5.32. Spremanje i kompresija¶
Svaka je stranica do sada radila sa slikama na kameri: snimljenima u međuspremnik slike ili alociranima na MicroPython hrpi, obrađivanima kroz metode modula image te ili prikazanima u pregledu unutar OpenMV IDE-a ili proslijeđenima u sljedeću fazu unutar iste skripte. Većina aplikacija u nekom trenutku mora napraviti suprotno: uzeti sliku koja se trenutačno nalazi u RAM-u i pohraniti je negdje trajno – na SD karticu, na USB host, preko mreže – gdje je nešto drugo osim kamere može pročitati.
Modul image nudi dva puta za taj posao. Put spremanja zapisuje sliku u datoteku na datotečnom sustavu, pri čemu se format datoteke bira prema nastavku, a detalje kodiranja obrađuje metoda. Put u format vraća objekt Image koji sadrži kodirani niz bajtova, prikladan za predaju pozivu za strujanje ili umrežavanje a da se datotečni sustav uopće ne dotakne. Svaki odgovara drukčijoj aplikaciji; oba se oslanjaju na isti pogon za kompresiju u pozadini.
5.32.1. Spremanje u datoteku¶
save() zapisuje sliku na datotečni sustav na zadanu putanju:
img.save("/sdcard/capture.jpg")
img.save("/sdcard/capture.bmp")
img.save("/sdcard/region.jpg", roi=(40, 60, 200, 150), quality=85)
Format se odabire prema nastavku datoteke. Prepoznaje se pet nastavaka: .bmp zapisuje Windows bitmap (bez gubitaka, bez kompresije, piksele snimljene bajt po bajt); .pgm zapisuje portable graymap (bez gubitaka, samo sivi tonovi); .ppm zapisuje portable pixmap (bez gubitaka, RGB); .jpg i .jpeg oba zapisuju JPEG (s gubicima, komprimirano). Slika primatelj već mora biti u ispravnom formatu boja za odabrani spremnik – slika u boji spremljena kao .pgm je pogreška.
roi ograničava spremanje na pravokutni podio slike, jednako kao što to čini ključna riječ roi svake druge metode modula image. Cijela je slika zadana vrijednost. Ključna se riječ zanemaruje pri spremanju JPEG-komprimirane slike jer oblik na disku već pokriva cijelu sličicu, a ponovno kodiranje kroz izrezivanje poništilo bi smisao spremanja postojećih komprimiranih bajtova.
quality je JPEG kvaliteta kompresije od 0 do 100 i ima smisla samo kada je izlaz JPEG (ključna se riječ zanemaruje za formate bez gubitaka). Zadana vrijednost 50 pravi je odnos za većinu aplikacija; 70 do 85 je raspon za višu vizualnu kvalitetu, 30 do 50 je pravi raspon za male sličice i prijenos ograničen propusnošću, a 90 i više rezervirano je za slučajeve u kojima će se slika pregledavati ručno ili proslijediti algoritmu u nastavku osjetljivom na artefakte kompresije.
Slika primatelj se vraća kako bi se poziv mogao ulančati: img.save("/sdcard/x.jpg").draw_string(0, 0, "saved"). Vraćeni objekt je ista slika u memoriji; spremanje je nuspojava.
Tipičan je primjer uzorak snimi i zabilježi. Aktivira se okidač (otkrivena je mrlja, pritisnut je gumb, istekao je mjerač vremena); skripta snima sličicu; dodaje vremensku oznaku nazivu datoteke; te poziva save() da gurne sliku na SD karticu. Pregled u OpenMV IDE-u nastavlja se izvoditi, sljedeći se okidač aktivira, a spremljene se datoteke gomilaju.
5.32.2. Kodiranje u memoriju¶
Kada odredište nije datotečni sustav nego mrežna veza, serijski priključak ili ulaz nekog drugog modula, aplikaciji je potreban kodirani niz bajtova u memoriji umjesto na disku. to_jpeg() i to_png() proizvode upravo to:
encoded = img.to_jpeg(quality=80, copy=True)
bytes_to_send = encoded.bytearray()
sock.send(bytes_to_send)
Zadano je ponašanje pretvorba na mjestu: primatelj se pretvara u JPEG (ili PNG) sliku i vraća se isti objekt. Uz copy=True pretvorba zapisuje u svježe alocirani objekt na hrpi; uz copy_to_fb=True izlaz završava u međuspremniku slike. Izbor je isti kao i kod svake druge metode pretvorbe – zadano na mjestu, kopiranje kada je izvornik kasnije potreban.
quality i subsampling iste su JPEG ručice za podešavanje koje izlaže put spremanja. subsampling bira shemu podsemplinga krominancije: image.JPEG_SUBSAMPLING_AUTO odabire najbolju za odabranu kvalitetu, image.JPEG_SUBSAMPLING_444 zadržava krominanciju u punoj razlučivosti (najveća datoteka, najbolja točnost boja), image.JPEG_SUBSAMPLING_422 i image.JPEG_SUBSAMPLING_420 prepolovljuju razlučivost krominancije duž jedne ili obje osi (manje datoteke, blago omekšavanje boja koje je nevidljivo pri uobičajenim udaljenostima gledanja). Zadana vrijednost AUTO pravi je izbor osim ako aplikacija nema specifičnu potrebu.
PNG putem to_png() je bez gubitaka, ali sporiji za kodiranje i proizvodi veće datoteke od JPEG-a za fotografski sadržaj (fotografski se sadržaj loše komprimira pod PNG-ovom shemom predviđanja). Koristite PNG kada je slika linijski crtež, snimka zaslona ili sadrži grafiku oštrih rubova nacrtanu preko snimljene sličice – kodiranje bez gubitaka čuva oštre rubove koje bi JPEG omekšao. Inače je JPEG pravi zadani izbor.
I to_jpeg() i to_png() prihvaćaju iste pozicijske ključne riječi u stilu crtanja i mjerila koje uzimaju druge metode pretvorbe – x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint – pa isti poziv može u jednom koraku kodirati skaliranu, izrezanu ili paletom mapiranu verziju izvora. compress() je naslijeđeni naziv za to_jpeg(); oba uzimaju iste argumente i proizvode isti rezultat.
5.32.3. Što kompresija donosi¶
Brojke iza kompromisa između JPEG-a i sirovih podataka vrijedi jednom proći do kraja.
Sličica RGB565 dimenzija 320 puta 240 ima 153.600 bajtova (jedna snimljena sličica pri QVGA). Sličica 640 puta 480 ima 614.400 bajtova; sličica 1280 puta 960 ima 2.457.600 bajtova. Nijedna od njih nije velika u usporedbi sa zaslonom stolnog računala ili telefona, ali su znatne u kontekstu kamere koja ukupno ima nekoliko MB RAM-a, SD kartice s konačnom propusnošću zapisivanja te host veze koja obično radi preko USB CDC-a, UART-a ili bežičnog modula pri skromnim brzinama.
JPEG pri quality=50 obično komprimira fotografski snimljenu sličicu 10 do 20 puta: ta sličica 640 puta 480 od 614 KB postaje kodirani niz bajtova od 30 do 60 KB. Pri quality=85 kompresija pada na 5 do 10 puta (60 do 120 KB za istu sličicu). Pri quality=10 – punoj artefakata, ali još uvijek prepoznatljivoj – kompresija doseže 30 do 50 puta (12 do 20 KB).
Te brojke određuju što je praktično raditi sa spremljenim sličicama. Putanja SD kartice koja održava 10 MB/s podnosi 30 sličica u sekundi JPEG-kodiranog VGA sadržaja pri quality=50 s prostorom za višak (oko 1 do 2 MB/s); spremanje istog sadržaja nekomprimiranog zahtijeva više od 18 MB/s, što premašuje ono što putanja datotečnog sustava kamere održava prema kartici. USB host koji povlači JPEG-kodirane sličice preko CDC-a pri 1 MB/s prima sličice od 30 do 60 KB pri otprilike 15 do 30 sličica u sekundi; povlačeći sirove sličice pri istoj brzini dobiva jednu ili dvije sličice u sekundi.
Ukratko: metode kompresije nisu samo pogodnost za spremanje. One su ono što snimljenu sličicu čini upotrebljivom izvan kamere pri brzinama sličica do kojih je aplikaciji stalo. Odabir prave kompresije – JPEG kvalitete 50 za opće bilježenje, 80 za kvalitetan rad, PNG za snimanje linijskih crteža – dio je rutinskog posla svake netrivijalne aplikacije za kameru.