5.3. Formati piksela¶
Algoritam koji detektira rubove očekuje da svaki piksel sadrži vrijednost svjetline. Algoritam koji prati obojeni objekt očekuje da svaki piksel nosi boju. Algoritam koji izvodi morfološko zatvaranje očekuje da svaki piksel bude ili uključen ili isključen. Format piksela koji Image nosi – jedan od onih nabrojanih u katalogu Vision senzora – upravo je ono što omogućuje da se ta očekivanja unaprijed provjere: format unaprijed kaže u kojem su obliku pikseli i koji algoritmi se stoga mogu izvoditi na njima bez koraka konverzije.
Ova stranica govori o tome kako se to ograničenje očituje u praksi. Koji je format ispravan izbor ovisi o tome što će cjevovod (pipeline) raditi, a metode konverzije između formata su način na koji cjevovod kojemu je potrebno više od jednog formata povezuje faze u cjelinu.
Pet nekomprimiranih formata piksela i kako se njihovi bajtovi pakiraju. JPEG i PNG ovdje nisu nacrtani jer su komprimirani tokovi promjenjive duljine, a ne fiksne mreže piksela.¶
5.3.1. Radni konj sivih tonova¶
Većina klasičnog strojnog vida svodi se na rad s vrijednostima svjetline. Detekcija rubova, podudaranje predložaka, dekodiranje AprilTag oznaka, procjena optičkog toka, morfološki operatori, analiza mrlja – svi oni, na razini na kojoj algoritmi rade, gledaju koliko je svaki piksel svijetao i kako se ta svjetlina uspoređuje sa svjetlinom obližnjih piksela. Boja scene često je korisna aplikaciji koja ih poziva, ali sami algoritmi je ne trebaju.
Format sivih tonova daje algoritmima upravo to, bez ikakvog dodatnog opterećenja. Jedan bajt po pikselu sadrži vrijednost svjetline od 0 (crno) do 255 (bijelo). Format je upola manji od RGB565 i YUV422 te trećina veličine RGB888, pa svaka operacija obrađuje manje podataka – i brže i s manjim pritiskom na međuspremnik. Na manjim kamerama, gdje se međuspremnik slike natječe s ostatkom skripte za RAM, ta razlika u veličini može biti ono što odlučuje hoće li cjevovod uopće stati. Ako boja nije naznaka koju algoritam treba, sivi tonovi su pravi odgovor.
5.3.2. Boja kroz RGB565¶
Kada boja jest naznaka – praćenje obojenog markera, razlikovanje crvenih jabuka od zelenih, izdvajanje UI elementa po njegovoj nijansi – dva bajta po pikselu kupuju dovoljno boje za vrste klasifikacije koje algoritmi izvode. RGB565 je zadani format boje na kameri i onaj koji metode svjesne boje na sučelju očekuju.
Renderiranje označene sličice – crtanje okvira detekcije, ispisivanje dijagnostičkog teksta, prikaz sličice na zaslonu ili slanje udaljenom pregledniku – također prirodno traži RGB565. Pregled u IDE-u, ugrađeni kontroleri zaslona i većina mrežnih odredišta ili izravno koriste taj format ili jeftino konvertiraju iz njega.
5.3.3. Bayer kao format pohrane¶
Bayer slika je sirovi izlaz senzora, prije nego što ga je ISP debayerirao u dovršeni prikaz boje. Svaki piksel je jedan bajt koji sadrži jedan kanal boje – onaj koji je propustio filtar boje na toj poziciji u mozaiku. Zbog toga je Bayer slika iste veličine kao slika u sivim tonovima i trećine veličine RGB888, što se poklapa s onim za što je Bayer zapravo koristan: pohranjivanje mnogo sličica odjednom kada je RAM ograničavajući čimbenik.
Kvaka je u tome što algoritmi u modulu image ne rade izravno na Bayer slikama. Bez debayeriranja nijedan piksel ne nosi dovoljno informacija da bi sam donio prosudbu o boji, a uzorci koje algoritmi traže – rubovi, kutovi, mrlje – bili bi iskrivljeni mozaikom. Jedini načini za čitanje ili izmjenu Bayer slike su get_pixel() i set_pixel(); sve ostalo očekuje dovršeni prikaz.
Obrazac koji iz toga proizlazi jest pohraniti sličice kao Bayer dok god trebaju čekati u redu te konvertirati svaku u sive tonove ili RGB565 u trenutku kada njezina obrada zaista počinje. Konverzija troši cikluse procesora, ali štedi RAM koji bi inače bio zauzet držeći dovršene sličice tijekom cijelog životnog vijeka aplikacije.
Napomena
Jedine operacije modula image izravno na Bayer pikselima su get_pixel(), set_pixel() te put JPEG kodiranja koji napaja pregled u IDE-u ili udaljeni preglednik. Crtanje, analiza i filtriranje svi zahtijevaju prethodnu konverziju u sive tonove, RGB565 ili binarni format.
5.3.4. YUV422 za cjevovode koji žele oboje¶
YUV422 razdvaja informaciju svakog piksela u kanal luminancije (Y) i dva kanala krominancije (U i V) te poduzorkuje krominanciju tako da susjedni parovi piksela dijele jedan U i jedan V. Bajtova po pikselu u prosjeku ispada dva – jednako kao kod RGB565 – ali su raspoređeni tako da je Y kanal već neprekidna 8-bitna slika u sivim tonovima koja se nalazi na poznatim odmacima u međuspremniku.
Taj je raspored upravo ono što cjevovod želi kada su neke od njegovih faza rad u sivim tonovima, a nekima treba boja. Izravno čitanje Y vrijednosti za faze u sivim tonovima preskače trošak eksplicitne konverzije; kanali U i V su tu kada kasnijoj fazi zaista treba boja. Izvan tog specifičnog obrasca, RGB565 je obično jednostavniji izbor za boju, a sivi tonovi su jednostavniji izbor za rad samo sa svjetlinom – vrijednost YUV422 dolazi od toga što je dobar u oboje istovremeno.
Napomena
Modul image radi na YUV422 na ograničeniji način nego na sivim tonovima, RGB565 ili binarnom formatu – izravna čitanja Y kanala za rad u sivim tonovima i put JPEG kodiranja koji napaja pregled u IDE-u ili udaljeni preglednik. Metode svjesne boje očekuju RGB565; YUV422 sličice trebaju eksplicitnu konverziju prije analize boje ili crtanja.
5.3.5. Binarni format, maske i pragovani izlaz¶
Binarna slika je jedan bit po pikselu: svaki piksel je ili 0 ili 1. Format se rijetko pojavljuje kao snimka senzora; umjesto toga pojavljuje se kao prirodni izlaz pragovanja (gdje test boje ili svjetline klasificira svaki piksel u „da, odgovara” ili „ne, ne odgovara”) te kao prirodni ulaz u morfološke operacije i u argument mask koji mnoge metode prihvaćaju.
Praktična prednost ovog formata jest njegova veličina. Binarna slika zauzima jednu osminu prostora slike u sivim tonovima, pa je nošenje velike maske uokolo – izbor po pikselu o tome koje pozicije bi neka kasnija operacija trebala dotaknuti – jeftino. Činjenica da mnoge operacije prihvaćaju binarnu sliku kao mask= ključni argument druga je strana iste medalje: format je malen, a ulančavanje binarnog izlaza jedne faze u ulaz maske druge česti je obrazac cjevovoda.
5.3.6. JPEG i PNG na granici¶
JPEG i PNG Image objekti razlikuju se od ostalih u katalogu. Oni nisu mreže piksela; oni su komprimirani tokovi bajtova koji kodiraju podatke o pikselima u obliku koji operacije na razini piksela ne mogu čitati. Pozivanje get_pixel() na JPEG-u ne vraća piksel na poziciji; piksel nigdje ne stoji raspakiran u međuspremniku da bi ga metoda dohvatila.
JPEG i PNG pojavljuju se na granici obrade slike, gdje podaci o pikselima napuštaju ili ulaze u kameru u komprimiranom obliku. Spremanje sličice na disk kao JPEG održava datoteku malom; slanje sličice preko mreže kao JPEG održava prijenos jeftinim; učitavanje referentne sličice iz JPEG datoteke omogućuje joj da na disku stoji u mnogo manjem obliku nego što bi to bili sirovi pikseli. Za bilo koji od tih slučajeva uporabe komprimirani prikaz je pravi odgovor. No, da bi se na JPEG-u izvela bilo kakva stvarna obrada, aplikacija ga najprije konvertira u upotrebljiv format – a ta konverzija je mjesto na kojem se komprimirani bajtovi šire u piksele i na kojem se međuspremnik napuhava (30 KB JPEG-a može postati 600 KB RGB565).
5.3.7. Konverzija između formata¶
Put konverzije je ono što spaja različite formate u jedinstveni cjevovod. Pet metoda na klasi Image uzima postojeću sliku i vraća novu u drugom formatu:
to_grayscale()proizvodi sliku s jednim bajtom po pikselu, format koji klasični algoritmi žele.to_rgb565()proizvodi format boje s dva bajta po pikselu koji govore i metode svjesne boje i pregled u IDE-u.to_bitmap()proizvodi jednobitnu binarnu sliku, format koji prihvaćaju morfologija imaskargumenti.to_jpeg()proizvodi JPEG-komprimiranu sliku prikladnu za spremanje ili prijenos.to_png()proizvodi PNG-komprimiranu sliku kada se kodiranje bez gubitaka preferira nad JPEG-ovim manjim datotekama.
Svaka konverzija po zadanom se izvodi na mjestu (in place): međuspremnik izvorne slike prepisuje se konvertiranim rezultatom, a izvorni pikseli izvora nestaju nakon povratka iz poziva. To je najjeftinija opcija i za procesor i za memoriju, te je pravi odgovor kada izvorna sličica neće biti potrebna ni za što drugo.
Kada je izvor ipak još potreban – kada kasnija faza cjevovoda mora vidjeti izvornu sličicu – dva ključna argumenta nadjačavaju zadanu izvedbu na mjestu. copy=True alocira zasebni međuspremnik za konvertiranu sliku na Python hrpi (heap) i ostavlja izvor netaknutim. copy_to_fb=True izvodi istu alokaciju, ali je smješta u međuspremnik slike umjesto na hrpu – za čime aplikacija poseže kada konvertirana slika treba završiti u pregledu u IDE-u, budući da IDE čita iz međuspremnika slike.
Dvije daljnje metode proizvode RGB565 slike obojene kroz paletu umjesto izravnom konverzijom. to_rainbow() preslikava svaku ulaznu vrijednost jednog kanala na boju duž glatkog gradijenta koji prolazi kroz vidljivi spektar. to_ironbow() preslikava svaku ulaznu vrijednost na nelinearnu paletu termalnog snimača koja ide od crne kroz tamnocrvene i narančaste do bijele. Obje su alati za vizualizaciju, a ne za mjerenje; smisao je učiniti sliku jednog kanala, čije bi sirove vrijednosti inače bile nevidljive oku, čitljivom na prvi pogled.
5.3.8. Veličina međuspremnika¶
Još jedan detalj o formatima koji vrijedi izrijekom navesti. size() uvijek prijavljuje veličinu međuspremnika u bajtovima, a ne broj piksela. Za nekomprimirane formate to izravno proizlazi iz dimenzija i broja bajtova po pikselu: width * height * bytes_per_pixel. Za JPEG i PNG to je veličina komprimiranog toka, koja varira od sličice do sličice ovisno o tome što scena sadrži. Kod koji alocira međuspremnike iz proračuna bajtova koristi size() za prvi slučaj; kod koji strujno šalje komprimirane sličice iz kamere čita je nakon svake kompresije kako bi znao koliko bajtova tok zapravo sadrži.