5.23. Perspektiivikorjaus¶
Varoitus
Mielivaltainen 3-kertaa-3 transform-matriisi on tuettu vain OpenMV Cam N6:lla – avainsana jätetään hiljaisesti huomiotta jokaisella muulla kortilla. Sovellusten, joiden on toimittava muualla, on käytettävä valmista rotation_corr() -metodia (sen corners=-muotoa) tai esilaskettava korjattu kuva kortin ulkopuolella.
Valmis rotation_corr() -metodi paketoi tietyn perspektiivivääristymien perheen pienen parametrijoukon taakse ja toimii jokaisella tuetulla kortilla. Jotkin sovellukset tarvitsevat vääristymän, joka ei sovi tuohon muotoon: mielivaltaisen projektiivisen uudelleenkuvauksen yhdestä nelikulmiosta toiseen, kalibroidun korjauksen tunnetulle kiinnitykselle, joka on jo selvitetty etukäteen, tai jonkin aiemman algoritmin valmiina luovuttaman vääristymämatriisin. Niitä varten draw_image() – yhdessä metodien copy(), crop() ja scale() kanssa – hyväksyy transform-avainsanan, joka ottaa käsin rakennetun 3-kertaa-3-matriisin, joka kuvaa vääristymän suoraan.
5.23.1. Affiinit ja projektiiviset muunnokset¶
Geometriset vääristymät ilmaistaan homogeenisissa koordinaateissa: pikselin sijainti (x, y), johon on lisätty 1, kerrottuna 3-kertaa-3-matriisilla.
Affiini muoto on hyvä paikka aloittaa. Sen alin rivi on kiinnitetty arvoon \((0, 0, 1)\):
Auki kirjoitettuna jokainen ulostulokoordinaatti on syötekoordinaattien lineaarinen yhdistelmä plus vakio:
joka kattaa skaalauksen, kierron, leikkauksen ja siirron missä tahansa yhdistelmässä – ja niissä kaikissa yhdensuuntaiset viivat pysyvät yhdensuuntaisina.
Projektiivinen (perspektiivinen) muoto vapauttaa alimman rivin:
Auki kirjoitettuna:
Jakaminen termillä \(w' = g x + h y + 1\) on se, mikä tekee muunnoksesta projektiivisen pelkän affiinin sijaan. Kun \(g\) ja \(h\) ovat molemmat nollia, \(w'\) pysyy ykkösenä eikä jako tee mitään – jälleen affiini muoto. Kun jompikumpi on nollasta poikkeava, \(w'\) vaihtelee syötteen sijainnin mukaan ja eri sijainneissa olevat pikselit lyhentyvät eri määrillä, mikä ei enää pidä yhdensuuntaisia viivoja yhdensuuntaisina – se on juuri keystone-ilmiö, joka syntyy katsottaessa tasoa vinosta kulmasta. Projektiivinen muunnos on yleisin geometrinen vääristymä, joka vie suorat viivat suoriksi viivoiksi; skaalaus, peilaus, transponointi, kierto ja neljän kulman kiertokorjaus ovat kaikki sen erikoistapauksia.
Nimetyt muunnokset johtuvat suoraan affiinista muodosta. Identiteettimuunnos on identiteettimatriisi, ja:
Useimpia käsin rakennettuja muunnoksia varten sovellus aloittaa yhdellä näistä pohjana ja kertoo sisään lisää matriiseja jokaista lisäoperaatiota varten päätyen yhteen 3-kertaa-3-matriisiin, joka kuvaa yhdistetyn vääristymän. Matriisit sovelletaan oikealta vasemmalle: \(M = T R S\) suorittaa ensin skaalauksen, sitten kierron ja sitten siirron. Yhdistelmä, jota kaikki lopulta tarvitsevat, on kierto kuvan keskipisteen ympäri – pelkkä kiertomatriisi pyörittää kuvaa pikseliorigon ympäri vasemmassa yläkulmassa, joten keskitetty versio siirtää keskipisteen \((c_x, c_y)\) origoon, kiertää ja siirtää sen takaisin:
5.23.2. transform-avainsana¶
Matriisi annetaan transform-avainsanan kautta, toimitettuna 3-kertaa-3-muotoisena ulab.numpy.ndarray-oliona. Käytettävä metodi on draw_image(), joka vääristää lähteen matriisin läpi piirtäessään sen kohteeseen – tulos päätyy puskuriin, jota sovellus hallitsee, ja vääristymä yhdistyy kaiken muun kanssa kutsussa: skaalauksen, alpha-sekoituksen ja maskauksen.
import ulab.numpy as np
M = np.array([[1.2, 0.0, -20.0],
[0.0, 1.2, -15.0],
[0.0, 0.0, 1.0]])
canvas.draw_image(img, transform=M)
Esimerkki vääristää kuvan img kuvalle canvas skaalattuna 1,2-kertaiseksi kumpaankin suuntaan ja siirrettynä vasemmalle ja ylös 20 ja 15 pikseliä – affiini vääristymä, joka on rakennettu suoraan edellä kuvatuista matriisin alkioista. Sama avainsana metodeissa copy(), crop() ja scale() soveltaa vääristymän kuvaan itseensä.