5.2. Koordinaatit ja alueet

Kuvankäsittely toimii pikseleillä, ja toimiakseen pikseliin algoritmin on osoitettava se koordinaatilla. Pikseleistä koostuvaan suorakulmioon toimiminen edellyttää samaa – suorakulmio on kuvattava tavalla, josta algoritmi ja sovelluskoodi ovat yhtä mieltä. image-moduulin käyttämä koordinaatti- ja suorakulmiokäytäntö on suoraviivainen, mutta siihen liittyy yksi yksityiskohta, joka yllättää lukijat, jotka ovat tottuneet matemaattiseen käytäntöön tietokonegrafiikan käytännön sijaan, ja se kannattaa tehdä selväksi heti alkuun.

5.2.1. Pikseliruudukko

Pikseli (0, 0) on kuvan vasemmassa yläkulmassa. X-akseli kulkee oikealle, joten suurempi x tarkoittaa kauempana oikealla. Y-akseli kulkee alaspäin, joten suurempi y tarkoittaa kauempana alhaalla kuvassa. Leveys-kertaa-korkeus-kokoinen kuva sisältää pikseleitä kokonaislukukoordinaateissa (0, 0) koordinaattiin (width - 1, height - 1) saakka; pikseliä ei ole kohdassa (width, 0) eikä kohdassa (0, height) – ne sijainnit ovat oikea ja alareuna, yhden askeleen viimeisen todellisen pikselin ohi kummassakin suunnassa.

Alaspäin kulkeva y-akseli on edellä mainittu yksityiskohta. Ruutupaperigeometriaan tottunut lukija olettaa, että suurempi y tarkoittaa ylempänä; tässä tuo intuitio on tarkalleen käänteinen. Käänteisyyden syy on se, että sekä digitaaliset sensorit että digitaaliset näytöt toimivat vasemmasta yläkulmasta lähtien ja kulkevat oikealle jokaisen rivin läpi, ylhäältä alas, ja pikselien sijoittaminen muistiin samassa järjestyksessä tekee suhteesta ”sijainti i puskurissa” ja ”kuvan rivi r, sarake c” niin yksinkertaisen aritmeettisen palan kuin mahdollista – pikselin (x, y) sijainti i on yksinkertaisesti y * width + x. Jokainen kuvankäsittelykirjasto sopi tuosta järjestelystä vuosikymmeniä sitten samasta syystä, ja hintana on yksi pieni ajatuksellinen mukautus, kun kuvien kanssa työskennellään ensimmäistä kertaa.

Suorakulmio, joka edustaa kuvaa. Sen vasemmassa yläkulmassa oleva merkki on nimetty (0, 0). Yläreunaa pitkin kulkeva nuoli osoittaa oikealle, ja se on nimetty x; vasenta reunaa alas osoittava nuoli on nimetty y. Sisälle piirretty pienempi suorakulmio on nimetty ROI, sen vasen yläkulma on kohdassa (x, y) ja sen mitat w ja h on merkitty reunoja pitkin.

Kuvan koordinaatistojärjestelmä: origo vasemmassa yläkulmassa, x kulkee oikealle, y kulkee alaspäin. Kuvan sisällä oleva suorakulmainen alue nimetään sen vasemmalla yläkulmalla (x, y) ja sen mitoilla (w, h).

5.2.2. Suorakulmiot

Useimmat kuvaan kohdistuvat operaatiot välittävät yksittäisen pikselin sijaan enemmän suorakulmiosta pikseleitä – alueesta, jota tarkastellaan, alueesta, joka kopioidaan pois, kehyksestä kehyksen sisällä, jonka yli lasketaan tilastoja. Suorakulmion nimeämismuoto valitsee yksittäisen pikselin käytännön yksinkertaisimman mahdollisen laajennuksen: anna vasemman yläkulman koordinaatti, jota seuraavat suorakulmion mitat, pakattuna nelikkoon (x, y, w, h). Suorakulmion sisällä olevat pikselit ovat sarakkeissa xx + w - 1 ja riveillä yy + h - 1.

Tässä selvennettävä yksityiskohta on se, että w ja h ovat kokoja, eivät oikean alakulman koordinaatteja. Suorakulmio (10, 20, 4, 3) kattaa sarakkeet 10, 11, 12, 13 ja rivit 20, 21, 22 – yhteensä kaksitoista pikseliä – ei aluetta, joka kulkee koordinaatista (10, 20) koordinaattiin (4, 3). Käytäntö on yhtenäinen koko moduulissa, joten kun se on sisäistetty, lipsahdukset loppuvat, mutta ensimmäisellä kerralla se kyllä yllättää.

Muoto (x, y, w, h) esiintyy kolmessa paikassa, jotka näyttävät erilaisilta mutta jakavat saman käytännön. Ensimmäinen on, kun kuva kuvaa oman jalanjälkensä: koko kuvan kattava suorakulmio on (0, 0, width, height). Toinen on, kun tunnistusmenetelmä palauttaa tuloksen, jolla on rajauslaatikko – blob, rect, apriltag – ja laatikko raportoidaan takaisin muodossa (x, y, w, h). Kolmas on, kun menetelmälle on kerrottava, että sen tulee toimia kuvan osa-alueella koko kehyksen sijaan; operaation rajaava roi-avainsanaargumentti ottaa saman nelikon.

Rajauslaatikon poimiminen yhdestä menetelmästä ja sen pudottaminen seuraavan menetelmän roi-argumenttiin on yksi yleisimmistä kaavoista kuvankäsittelyssä. Karkean ensimmäisen tunnistuksen rajauslaatikko kaventaa hakualuetta tarkemmalle toiselle tunnistukselle, ja yhtenäinen sanasto tunnistustulosten ja menetelmäargumenttien välillä on se, mikä tekee tästä kaavasta niin suoraviivaisen kuin se on – yksi nelikkomuoto, käytettynä samalla tavalla luovutuksen molemmilla puolilla.

5.2.3. Kokonaislukuosoitteet, murtolukukeskipisteet

Pikseliosoitteet itsessään ovat kokonaislukuja. Pikseli joko on tai ei ole annetussa kokonaislukusarakkeessa ja -rivillä, ja kysymys siitä, mitä on koordinaatissa (40.5, 30.7), ei ole hyvin muotoiltu – juuri siinä sijainnissa ei ole pikseliä. Kourallinen suureita, jotka image-moduuli johtaa pikselisijainneista, on kuitenkin murtolukuisia, ja kannattaa ymmärtää miksi, jotta ero ei yllätä sovellusta myöhemmin.

Yleisin tapaus on keskipiste (centroid) – alueen massakeskipiste. Yhtenäiselle pikselialueelle keskipiste liukulukumuodossa on jäsenpikselien sijaintien keskiarvo, painotettuna niiden tiheydellä. Alueella, jonka pikselit ulottuvat kahteen sarakkeeseen, keskipisteen x on esimerkiksi 41,6 – todellinen sijainti, jonka silmä kuvaisi ”tuon alueen keskikohdaksi”, vaikkei mikään todellinen pikseli sijaitse tarkalleen tuossa x:ssä. Tunnistustulosobjektit kantavat molempia muotoja vain luettavina ominaisuuksina: kokonaislukuparin (cx / cy, hyödyllinen kun sijainti syötetään takaisin johonkin, joka haluaa kokonaislukupikselikoordinaatteja) ja liukulukuparin (cxf / cyf, hyödyllinen kun sijainti menee säätösilmukkaan, joka hyötyy alipikseliresoluutiosta).

Toinen tapaus on siirtymä kahden kehyksen välillä mitattuna taajuusalueella. Tekniikat, jotka analysoivat kuvan spektrisisältöä sen sijaan että käsittelisivät pikseleitä suoraan, voivat erottaa yhtä pikseliä hienompia siirtymiä, ja ne raportoivat nuo siirtymät liukulukuisina (dx, dy) -arvoina.

Nyrkkisääntö: pikseliosoitteet ovat kokonaislukuja; sijainnit ja siirtymät, jotka tulevat algoritmista ulos, voivat olla liukulukuja. Piirtomenetelmät hyväksyvät kummankin muodon ja pyöristävät liukuluvut alaspäin lähimpään kokonaislukupikseliin, kun tuloksen on osuttava ruudukkoon.

5.2.4. Karteesinen ja napakoordinaatistö

Tähän mennessä kuvattu järjestelmä on karteesinen: jokainen pikseli nimetään sen vaaka- ja pystysuoralla siirtymällä origosta. Se on järjestelmä, jossa tavut tallennetaan – pikseli i puskurissa vastaa pikseliä sarakkeessa i % width ja rivillä i // width, kulkien rivit ylhäältä – ja se on järjestelmä, jossa jokainen menetelmä oletusarvoisesti toimii.

Toinen esitystapa kannattaa tuntea, koska jotkin algoritmit toimivat siinä paljon paremmin. Napakoordinaatit nimeävät jokaisen pikselin sen etäisyydellä valitusta keskipisteestä ja kulmalla sen ja vertailusuunnan välillä. Kuvan pikselit eivät ole liikkuneet – tavut ovat edelleen samassa rivijärjestyksessä olevassa puskurissa – mutta osoitusjärjestelmä on vaihtunut tyylistä ”kuinka kauas oikealle ja kuinka kauas alas” tyyliin ”kuinka kaukana keskipisteestä ja missä kulmassa sen ympärillä.”

Kaksi suorakulmiota vierekkäin, kummatkin edustavat samaa kuvaa. Vasemmanpuoleinen näyttää karteesiset koordinaatit -- origo vasemmassa yläkulmassa, x- ja y-akselit, näytepiste P koordinaateissa (x, y). Oikeanpuoleinen näyttää napakoordinaatit -- keskipistemerkki C suorakulmion sisällä, viiva C:stä samaan pisteeseen P nimettynä r (etäisyys), ja kaari nimettynä theta (kulma).

Sama piste P, nimettynä kahdella tavalla: karteesinen (x, y) vasemman yläkulman origosta, napakoordinaatti (r, theta) valitusta keskipisteestä.

Miksi vaivautua vaihtamaan? Kahden identiteetin vuoksi, jotka muuttavat vaikeat haut helpoiksi.

Napakoordinaateissa kuvan kiertäminen valitun keskipisteen ympäri on sama operaatio kuin sen pikselien siirtäminen kulma-akselia pitkin – x-suunta uudelleenprojisoidussa kuvassa. Kierretty kopio on alkuperäinen siirrettynä vasemmalle tai oikealle napakoordinaatti-muodossa.

Log-napakoordinaatti-muunnelmassa – etäisyysakseli käyttää logaritmista asteikkoa, kulma-akseli pysyy lineaarisena – kuvan skaalaaminen valitun keskipisteen ympäri on sama operaatio kuin sen pikselien siirtäminen etäisyysakselia pitkin – y-suunta. Skaalattu kopio on alkuperäinen siirrettynä ylös tai alas log-napakoordinaatti-muodossa.

Niinpä algoritmi, jonka on tunnistettava tunnettu kuvio kierron tai skaalauksen alaisena, voi tehdä hakunsa napakoordinaatti-avaruudessa, jossa molemmat muunnokset muuttuvat tavallisiksi siirroiksi. Siirtoja on paljon halvempi etsiä kuin kiertoja ja skaalauksia, ja napakoordinaatti-uudelleenprojisointi on se, mikä tekee korvauksen mahdolliseksi.

Napakoordinaatit eivät korvaa karteesisia koordinaatteja pikselien tallentamisessa; tavut elävät aina karteesisessa ruudukossa. Moduuli tarjoaa parin menetelmiä, jotka uudelleenprojisoivat kuvan karteesisesta napakoordinaatti-muotoon tarvittaessa, napakoordinaatteja tarvitseva algoritmi tekee työnsä, ja joko tulos projisoidaan takaisin ulos tai napakoordinaatti-avaruuden mittausta käytetään suoraan. Tuo mekanismi on ainoa syy, miksi napakoordinaatit esiintyvät missään moduulin pinnassa.

Karteesisilla koordinaateilla yksittäisten pikselien nimeämiseen, (x, y, w, h) -nelikolla niistä koostuvien suorakulmioiden nimeämiseen, ja napakoordinaateilla käytettävissä silloin kun algoritmi hyötyy niistä, sovelluksella on täydellinen sanasto sille, missä kuvassa jokin sijaitsee. Se, mitä missä tahansa noista sijainneista todella on tallennettuna, on perustan seuraava kerros.