Kas vadinama sukimosi kampu. Dizainas pagal profilį

Rastrinio vaizdo pasukimas kampais, kurie yra 90° kartotiniai, palyginti su vaizdo geometriniu centru, yra nereikšminga užduotis, kurią galima išspręsti neprarandant kokybės tiesiog transformuojant kiekvieno pikselio koordinates.

Žemiau mes apsvarstysime algoritmą, kaip tiksliai pasukti rastrinį vaizdą savavališku kampu, palyginti su savavališku centru su minimaliais nuostoliais.

Reiškiu dėkingumą Vladislavui Vladimirovičiui Charčenkai už suteiktą pagalbą.

Algoritmas

Iš aukščiau pateikto paveikslo matyti, kad pasukus rastrinį vaizdą, kiekvieno galutinio vaizdo pikselio spalva nustatoma pridedant kelių pradinio vaizdo pikselių „fragmentų“ spalvas, proporcingas atitinkamo vaizdo plotams. „fragmentai“. Todėl bendrai kalbant, mūsų problemos sprendimas bus surasti visų „fragmentų“ sritis kiekvienam pradinio vaizdo pikseliui ir surinkti kiekvieno galutinio vaizdo pikselio spalvą iš atitinkamų „fragmentų“ spalvų.

Kaip pradinio vaizdo pikselių modelį naudosime kvadratą, kurio kraštinė = 1, su tokiais kampų žymėjimais:
i1 - dešiniausias kampas;
i2 - žemiausias kampas;
i3 - kairysis kampas;
i4 yra viršutinis kampas.

Galutinis vaizdo modelis bus lygiagrečių horizontalių ir vertikalių linijų tinklelis, kurio atstumas tarp linijų = 1.

Rastrinio vaizdo sukimosi centro koordinatės šiame vaizde gali būti išreikštos kaip savavališkų realiųjų skaičių pora. Tai reiškia, kad mūsų uždavinyje sukimosi centras gali būti ne geometriniame pikselio centre ir ne tinklelio linijų susikirtimo taške, o savavališkame Dekarto koordinačių taške.

Kadangi pasukus rastrinį vaizdą, kiekvieno pikselio kvadratas pasukamas tuo pačiu kampu (to pikselio centro atžvilgiu), išspręsime vieno pikselio problemą, o gautą sprendimą pritaikysime kiekvienam originalo pikseliui. vaizdas.

Taškinės schemos pasukimas gali būti suskirstytas į dvi dalis:
1. Pasukite kiekvieno pradinio vaizdo pikselio kvadratą šio kvadrato centro atžvilgiu tam tikru kampu.
2. Pikselio kvadrato centro poslinkis pagal vaizdo pasukimo kampą vaizdo sukimosi centro atžvilgiu, kad kvadratas užimtų galutinę vietą galutinio vaizdo tinklelyje.
Tokiu atveju galutinio vaizdo tinklelis supjausto kiekvieno pradinio vaizdo pikselio kvadratą į 4, 5 arba 6 gabalus.

Norint susisteminti gautų variantų įvairovę, turėjau sukurti visų galimų pradinio vaizdo pikselių kvadrato sankirtos su galutinio vaizdo tinkleliu taksonomiją. Buvo tik 23 labai skirtingi variantai:


Sutarimai čia yra tokie:
- langeliuose esantys skaičiai nurodo pikselio kvadrato kampų skaičius, kurie po vaizdo pasukimo pateko į tam tikrą galutinio vaizdo tinklelio langelį;
- žalia spalva nurodo ląsteles, kuriose pateko pikselio dalys, ir garantuojama, kad ten paliks „skilteles“;
- geltona žymi ląsteles, į kurias, priklausomai nuo sąlygų, gali pataikyti (arba nepataikyti) pikselių kvadrato „fragmentai“, suformuoti ne kvadrato kampais, o kvadrato kraštinėmis.

Aiškumo dėlei pateiksiu vieną iš galimų varianto Nr.3 variantų:

Kaip matote, viršutiniame dešiniajame langelyje nėra pikselio „fragmento“, nors kitomis sukimosi sąlygomis jis galėtų turėti.
Kad neapsunkinčiau skaitytojo detaliais geometriniais skaičiavimais, iš karto pasakysiu, kad visose šiose 23-ose parinktyse pradinio vaizdo pikselis supjaustomas į „šukes“, kurių plotą nesunku apskaičiuoti sujungus 4 formules. . Žemiau pateikiamos šios formulės su iliustracijomis. Raudona spalva nurodo galutinio vaizdo tinklelio linijas, kurios perpjauna pikselių kvadratą. Plotas, kurio plotas apskaičiuojamas pagal formulę, yra geltonai.

Formulė 1
Ši formulė nenaudojama galutiniam „skeveldros“ plotui apskaičiuoti, tačiau ją patogu naudoti greitai apskaičiuojant pagalbines tarpines sritis, nes žinome, kad viso pikselio plotas = 1.
Iš kvadrato kampų nukritę aukščiai į galutinio vaizdo tinklelį naudojami kaip įvesties kintamieji visose formulėse dėl tos paprastos priežasties, kad apskaičiuojant šiuos aukščius reikia akimirksniu pasirinkti trupmeninę koordinatės skaitinės vertės dalį. atitinkamo pikselio kvadrato kampo.

Formulė 2

Ši formulė naudojama tik 1 ir 2 variantuose.

Formulė 3
Dažnai naudojama formulė – gerai, kad ji greitai apskaičiuojama. Kadangi kiekvieno pikselio sukimosi kampas yra vienodas, visas trigonometrines funkcijas galima apskaičiuoti vieną kartą, prieš apdorojant visus pikselius, ir tada naudoti šias reikšmes cikle kaip konstantas.

Formulė 4
Ši formulė apskaičiuojama dviem etapais. Pirmiausia įvertinama skliausteliuose esanti išraiška. Jei ji įgyja teigiamą reikšmę, tada apskaičiuojamas plotas. Jei reikšmė yra neigiama, tai reiškia, kad tinklelio kampo ir kvadrato kraštinės suformuota „drožlė“ nėra nupjauta nuo pikselio ir nėra prasmės atlikti tolesnius skaičiavimus.

Atsižvelgiant į visa tai, kas išdėstyta pirmiau, paprastai algoritmas atrodys taip:
1. Į kompiuterio atmintį įkelkite originalų vaizdą.
2. Apskaičiuokite galutinio vaizdo matmenis pikseliais.
3. Sukurkite tarpinį dvimatį masyvą, kurio kiekviename elemente yra 3 RGB spalvų komponentai slankiojo kablelio formatu. Masyvo matmenys yra lygūs galutinio vaizdo matmenims.
4. Paeiliui kartokite visus pradinio vaizdo pikselius; kiekvieną iš jų pasukame tam tikru kampu ir dedame į galutinio vaizdo tinklelį, apskaičiuodami 4 pikselio kvadrato kampų koordinates; suskirstome pikselį į 23 parinktis ir suskaičiuojame „fragmentų“ plotus; Gautų „skeveldrų“ spalvas pridedame prie atitinkamų tarpinio masyvo elementų proporcingai šių „skeveldrų“ plotui.
5. Apdoroję visus pradinio vaizdo pikselius, RGB reikšmes tarpiniame masyve suapvaliname iki kiekvieno elemento sveikojo skaičiaus ir pagal šias sveikųjų skaičių reikšmes sukuriame galutinį vaizdą BMP formatu.

Programa

Remiantis aukščiau pateiktu algoritmu, buvo parašyta programa, skirta „Windows“. Galima atsisiųsti „Object Pascal“ šaltinio kodus ir sukompiliuotą vykdomąjį failą.

Programos sąsaja.
Spustelėjus mygtuką „Atidaryti...“, atidaromas BMP failo pasirinkimo dialogo langas. Palaikomi tik taškai su 24 bitų palete. Atidarytas vaizdas rodomas lange. Lango pavadinime rodomas visas failo kelias ir vaizdo matmenys.

Lauke „Kampas“ nurodykite sukimosi kampą laipsniais – bet kurį teigiamą skaičių.
Įvedant trupmeninius skaičius kaip dešimtainį skyriklį galima naudoti tašką arba kablelį.

Radijo mygtukai „CW“ ir „CCW“ nustato sukimosi kryptį: atitinkamai „pagal laikrodžio rodyklę“ ir „prieš laikrodžio rodyklę“.

Bloke „Fono spalva“ galite nustatyti fono spalvą, su kuria bus maišomi vaizdo kraštinių pikseliai. Numatytoji fono spalva yra juoda.

Laukuose „Centras X“ ir „Centras Y“ nurodomos sukimosi centro koordinatės. Reikėtų atsižvelgti į tai, kad koordinačių pradžia yra viršutiniame kairiajame vaizdo kampe, o Y didėja žemyn. Pagal numatytuosius nustatymus sukimosi centras nustatytas į įkelto vaizdo geometrinį centrą.

Spustelėjus mygtuką „Pasukti“ arba paspaudus Enter klavišą, vaizdas pasukamas nurodytu kampu nurodyto sukimosi centro atžvilgiu ir rodomas lange. Vaizdo pasukimas kampais, kurie yra 90° kartotiniai, įgyvendinamas pagal supaprastintą schemą, tiesiog pakeičiant pradinio vaizdo pikselių koordinates, o „Centro X“ ir „Centro Y“ reikšmės nepaisomos.
Algoritmo veikimo laikas sekundėmis rodomas po mygtuku „Pasukti“.

Naudojant mygtuką „Išsaugoti...“, pasuktą vaizdą galima įrašyti į BMP failą.

Jei galutinis vaizdas netelpa į langą, jis priderinamas prie lango kraštų naudojant StretchBlt API funkciją – todėl realią didelių vaizdų kokybę galima įvertinti tik naudojant išsaugotą BMP failą.
Norint pasukti vaizdą kitu kampu, jo perkrauti nereikia – pasukamas vaizdas iš pasirinkto failo, o ne tas, kuris šiuo metu rodomas lange.

1024 x 768 matmenų vaizdas mašinoje su keturių branduolių 2,67 GHz procesoriumi ši programa pasuka savavališku kampu, vidutiniškai per maždaug 0,5 sekundės. 4000 x 4000 matmenų vaizdas – maždaug per 10 sekundžių. Algoritmo veikimo laikas skirtingais kampais gali skirtis dėl to, kad vaizdas skirtingais kampais suskaidomas į skirtingą skaičių „skeveldrų“, atitinkamai skiriasi bendras laikas, sugaištas skaičiuojant šių fragmentų plotus.

Tarpinis masyvas, kuriame yra informacija apie galutinio vaizdo pikselių spalvą slankiojo kablelio formatu, yra įdiegtas išplėstiniame tipe (10 baitų), todėl apdorojant didelius vaizdus (maždaug daugiau nei 5000 x 5000 pikselių) gali atsirasti atminties perpildymo klaida. Situaciją galima pagerinti naudojant ne tokį tikslų duomenų tipą ir išsaugant sveikąją skaičiaus dalį tiesiai į galutinį bitų grafiką, pagalbiniame masyve paliekant tik trupmeninę dalį.

Rezultatai

Atlikime lyginamąją Photoshop programoje įdiegto precizinio algoritmo ir vaizdo pasukimo algoritmo veikimo analizę.
1 testas
Pirmajam bandymui padariau labai paprastą vaizdą – horizontalią juodą 1 pikselio storio ir 10 pikselių ilgio liniją, nukrypusią nuo balto kvadrato, kurio matmenys 100 x 100 pikselių, centro:

Po to aš pasukau šį vaizdą taško su koordinatėmis (0, 0) atžvilgiu 3° pagal laikrodžio rodyklę. Taškas (0, 0) buvo pasirinktas, nes, remdamasis mano eksperimentais, „Photoshop“ pasuka vaizdą pagal šį tašką. Štai lyginamasis rezultatas (priartintas 24 kartus):

Tikslumo algoritmas

Photoshop 7.0.1

„Photoshop CS6“ (64 bitų)
„Photoshop“ algoritmas sukuria kontrastingesnį vaizdą, o tikslumo algoritmas šiek tiek „sulieja“ vaizdą. Tačiau apskritai, vizualiai įvertinus, rezultatas beveik toks pat. Praeidami pažymime, kad „Photoshop“ įdiegtas sukimosi algoritmas per 10 metų nepatyrė reikšmingų pokyčių.

2 testas
Antram bandymui pasirinkau Tulip iš standartinio Win7 platinimo:

Pasukus šį vaizdą 5° pagal laikrodžio rodyklę geometrinio centro atžvilgiu, susumavau visų pikselių spalvas pagal RGB kanalus. Štai tikslaus algoritmo ir „Photoshop“ algoritmo rezultatas:
Skaičiai skliausteliuose rodo absoliutų šio rodiklio nuokrypį nuo originalo.
Vaizdo spalva po precizinio pasukimo ir prieš apvalinimą praktiškai nepasikeitė – to ir reikėjo tikėtis.
Didžiausią nuokrypį šiuo konkrečiu atveju randame „Photoshop“ algoritmo G kanale. Procentais šis nuokrypis yra tik 0,06%, todėl jis nėra pastebimas „iš akies“, tačiau dėl perfekcionizmo „Photoshop“ rezultatas yra prastesnis nei tikslaus algoritmo.
Svarbu pažymėti, kad kiekvieno pikselio spalvos suapvalinimas tikslumo algoritme iki sveikojo skaičiaus reikšmės, reikalingos BMP formatui, negrįžtamai sunaikina dalį spalvų informacijos.

Norėdami vizualiai palyginti du algoritmus, pateiksiu padidintą vaizdo fragmentą,

Pasukta atitinkamai 5° pagal laikrodžio rodyklę, „Photoshop“:

Ir su tikslumo algoritmu:

Lyginamoji analizė rodo, kad „Photoshop“ geriau išsaugo kontrastingus vaizdo elementus, bet tuo pačiu sukuria iškreiptų spalvų „aureoles“. Tikslumo algoritmas neiškraipo spalvos, bet tuo pačiu kažkiek „sulieja“ vaizdą.

Išvados

1. Galimas tikslumas ir tuo pačiu gana greitas rastrinio vaizdo pasukimas savavališku kampu. Man lieka paslaptis, kodėl profesionalūs grafiniai redaktoriai neturi parinkties, leidžiančios vartotojui itin tiksliai pasukti vaizdą per šiek tiek daugiau laiko.

2. Nepaisant itin didelio nagrinėjamo algoritmo tikslumo, atvirkštinė vaizdo transformacija, t.y. Neįmanoma pasukti į priešingą kampą neprarandant kokybės, nes tikslios spalvos reikšmės apvalinimas (slankiojo kablelio formatu) negrįžtamai sunaikina dalį spalvos informacijos.

3. Vaizdinio kontrastingų detalių suvokimo požiūriu geriausią rezultatą duoda neoptimalus Photoshop algoritmas. Tikslumo algoritmą tikslinga naudoti tais atvejais, kai svarbu išsaugoti maksimalią informaciją apie vaizdo spalvą.

UPD: Praktiniam naudojimui parašiau programą, kuri įgyvendina supaprastintą algoritmą, kuriame kiekvienam galutinio vaizdo pikseliui paeiliui apskaičiuojami visi reikalingi pikselių gabalėliai pradiniame vaizde ir iškart įvyksta spalvų apvalinimas. Tik po to apskaičiuojamas kitas galutinio vaizdo pikselis. Tokiu atveju programa kelis kartus pasiekia vieną šaltinio vaizdo pikselį. Taigi skaičiavimo laikas vidutiniškai pailgėjo 1,7 karto, tačiau atmintis šioje algoritmo versijoje išleidžiama tik bitmaps saugojimui, o tai leidžia dirbti su didelio dydžio vaizdais. Galite atsisiųsti programą ir šaltinius


Svarbi trigonometrijos sąvoka yra sukimosi kampas. Žemiau mes nuosekliai pateiksime posūkio idėją ir pristatysime visas susijusias sąvokas. Pradėkime nuo bendros posūkio idėjos, tarkime, visiško apsisukimo. Toliau pereikime prie sukimosi kampo sąvokos ir apsvarstykime pagrindines jo charakteristikas, tokias kaip sukimosi kryptis ir dydis. Galiausiai pateikiame figūros sukimosi aplink tašką apibrėžimą. Visą teoriją pateiksime tekste su aiškinamaisiais pavyzdžiais ir grafinėmis iliustracijomis.

Puslapio naršymas.

Kas vadinama taško sukimu aplink tašką?

Iš karto atkreipkime dėmesį, kad kartu su fraze „sukimas aplink tašką“ taip pat naudosime frazes „sukimas apie tašką“ ir „sukimas apie tašką“, kurios reiškia tą patį.

Supažindinkime taško pasukimo aplink tašką samprata.

Pirma, apibrėžkime sukimosi centrą.

Apibrėžimas.

Taškas, apie kurį atliekamas sukimas, vadinamas sukimosi centras.

Dabar pasakykime, kas atsitiks sukant tašką.

Sukant tam tikrą tašką A sukimosi centro O atžvilgiu, gaunamas taškas A 1 (kuris tam tikro skaičiaus atveju gali sutapti su A), o taškas A 1 yra ant apskritimo su centras spindulio OA taške O. Kitaip tariant, pasuktas taško O atžvilgiu, taškas A eina į tašką A 1, esantį ant apskritimo, kurio centras yra taške O, kurio spindulys OA.

Manoma, kad taškas O, apsisukdamas pats, virsta savimi. Tai yra, dėl sukimosi aplink sukimosi centrą O taškas O virsta savimi.

Taip pat verta paminėti, kad taško A sukimasis aplink tašką O turėtų būti laikomas poslinkiu, atsirandančiu dėl taško A judėjimo apskritimu, kurio centras yra taške O, kurio spindulys OA.

Aiškumo dėlei pateiksime taško A sukimosi aplink tašką O iliustraciją, rodykle parodysime taško A judėjimą į tašką A 1.

Pilnas apsisukimas

Galima pasukti tašką A sukimosi centro O atžvilgiu taip, kad taškas A, perėjęs visus apskritimo taškus, būtų toje pačioje vietoje. Šiuo atveju jie sako, kad taškas A pajudėjo aplink tašką O.

Pateiksime grafinę visiškos revoliucijos iliustraciją.

Jei nesustosite ties vienu apsisukimu, o toliau judėsite tašką aplink apskritimą, tuomet galėsite atlikti du, tris ir tt pilnus apsisukimus. Žemiau esančiame brėžinyje parodyta, kaip galima padaryti du pilnus apsisukimus dešinėje ir tris kairėje.


Sukimosi kampo koncepcija

Iš pirmoje pastraipoje pateiktos taško pasukimo sąvokos aišku, kad yra begalė galimybių pasukti tašką A aplink tašką O. Iš tiesų, bet kuris apskritimo taškas, kurio centras yra taške O, kurio spindulys OA, gali būti laikomas tašku A 1, gautu sukant tašką A. Todėl, norėdami atskirti vieną posūkį nuo kito, pristatome sukimosi kampo samprata.

Viena iš sukimosi kampo charakteristikų yra sukimosi kryptis. Sukimosi kryptis lemia, kaip taškas sukamas – pagal laikrodžio rodyklę ar prieš laikrodžio rodyklę.

Dar viena sukimosi kampo savybė yra jos dydžio. Sukimosi kampai matuojami tais pačiais vienetais, kaip: dažniausiai naudojami laipsniai ir radianai. Čia verta paminėti, kad sukimosi kampas gali būti išreikštas laipsniais bet kokiu realiu skaičiumi nuo minus begalybės iki plius begalybės, priešingai nei geometrijoje, kurios vertė laipsniais yra teigiama ir neviršija 180.

Mažosios graikų abėcėlės raidės dažniausiai vartojamos pasukimo kampams žymėti: t.t. Norint pažymėti daug sukimosi kampų, dažnai naudojama viena raidė su apatiniais indeksais, pavyzdžiui, .

Dabar pakalbėkime apie sukimosi kampo ypatybes išsamiau ir tvarka.

Sukimo kryptis

Tegu taškai A ir A 1 pažymėti apskritime, kurio centras yra taške O. Galite patekti į tašką A 1 iš taško A sukdami aplink centrą O pagal laikrodžio rodyklę arba prieš laikrodžio rodyklę. Logiška šiuos posūkius laikyti skirtingais.

Pavaizduokime sukimus teigiama ir neigiama kryptimis. Žemiau esančiame brėžinyje pavaizduotas sukimasis teigiama kryptimi kairėje, o neigiama kryptimi dešinėje.

Sukimosi kampo reikšmė, savavališkos vertės kampas

Kitokio nei sukimosi centro sukimosi kampas visiškai nustatomas nurodant jo dydį, kita vertus, pagal sukimosi kampo dydį galima spręsti, kaip šis sukimasis buvo atliktas.

Kaip minėjome aukščiau, sukimosi kampas laipsniais išreiškiamas skaičiumi nuo −∞ iki +∞. Šiuo atveju pliuso ženklas atitinka sukimąsi pagal laikrodžio rodyklę, o minuso ženklas – sukimąsi prieš laikrodžio rodyklę.

Dabar belieka nustatyti atitiktį tarp sukimosi kampo vertės ir sukimosi, kurį jis atitinka.

Pradėkime nuo nulio laipsnių sukimosi kampo. Šis sukimosi kampas atitinka taško A judėjimą link savęs. Kitaip tariant, pasukus 0 laipsnių aplink tašką O, taškas A lieka vietoje.

Mes pereiname prie taško A sukimosi aplink tašką O, kuriame sukimasis vyksta per pusę apsisukimo. Darysime prielaidą, kad taškas A eina į tašką A 1. Šiuo atveju kampo AOA 1 absoliuti vertė laipsniais neviršija 180. Jei sukimas įvyko teigiama kryptimi, tada posūkio kampo vertė laikoma lygia kampo reikšmei AOA 1, o jei sukimas įvyko neigiama kryptimi, tada jo vertė laikoma lygi kampo reikšmei. AOA 1 su minuso ženklu. Pavyzdžiui, čia yra 30, 180 ir –150 laipsnių sukimosi kampai.


Didesni nei 180 laipsnių ir mažesni nei –180 laipsnių sukimosi kampai nustatomi remiantis šiais gana akivaizdžiais dalykais nuoseklių posūkių savybės: keli nuoseklūs taško A apsisukimai aplink centrą O yra lygiaverčiai vienam apsisukimui, kurio dydis lygus šių sukimų dydžių sumai.

Pateiksime pavyzdį, iliustruojantį šią savybę. Pasukime tašką A taško O atžvilgiu 45 laipsniais, tada pasukime šį tašką 60 laipsnių, po to šį tašką pasukime –35 laipsniais. Šių posūkių tarpinius taškus pažymėkime A 1, A 2 ir A 3. Į tą patį tašką A 3 galėtume patekti atlikę vieną taško A pasukimą 45+60+(−35)=70 laipsnių kampu.

Taigi, pasukimo kampus, didesnius nei 180 laipsnių, pavaizduosime kaip kelis posūkius iš eilės kampais, kurių suma suteikia pradinio sukimosi kampo reikšmę. Pavyzdžiui, 279 laipsnių sukimosi kampas atitinka nuoseklius 180 ir 99 laipsnių arba 90, 90, 90 ir 9 laipsnių, arba 180, 180 ir –81 laipsnių, arba 279 nuoseklius 1 laipsnio apsisukimus.

Panašiai nustatomi ir mažesni nei –180 laipsnių sukimosi kampai. Pavyzdžiui, –520 laipsnių sukimosi kampas gali būti interpretuojamas kaip nuoseklus taško pasukimas –180, –180 ir –160 laipsnių.

Apibendrinkime. Nustatėme sukimosi kampą, kurio reikšmė laipsniais išreiškiama kokiu nors realiu skaičiumi iš intervalo nuo −∞ iki +∞. Trigonometrijoje dirbsime būtent su sukimosi kampais, nors žodis „sukimas“ dažnai praleidžiamas ir jie tiesiog sakomi „kampas“. Taigi trigonometrijoje dirbsime su savavališko dydžio kampais, o tai reiškia sukimosi kampus.

Apibendrinant šį klausimą, pažymime, kad visas sukimasis teigiama kryptimi atitinka 360 laipsnių (arba 2 π radianų) sukimosi kampą, o neigiama kryptimi - –360 laipsnių (arba –2 π rad) sukimosi kampą. . Šiuo atveju patogu didelius sukimosi kampus pavaizduoti kaip tam tikrą pilnų apsisukimų skaičių ir kitą pasukimą kampu nuo –180 iki 180 laipsnių. Pavyzdžiui, paimkime 1340 laipsnių sukimosi kampą. Nesunku įsivaizduoti 1340 kaip 360·4+(−100) . Tai yra, pradinis sukimosi kampas atitinka 4 pilnus apsisukimus teigiama kryptimi ir vėlesnį –100 laipsnių sukimąsi. Kitas pavyzdys: –745 laipsnių sukimosi kampas gali būti interpretuojamas kaip du apsisukimai prieš laikrodžio rodyklę, po kurio seka –25 laipsnių pasukimas, nes –745=(-360) 2+(-25) .

Pasukite figūrą aplink tašką kampu

Taško posūkio sąvoka lengvai išplečiama iki pasukite bet kokią formą aplink tašką kampu(kalbame apie tokį sukimąsi, kad ir taškas, apie kurį sukamas, ir pasukama figūra yra toje pačioje plokštumoje).

Figūros sukimas reiškia visų figūros taškų pasukimą aplink duotą tašką tam tikru kampu.

Kaip pavyzdį iliustruojame tokį veiksmą: pasukite atkarpą AB kampu taško O atžvilgiu, ši atkarpa pasukta pateks į atkarpą A 1 B 1.

Nuorodos.

  • Algebra: Vadovėlis 9 klasei. vid. mokykla/Yu. N. Makaryčiovas, N. G. Mindjukas, K. I. Neškovas, S. B. Suvorova; Red. S. A. Telyakovsky.- M.: Išsilavinimas, 1990.- 272 p.: iliustr.- isbn 5-09-002727-7
  • Bašmakovas M. I. Algebra ir analizės pradžia: vadovėlis. 10-11 klasėms. vid. mokykla – 3 leidimas. - M.: Išsilavinimas, 1993. - 351 p.: iliustr. - ISBN 5-09-004617-4.
  • Algebra ir analizės pradžia: Proc. 10-11 klasėms. bendrojo išsilavinimo institucijos / A. N. Kolmogorov, A. M. Abramov, Yu P. Dudnitsyn ir kt. Red. A. N. Kolmogorovas - 14 leidimas - M.: Išsilavinimas, 2004. - 384 p.: ISBN 5-09-013651-3.
  • Gusevas V. A., Mordkovičius A. G. Matematika (vadovas stojantiems į technikos mokyklas): Proc. pašalpa.- M.; Aukščiau mokykla, 1984.-351 p., iliustr.

ĮVADAS. PROBLEMOS PAREIŠKIMAS.

1. VAIZDO SUKIMO ALGORITMO APRAŠYMAS

2. TAIKYMO KŪRIMAS C# PROGRAMAVIMO KALBA

2.1 Programos aprašymas

2.2 Programos testavimas

IŠVADA

NAUDOTŲ ŠALTINIŲ SĄRAŠAS

A PRIEDAS

ĮVADAS. PROBLEMOS PAREIŠKIMAS

Atliekant disciplinos „Vaizdų gavimas ir apdorojimas“ tyrimą, kaip testą, buvo iškelta užduotis aprašyti algoritmą ir įgyvendinti vaizdo pasukimo aplink centrą vartotojo nurodytu kampu funkciją. Vieną kartą apskaičiuokite kampo kosinusą ir sinusą. Savavališkai nustatykite visus pradinius parametrus ir patikrinkite, ar jie atitinka priimtinų verčių diapazoną.

1 . Vaizdo pasukimo algoritmo aprašymas

Norėdami pasukti vaizdą kampu, nurodytu laipsniais, naudokite privačią Bitmap RotateImage (Bitmap Image, int kampas) funkciją.

Įvesties parametrai:

Bitmap Image – vaizdas pasukamas;

int kampas – sukimosi kampas laipsniais.

Funkcija grąžina vaizdą, pasuktą nurodytu kampu.

Funkcijos algoritmas:

1) Įvestis yra vaizdas ir sukimosi kampas laipsniais;

2) Apskaičiuokite sukimosi kampo sinusus ir kosinusus (vieną kartą). Sukimosi kampas nurodomas radianais;

3) Apskaičiuokite naują vaizdo plotį ir aukštį naudodami apskaičiuotą sukimosi kampo sinusą ir kosinusą;

4) Taškinio šaudymo galerijos struktūrų masyvo inicijavimas (Taškas = naujas taškas), apibrėžiantis lygiagretainį.

5) Atsižvelgiant į sukimosi kampą (kuriame ketvirtyje jis yra radianais), apskaičiuojamos trijų taškų koordinatės, kad būtų sukurtas naujas vaizdas. Koordinatės apskaičiuojamos remiantis šio algoritmo (3) punktu (naujas plotis ir aukštis – taškų X ir Y koordinačių perskaičiavimas);

6) Pasukto vaizdo braižymas naudojant tris taškus (viršutinis kairysis, viršutinis dešinysis ir apatinis kairysis lygiagretainio kampai. Ketvirtasis taškas ekstrapoliuojamas remiantis pirmaisiais trimis).

g.DrawImage(Vaizdas, taškai); - piešimo funkcija.

7) Grąžinkite pasuktą vaizdą, kad galėtumėte naudoti ne šiai funkcijai.

Vaizdo centravimą atlieka elemento ypatybė pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;

2 . TAIKYMO KŪRIMAS C# PROGRAMAVIMO KALBA

Vaizdų apdorojimo programos kūrimo įrankiu pasirinkta MS Visual Studio 2012 programavimo kalba. Šis įrankių rinkinys suteikia pakankamai galimybių dirbti su grafika.

Pagal užduotį buvo sukurta aplikacija.

2. 1 Programos aprašymas

pasukti vaizdo kampo diapazoną

Programa yra pagrįsta frmRotationForm klase.

Ši klasė įgyvendina šiuos metodus:

Privatus void btnRotateImage_Click(objekto siuntėjas, EventArgs e) metodas tvarko spustelėjus mygtuką „Pasukti vaizdą“. Paspaudus teksto lauko turinį bandoma konvertuoti į skaičių (vėliau naudoti kaip ang kintamąjį, kuris skirtas saugoti sukimosi kampą laipsniais). Šis metodas taip pat tvarko išimtis ir paleidžia funkciją RotateImage, kuri pasuka vaizdą.

Privatus Bitmap RotateImage (Bitmap Image, int kampas) metodas pasuka vaizdą nurodytu kampu. Grąžina pasuktą vaizdą.

Privatus void btnLoadImage_Click(objekto siuntėjas, EventArgs e) metodas įkelia vaizdą iš disko į PictureBox su pradiniu vaizdu.

Privatus void timer1_Tick(objekto siuntėjas, EventArgs e) metodas vykdomas kiekvienam laikmačio žymėjimui. Šioje programoje dažnis nustatytas į 50 milisekundžių (kad animacijos režimu veiktų sklandžiau).

2. 2 Taikymo testavimas

Sukurta programa buvo išbandyta Microsoft Windows 7 64 bitų operacinėje sistemoje su įdiegta .NET Framework 4.5. Vykdomojo failo Image_Rotation.exe paleidimo rezultatas parodytas 2.1 pav.

2.1 pav. Programos langas paleidžiant

Kai paleidžiu programą, numatytasis vaizdas, kurį pasirinkau, yra „laidinis“. Jį galite pakeisti spustelėdami mygtuką „Įkelti vaizdą“. Savo atvaizdo pasirinkimo rezultatas pateiktas 2.2 pav.

2.2 pav. Savo vaizdo pasirinkimas pasukimui

Tolesni veiksmai aptariami numatytame paveikslėlyje. Pasirinkę pasukimo kampą atitinkamame teksto laukelyje viršutiniame kairiajame formos kampe, spustelėkite mygtuką „pasukti vaizdą“. (žr. 2.3 pav.).

2.3 pav. Vaizdo pasukimo 8 laipsniais rezultatas

Paveiksle aprašyti stačiakampiai yra pagalbinis įrankis, jie rodomi jūsų patogumui ir rodo vaizdo centrą.

Programa įgyvendina „apsaugą nuo kvailių“, būtent: jei bandote įvesti kampą, didesnį nei 360 laipsnių arba mažesnį nei -360 laipsnių, taip pat tekstą, rodomas įspėjimas ir vaizdas nebus apdorotas:

2.4 pav. – Bandymas pasukti vaizdą -361 laipsniu

Programoje įdiegta galimybė „animuoti sukimąsi“ pagal laikrodžio rodyklę / prieš laikrodžio rodyklę, taip pat „didinti“ (padidinti paveikslėlį, kad jis tilptų į „PictureBox“ konteinerį).

2.5 pav. Animuotas sukimas

IŠVADA

Bandymo techninėse specifikacijose nustatyta užduotis įvykdyta.

Studijavo vaizdo apdorojimo būdus naudojant C# programavimo kalbą.

Programos šaltinio kodas pateiktas A priede.

NAUDOTŲ ŠALTINIŲ SĄRAŠAS

1 Starovoitovas V.V. Skaitmeniniai vaizdai: nuo gavimo iki

apdorojimas / V.V. Starovoitovas, Yu.I. Golub - Minskas: Baltarusijos OIPI NAS, 2014. - 202 p. - ISBN 978-985-6744-80-1.

2 Christian Nagel, Bill Ivien ir kiti.

3 Programų kūrimas Microsoft platformoje. MSDN [elektroninis išteklius]: http://msdn.microsoft.com/ru-ru/library/4f9s3at1(v=vs.110).aspx. - Priėjimo data: 2014-10-25.

A PRIEDAS

Klasės „frmRotationForm“ sąrašas

naudojant System.Collections.Generic;

naudojant System.ComponentModel;

naudojant System.Data;

naudojant System.Drawing;

naudojant System.Linq;

naudojant System.Text;

naudojant System.Threading.Tasks;

naudojant System.Windows.Forms;

naudojant System.Drawing.Drawing2D;

vardų erdvė Image_Rotation

viešoji dalinė klasė frmRotationForm: Forma

privatus int jj;//kampas laipsniais

vieša frmRotationForm()

InitializeComponent();

w.Text = pictureBox3.Image.Width.ToString();

h.Text = pictureBox3.Image.Height.ToString();

jj = Convert.ToInt32(textBox1.Text);

private void btnRotateImage_Click(objekto siuntėjas, EventArgs e)

ang = Convert.ToInt32(textBox1.Text);

jei (ang< -360 || ang > 360)

sugauti (išimtis, išskyrus)

MessageBox.Show("Leidžiami kampai nuo 0 iki 360. \nŽenklui \"-\" leidžiama suktis prieš laikrodžio rodyklę.");

Bitmap i = new Bitmap(pictureBox1.Image);

pictureBox1.Image = this.RotateImage(i, ang);

//this.Controls.Add(pictureBox1);

privatus bitmap RotateImage (Bitmap vaizdas, vidinis kampas)

var pi2 = Math.PI/2;//PI po du

int oldWidth = Vaizdas.Plotis;

int oldHeight = Vaizdas.Aukštis;

var teta = kampas * Math.PI / 180.0 //konvertuoti į radianus

var locked_theta = teta;

if (užrakintas_teta< 0.0) locked_theta += 2 * Math.PI;

dvigubas naujasPlotis, naujas Aukštis;

int nPlotis, nAukštis;

double gretimasViršus, priešingasViršus;

double gretimasApačia, priešingaBottom;

#region Apskaičiuokite naują plotį ir aukštį

double SINUS = Math.Abs(Math.Sin(locked_theta));

double COSINUS = Math.Abs(Math.Cos(locked_theta));

if ((užrakintas_teta >= 0,0 && užrakintas_teta< pi2) || (locked_theta >= Math.PI && locked_theta< (Math.PI + pi2)))

(// Kampas (>= 0 ir< Pi/2) или (>= PI ir< ПИ + Пи/2)

šalia viršus = COSINUS * oldWidth;

PriešingaTop = SINUSAS * oldWidth;

gretimasBottom = COSINUS * oldAukštis;

PriešingaBottom = SINUSAS * oldAukštis;

gretimasViršus = SINUSAS * oldAukštis;

PriešingaTop = COSINUS * oldAukštis;

nextBottom = SINUS * oldWidth;

PriešingaBottom = COSINUS * oldWidth;

newWidth = gretimasViršus + priešingaApačia;

newHeigth = gretimasApačia + priešingaViršus;

nWidth = (int)(Math.Ceiling(newWidth));//apvalinti iki sveikųjų skaičių

nAukštis = (int)(Math.Ceiling(newHeigth));

#endregion Apskaičiuokite naują plotį ir aukštį

Bitmap rotatedBmp = new Bitmap(nWidth,nHeigth);

Grafika g = Graphics.FromImage(rotatedBmp);

Taškiniai taškai = naujas Taškas ;//3 taško tipo struktūrų masyvas, apibrėžiantis lygiagretainį

//Trys taškai žymi: viršutinį kairįjį, viršutinį dešinįjį, apatinį kairįjį lygiagretainio kampus.

//Ketvirtasis taškas ekstrapoliuojamas iš pirmųjų trijų

//atskaitos taškas (0,0) - viršutinis kairysis kampas

if (užrakintas_teta >= 0,0 && užrakintas_teta< pi2) //90

taškai = new Taškas((int)priešaisBottom, 0);

else if (locked_theta >= pi2 && locked_theta< Math.PI) //90-180

taškai = naujas Taškas(nPlotis, (int)(priešaisViršus));

else if (locked_theta >= Math.PI && locked_theta< (Math.PI + pi2))//180-270

taškai = naujas Taškas((int)(greta esantisViršus), nAukštis);

taškai = new Point(0, (int)(greta apačia));

taškai = naujas Taškas(nPlotis, (int)(priešaisViršus));

taškai = new Point(0, (int)(greta apačia));

taškai = new Taškas((int)(priešais apačioje), 0);

taškai = naujas Taškas((int)(greta esantisViršus), nAukštis);

label6.Text = "Centras ORIGINALUS x="+ (oldWidth / 2.0f).ToString() + ", y=" + (oldAukštis / 2.0f).ToString();

label7.Text = "Centras ROTATE x=" + (nWidth / 2.0f).ToString() + ", y=" + (nAukštis / 2.0f).ToString();

g.DrawImage(Vaizdas, taškai);

g.DrawStačiakampis(naujas rašiklis(spalva.raudona, 0.1f),naujas stačiakampis(0,0,nplotis/2,naukštis/2));

g.DrawStačiakampis(naujas rašiklis(spalva.raudona, 0,1f), naujas stačiakampis(nplotis/2, naukštis/2, n plotis/2-1, n aukštis/2-1));

Vaizdas.Dispose();

return rotatedBmp;

private void btnLoadImage_Click(objekto siuntėjas, EventArgs e)

OpenFileDialog dlg = naujas OpenFileDialog();

dlg.Title = "Atidaryti vaizdą";!}

dlg.Filter = "jpg failai (*.jpg)|*.jpg|Visi failai (*.*)|*.*";

if (dlg.ShowDialog() == DialogResult.OK)

pictureBox3.Image = naujas Bitmap(dlg.OpenFile());

pictureBox1.Image = pictureBox3.Image;

w.Text = pictureBox1.Image.Width.ToString();

h.Text = pictureBox1.Image.Height.ToString();

private void timer1_Tick(objekto siuntėjas, EventArgs e)

jei (2 žymimasis langelis. Pažymėta)

(//pakeiskite pkcherbox režimą į ZOOM

pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;

//jei nepažymėta, vaizdas yra centre

pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;

jei (1 žymimasis langelis. Pažymėta)

(//"animacijos" įgyvendinimas - paveikslėlio sukimas aplink savo ašį pagal laikrodžio rodyklę/prieš laikrodžio rodyklę

radioButton1.Visible = tiesa;

radioButton2.Visible = tiesa;

jei (radioButton1.Checked)

( // pagal laikrodžio rodyklę

this.textBox1.Text = jj++.ToString();

jei (jj == 360) jj = 0;

(//prieš laikrodžio rodyklę

this.btnRotateImage_Click(this, e);

this.textBox1.Text = jj--.ToString();

jei (jj == 0) jj = 359;

radioButton1.Visible = klaidinga;

radioButton2.Visible = false;

Panašūs dokumentai

    Vaizdo triukšmo filtravimas. Jo binarizacijos ir pasukimo algoritmai. Informacinių natų atpažinimo požymių formavimas. Programinės įrangos schema. Programoje įdiegtų klasių, funkcijų, metodų aprašymas. Taikymo testavimas.

    kursinis darbas, pridėtas 2013-12-17

    Informacija apie grafinius formatus. Vaizdo saugojimas programoje. Eilė kaip pagalbinė duomenų struktūra. Vaizdo įkėlimas iš dvejetainio failo. Operacijos su vaizdais. Rezoliucijos sumažėjimas. Padidinkite vaizdo dydį.

    kursinis darbas, pridėtas 2013-06-29

    Programos, skirtos pustonių vaizdui suspausti arba suspausti naudojant tarptautinį JPEG standartą, kūrimas. JPEG metodo aprašymas, rezultatų išvedimas dekoduoto vaizdo pavidalu. Pustonių vaizdo glaudinimo metodų apžvalga.

    kursinis darbas, pridėtas 2012-10-14

    Bendras dviejų vaizdų palyginimo algoritmas. Didžiausio ploto metodas. Histogramos metodas. Vaizdo paruošimas atpažinimui. Daugiamatės funkcijos modeliavimas. Vektorių pasiskirstymas. Deformuojami modeliai. Programinės įrangos diegimas.

    baigiamasis darbas, pridėtas 2008-09-29

    Animacinio animacinio filmo veikėjo „Mikė Pūkuotukas“ GIF vaizdo kūrimo etapų aprašymas „Adobe Photoshop CS6“. Sukurti pasikartojančio vaizdo sluoksnį ir paruošti kadrus GIF animacijai. Tinkinkite animacijos efektus ir gaukite GIF failą.

    laboratorinis darbas, pridėtas 2015-03-05

    Programos, kurios tikslas yra paversti nespalvotus pustonių vaizdus į spalvotus, kūrimas. Vaizdo apdorojimo technikų apžvalga, vaizdo transformavimo metodai naudojant neuroninį tinklą. Spalvų erdvių klasterizacijos aprašymai.

    baigiamasis darbas, pridėtas 2012-06-17

    Judėjimo parametrų nustatymas sukimosi metu, greičio, pagreičio, laiko priklausomybė nuo sukimosi kampo, sukimosi laiko nustatymas tam tikru kampu. Sukurto matematinio modelio taikymas kūno judėjimo parametrams skaičiuoti.

    kursinis darbas, pridėtas 2010-03-18

    Kompiuterinė grafika. Pikseliai, raiška, vaizdo dydis. Vaizdų tipai. Juodos ir baltos linijos ir pustonių vaizdai. Indeksuotos spalvos. Pilnų spalvų vaizdai. Failų formatai. Spalva ir jos modeliai. Spalvų modeliai: RGB, CMYK, HSB.

    santrauka, pridėta 2009-02-20

    Vaizdo kodavimo metodai: trukmės kodavimas, nuo dažnio priklausomas kodavimas, Lempel-Ziv metodas. Linijos dydis 16 bitų spalva. Apskaičiuokite viso originalaus vaizdo dydį. Aukštos kokybės ir žemos kokybės vaizdo glaudinimo pavyzdžiai.

    pristatymas, pridėtas 2013-10-22

    Adobe Photoshop programos sąsaja. Vaizdo pakeitimų atlikimas. Atspalvių keitimo ir vaizdų iškraipymo įrankiai. Vaizdo formavimo seka. Vaizdų tonų ir spalvų korekcija, darbas su filtrais ir funkcijomis.

Rastrinio vaizdo pasukimas kampais, kurie yra 90° kartotiniai, palyginti su vaizdo geometriniu centru, yra nereikšminga užduotis, kurią galima išspręsti neprarandant kokybės tiesiog transformuojant kiekvieno pikselio koordinates.

Žemiau mes apsvarstysime algoritmą, kaip tiksliai pasukti rastrinį vaizdą savavališku kampu, palyginti su savavališku centru su minimaliais nuostoliais.

Reiškiu dėkingumą Vladislavui Vladimirovičiui Charčenkai už suteiktą pagalbą.

Algoritmas

Iš aukščiau pateikto paveikslo matyti, kad pasukus rastrinį vaizdą, kiekvieno galutinio vaizdo pikselio spalva nustatoma pridedant kelių pradinio vaizdo pikselių „fragmentų“ spalvas, proporcingas atitinkamo vaizdo plotams. „fragmentai“. Todėl bendrai kalbant, mūsų problemos sprendimas bus surasti visų „fragmentų“ sritis kiekvienam pradinio vaizdo pikseliui ir surinkti kiekvieno galutinio vaizdo pikselio spalvą iš atitinkamų „fragmentų“ spalvų.

Kaip pradinio vaizdo pikselių modelį naudosime kvadratą, kurio kraštinė = 1, su tokiais kampų žymėjimais:
i1 - dešiniausias kampas;
i2 - žemiausias kampas;
i3 - kairysis kampas;
i4 yra viršutinis kampas.

Galutinis vaizdo modelis bus lygiagrečių horizontalių ir vertikalių linijų tinklelis, kurio atstumas tarp linijų = 1.

Rastrinio vaizdo sukimosi centro koordinatės šiame vaizde gali būti išreikštos kaip savavališkų realiųjų skaičių pora. Tai reiškia, kad mūsų uždavinyje sukimosi centras gali būti ne geometriniame pikselio centre ir ne tinklelio linijų susikirtimo taške, o savavališkame Dekarto koordinačių taške.

Kadangi pasukus rastrinį vaizdą, kiekvieno pikselio kvadratas pasukamas tuo pačiu kampu (to pikselio centro atžvilgiu), išspręsime vieno pikselio problemą, o gautą sprendimą pritaikysime kiekvienam originalo pikseliui. vaizdas.

Taškinės schemos pasukimas gali būti suskirstytas į dvi dalis:
1. Pasukite kiekvieno pradinio vaizdo pikselio kvadratą šio kvadrato centro atžvilgiu tam tikru kampu.
2. Pikselio kvadrato centro poslinkis pagal vaizdo pasukimo kampą vaizdo sukimosi centro atžvilgiu, kad kvadratas užimtų galutinę vietą galutinio vaizdo tinklelyje.
Tokiu atveju galutinio vaizdo tinklelis supjausto kiekvieno pradinio vaizdo pikselio kvadratą į 4, 5 arba 6 gabalus.

Norint susisteminti gautų variantų įvairovę, turėjau sukurti visų galimų pradinio vaizdo pikselių kvadrato sankirtos su galutinio vaizdo tinkleliu taksonomiją. Buvo tik 23 labai skirtingi variantai:



Sutarimai čia yra tokie:
- langeliuose esantys skaičiai nurodo pikselio kvadrato kampų skaičius, kurie po vaizdo pasukimo pateko į tam tikrą galutinio vaizdo tinklelio langelį;
- žalia spalva nurodo ląsteles, kuriose pateko pikselio dalys, ir garantuojama, kad ten paliks „skilteles“;
- geltona žymi ląsteles, į kurias, priklausomai nuo sąlygų, gali pataikyti (arba nepataikyti) pikselių kvadrato „fragmentai“, suformuoti ne kvadrato kampais, o kvadrato kraštinėmis.

Aiškumo dėlei pateiksiu vieną iš galimų varianto Nr.3 variantų:

Kaip matote, viršutiniame dešiniajame langelyje nėra pikselio „fragmento“, nors kitomis sukimosi sąlygomis jis galėtų turėti.
Kad neapsunkinčiau skaitytojo detaliais geometriniais skaičiavimais, iš karto pasakysiu, kad visose šiose 23-ose parinktyse pradinio vaizdo pikselis supjaustomas į „šukes“, kurių plotą nesunku apskaičiuoti sujungus 4 formules. . Žemiau pateikiamos šios formulės su iliustracijomis. Raudona spalva nurodo galutinio vaizdo tinklelio linijas, kurios perpjauna pikselių kvadratą. Plotas, kurio plotas apskaičiuojamas pagal formulę, yra geltonai.

Formulė 1

Ši formulė nenaudojama galutiniam „skeveldros“ plotui apskaičiuoti, tačiau ją patogu naudoti greitai apskaičiuojant pagalbines tarpines sritis, nes žinome, kad viso pikselio plotas = 1.
Iš kvadrato kampų nukritę aukščiai į galutinio vaizdo tinklelį naudojami kaip įvesties kintamieji visose formulėse dėl tos paprastos priežasties, kad apskaičiuojant šiuos aukščius reikia akimirksniu pasirinkti trupmeninę koordinatės skaitinės vertės dalį. atitinkamo pikselio kvadrato kampo.

Formulė 2


Ši formulė naudojama tik 1 ir 2 variantuose.

Formulė 3

Dažnai naudojama formulė – gerai, kad ji greitai apskaičiuojama. Kadangi kiekvieno pikselio sukimosi kampas yra vienodas, visas trigonometrines funkcijas galima apskaičiuoti vieną kartą, prieš apdorojant visus pikselius, ir tada naudoti šias reikšmes cikle kaip konstantas.

Formulė 4

Ši formulė apskaičiuojama dviem etapais. Pirmiausia įvertinama skliausteliuose esanti išraiška. Jei ji įgyja teigiamą reikšmę, tada apskaičiuojamas plotas. Jei reikšmė yra neigiama, tai reiškia, kad tinklelio kampo ir kvadrato kraštinės suformuota „drožlė“ nėra nupjauta nuo pikselio ir nėra prasmės atlikti tolesnius skaičiavimus.

Atsižvelgiant į visa tai, kas išdėstyta pirmiau, paprastai algoritmas atrodys taip:
1. Į kompiuterio atmintį įkelkite originalų vaizdą.
2. Apskaičiuokite galutinio vaizdo matmenis pikseliais.
3. Sukurkite tarpinį dvimatį masyvą, kurio kiekviename elemente yra 3 RGB spalvų komponentai slankiojo kablelio formatu. Masyvo matmenys yra lygūs galutinio vaizdo matmenims.
4. Paeiliui kartokite visus pradinio vaizdo pikselius; kiekvieną iš jų pasukame tam tikru kampu ir dedame į galutinio vaizdo tinklelį, apskaičiuodami 4 pikselio kvadrato kampų koordinates; suskirstome pikselį į 23 parinktis ir suskaičiuojame „fragmentų“ plotus; Gautų „skeveldrų“ spalvas pridedame prie atitinkamų tarpinio masyvo elementų proporcingai šių „skeveldrų“ plotui.
5. Apdoroję visus pradinio vaizdo pikselius, RGB reikšmes tarpiniame masyve suapvaliname iki kiekvieno elemento sveikojo skaičiaus ir pagal šias sveikųjų skaičių reikšmes sukuriame galutinį vaizdą BMP formatu.

Programa

Remiantis aukščiau pateiktu algoritmu, buvo parašyta programa, skirta „Windows“. Galima atsisiųsti „Object Pascal“ šaltinio kodus ir sukompiliuotą vykdomąjį failą.

Programos sąsaja.
Spustelėjus mygtuką „Atidaryti...“, atidaromas BMP failo pasirinkimo dialogo langas. Palaikomi tik taškai su 24 bitų palete. Atidarytas vaizdas rodomas lange. Lango pavadinime rodomas visas failo kelias ir vaizdo matmenys.

Lauke „Kampas“ nurodykite sukimosi kampą laipsniais – bet kurį teigiamą skaičių.
Įvedant trupmeninius skaičius kaip dešimtainį skyriklį galima naudoti tašką arba kablelį.

Radijo mygtukai „CW“ ir „CCW“ nustato sukimosi kryptį: atitinkamai „pagal laikrodžio rodyklę“ ir „prieš laikrodžio rodyklę“.

Bloke „Fono spalva“ galite nustatyti fono spalvą, su kuria bus maišomi vaizdo kraštinių pikseliai. Numatytoji fono spalva yra juoda.

Laukuose „Centras X“ ir „Centras Y“ nurodomos sukimosi centro koordinatės. Reikėtų atsižvelgti į tai, kad koordinačių pradžia yra viršutiniame kairiajame vaizdo kampe, o Y didėja žemyn. Pagal numatytuosius nustatymus sukimosi centras nustatytas į įkelto vaizdo geometrinį centrą.

Spustelėjus mygtuką „Pasukti“ arba paspaudus Enter klavišą, vaizdas pasukamas nurodytu kampu nurodyto sukimosi centro atžvilgiu ir rodomas lange. Vaizdo pasukimas kampais, kurie yra 90° kartotiniai, įgyvendinamas pagal supaprastintą schemą, tiesiog pakeičiant pradinio vaizdo pikselių koordinates, o „Centro X“ ir „Centro Y“ reikšmės nepaisomos.
Algoritmo veikimo laikas sekundėmis rodomas po mygtuku „Pasukti“.

Naudojant mygtuką „Išsaugoti...“, pasuktą vaizdą galima įrašyti į BMP failą.

Jei galutinis vaizdas netelpa į langą, jis priderinamas prie lango kraštų naudojant StretchBlt API funkciją – todėl realią didelių vaizdų kokybę galima įvertinti tik naudojant išsaugotą BMP failą.
Norint pasukti vaizdą kitu kampu, jo perkrauti nereikia – pasukamas vaizdas iš pasirinkto failo, o ne tas, kuris šiuo metu rodomas lange.

1024 x 768 matmenų vaizdas mašinoje su keturių branduolių 2,67 GHz procesoriumi ši programa pasuka savavališku kampu, vidutiniškai per maždaug 0,5 sekundės. 4000 x 4000 matmenų vaizdas – maždaug per 10 sekundžių. Algoritmo veikimo laikas skirtingais kampais gali skirtis dėl to, kad vaizdas skirtingais kampais suskaidomas į skirtingą skaičių „skeveldrų“, atitinkamai skiriasi bendras laikas, sugaištas skaičiuojant šių fragmentų plotus.

Tarpinis masyvas, kuriame yra informacija apie galutinio vaizdo pikselių spalvą slankiojo kablelio formatu, yra įdiegtas išplėstiniame tipe (10 baitų), todėl apdorojant didelius vaizdus (maždaug daugiau nei 5000 x 5000 pikselių) gali atsirasti atminties perpildymo klaida. Situaciją galima pagerinti naudojant ne tokį tikslų duomenų tipą ir išsaugant sveikąją skaičiaus dalį tiesiai į galutinį bitų grafiką, pagalbiniame masyve paliekant tik trupmeninę dalį.

Rezultatai

Atlikime lyginamąją Photoshop programoje įdiegto precizinio algoritmo ir vaizdo pasukimo algoritmo veikimo analizę.

1 testas

Pirmajam bandymui padariau labai paprastą vaizdą – horizontalią juodą 1 pikselio storio ir 10 pikselių ilgio liniją, nukrypusią nuo balto kvadrato, kurio matmenys 100 x 100 pikselių, centro:

Po to šį vaizdą geometrinio centro atžvilgiu pasukau 3° pagal laikrodžio rodyklę. Štai lyginamasis rezultatas (priartintas 24 kartus):

Tikslumo algoritmas

„Photoshop CS6“ (64 bitų)
Akivaizdu, kad „Photoshop“ algoritmas įveda tam tikrus vaizdo iškraipymus. Praeidami pažymime, kad „Photoshop“ įdiegtas sukimosi algoritmas per 10 metų nepatyrė jokių pastebimų pokyčių.

2 testas

Antram bandymui pasirinkau Tulip iš standartinio Win7 platinimo:

Pasukus šį vaizdą 5° pagal laikrodžio rodyklę geometrinio centro atžvilgiu, susumavau visų pikselių spalvas pagal RGB kanalus. Štai tikslaus algoritmo ir „Photoshop“ algoritmo rezultatas:

Skaičiai skliausteliuose rodo absoliutų šio rodiklio nuokrypį nuo originalo.
Vaizdo spalva po precizinio pasukimo ir prieš apvalinimą praktiškai nepasikeitė – to ir reikėjo tikėtis.
Didžiausią nuokrypį šiuo konkrečiu atveju randame „Photoshop“ algoritmo G kanale. Procentais šis nuokrypis yra tik 0,06%, todėl jis nėra pastebimas „iš akies“, tačiau dėl perfekcionizmo „Photoshop“ rezultatas yra prastesnis nei tikslaus algoritmo.
Svarbu pažymėti, kad kiekvieno pikselio spalvos suapvalinimas tikslumo algoritme iki sveikojo skaičiaus reikšmės, reikalingos BMP formatui, negrįžtamai sunaikina dalį spalvų informacijos.

Norėdami vizualiai palyginti du algoritmus, pateiksiu padidintą vaizdo fragmentą,

pasuktas atitinkamai 5° pagal laikrodžio rodyklę, „Photoshop“:

ir tikslumo algoritmas:

Lyginamoji analizė rodo, kad „Photoshop“ geriau išsaugo kontrastingus vaizdo elementus, bet tuo pačiu sukuria iškreiptų spalvų „aureoles“. Tikslumo algoritmas neiškraipo spalvos, bet tuo pačiu kažkiek „sulieja“ vaizdą.

Išvados

1. Galimas tikslumas ir tuo pačiu gana greitas rastrinio vaizdo pasukimas savavališku kampu. Man lieka paslaptis, kodėl profesionalūs grafiniai redaktoriai neturi parinkties, leidžiančios vartotojui itin tiksliai pasukti vaizdą per šiek tiek daugiau laiko.

2. Nepaisant itin didelio nagrinėjamo algoritmo tikslumo, atvirkštinė vaizdo transformacija, t.y. Neįmanoma pasukti į priešingą kampą neprarandant kokybės, nes tikslios spalvos reikšmės apvalinimas (slankiojo kablelio formatu) negrįžtamai sunaikina dalį spalvos informacijos.

3. Kontrastingų detalių vizualinio suvokimo požiūriu geriausią rezultatą gauna neoptimalus algoritmas. Tikslumo algoritmą tikslinga naudoti tais atvejais, kai svarbu išsaugoti maksimalią informaciją apie vaizdo spalvą.



Ar jums patiko straipsnis? Pasidalinkite su draugais!