5.5. Regiuni și măști¶
Implicit, fiecare operație din modulul image atinge fiecare pixel al imaginii sale sursă. Acesta este comportamentul cel mai simplu de descris și cel corect atunci când sarcina algoritmului acoperă cu adevărat întregul cadru – o corecție uniformă a culorii, o histogramă globală, o trecere de codare pentru transmisie. Însă, în practică, majoritatea algoritmilor doresc să examineze mai puțin de atât. Un urmăritor de blob-uri care supraveghează un marcator colorat se interesează de partea din scenă în care poate apărea marcatorul, nu de peretele din spatele lui. O trecere de curățare morfologică este sigură doar pe pixelii pe care o etapă anterioară i-a marcat drept candidați. Un detector de fețe ar putea rula doar în interiorul casetei de încadrare pe care un detector mai grosier a delimitat-o deja. Modulul image susține această activitate prin două mecanisme care limitează o operație la un subset de pixeli: regiunile de interes dreptunghiulare și măștile binare. Acestea se combină liber, iar aproape fiecare metodă care atinge pixeli acceptă unul sau celălalt – ori ambele – ca argument cu cuvânt-cheie.
5.5.1. Regiuni de interes¶
O regiune de interes este un dreptunghi de pixeli denumit prin cvadruplul (x, y, w, h) introdus pe pagina coordonatelor. Aproximativ treizeci de metode din interfață acceptă un argument cu cuvânt-cheie roi; când este prezent, operația rulează doar pe pixelii din interiorul acelui dreptunghi și lasă restul imaginii neatins. Când roi este None sau este omis, operația rulează pe întreaga imagine – la fel ca și cum s-ar fi transmis roi=(0, 0, width, height).
În cod, cuvântul-cheie stă alături de orice alte argumente pe care le primește operația:
# Compute a histogram over a centred crop of the image.
h = img.get_histogram(roi=(64, 64, 128, 128))
Primul lucru pe care îl oferă regiunile de interes este controlul fals-pozitivelor. Un urmăritor de culoare care privește doar masa nu se va declanșa niciodată la cămașa care trece pe lângă ea; un detector de muchii care rulează doar în zona de lucru definită nu va raporta niciodată muchiile suportului camerei în sine. Reducerea zonei de căutare la partea din scenă de care algoritmul chiar se interesează este cea mai ieftină îmbunătățire pe care o conductă o poate aduce propriei fiabilități.
Al doilea lucru pe care îl oferă este conducta de la grosier la fin. Obiectele rezultat ale detectării – un blob, un rect, un apriltag și așa mai departe – își expun casetele de încadrare sub forma aceluiași cvadruplu (x, y, w, h) pe care îl acceptă roi. Astfel, o primă etapă grosieră poate returna o casetă de încadrare, caseta intră direct în roi al etapei următoare, iar a doua etapă rulează pe zona mai îngustă. Fiecare îngustare progresivă atât accelerează etapa următoare, cât și îi face rezultatele mai fiabile, deoarece spațiul de căutare a fost deja filtrat.
5.5.2. Măști binare¶
Un dreptunghi este forma potrivită atunci când zona de interes este aliniată la axe. Când nu este – o regiune curbată, una neconvexă, pixelii pe care o etapă anterioară i-a clasificat drept „potriviri” – operația trebuie instruită să se limiteze la un tipar arbitrar de pixeli. Mecanismul pentru aceasta este o mască binară: o Image separată, cu aceleași dimensiuni ca sursa, folosită ca un comutator pornit / oprit per pixel. Un pixel diferit de zero în mască spune „include pixelul sursă corespunzător”; un pixel zero spune „lasă pixelul sursă neatins”.
O mască este de obicei o imagine BINARY – formatul de un bit per pixel care există exact pentru acest scop – dar orice imagine cu un singur canal va funcționa, deoarece consumatorul tratează orice valoare diferită de zero drept pornită.
Metodele de filtrare, prag și aritmetică acceptă un argument cu cuvânt-cheie mask. Forma este aceeași la fiecare: o imagine binară alocată separat, cu aceleași dimensiuni ca sursa, transmisă mai departe.
Regiunile de interes și măștile se combină. Transmiteți-le pe ambele, iar operația rulează doar pe pixelii care sunt în interiorul ROI și porniți în mască. Cele două mecanisme oferă codului aplicației pârghii independente – una pentru zona dreptunghiulară de interes, una pentru tiparul arbitrar din interiorul acesteia – fără ca vreuna dintre forme să moștenească constrângeri de la cealaltă.
Un ROI restrânge o operație la un dreptunghi aliniat la axe. O mască o îngustează și mai mult la un tipar arbitrar de pixeli. Cele două se combină: doar pixelii din interiorul ROI și porniți în mască sunt modificați.¶
5.5.3. Construirea măștilor¶
Trei metode Image construiesc geometrii uzuale de mască pe loc, prin anularea pixelilor din afara regiunii alese:
mask_rectangle()păstrează un dreptunghi.mask_circle()păstrează un cerc.mask_ellipse()păstrează o elipsă.
Fiecare primește (x, y, w, h) (pentru dreptunghi și elipsă) sau (x, y, radius) (pentru cerc). Apelarea oricăreia dintre ele fără argumente centrează geometria și o dimensionează pentru a umple imaginea, formă la care recurge o aplicație atunci când scopul este un simplu oval sau cerc pe întreaga imagine care nu ascunde decât colțurile.
mask = image.Image(img.width(), img.height(), image.BINARY)
mask.clear() # start from all zeros
mask.mask_ellipse() # centred, full-size oval
Măștile interesante provin rareori doar din metodele mask_*. Ele provin din etapele anterioare ale conductei: o trecere de prag produce o imagine binară ai cărei pixeli diferiți de zero marchează potrivirile, exact forma potrivită pentru a fi transmisă argumentului mask= al etapei următoare. O trecere de curățare morfologică rafinează acea mască fără a-i schimba forma. Orice ajunge să fie o imagine cu un singur canal este în sine o mască validă.
5.5.4. Cum modifică operațiile imaginea¶
Un tipar vizibil în fiecare fragment de cod din ultimele câteva pagini – operația returnând aceeași img pentru înlănțuire – merită evidențiat explicit, astfel încât să nu fie nevoie să fie reafirmat de fiecare dată când este introdusă o metodă nouă. Trei familii de metode apar pe interfața Image, fiecare tratând imaginea sursă în mod diferit:
Metodele de operare modifică pixelii sursei pe loc și returnează aceeași imagine pentru înlănțuire. Familiile de desenare, aritmetică, prag și filtrare se comportă toate în acest fel.
img.gaussian(1)aplică o estompare luiimgși returnează aceeașiimg; reatribuirea –img = img.gaussian(1)– este inofensivă, dar inutilă.Metodele de conversie operează implicit pe loc, la fel ca metodele de operare, dar acceptă
copy=Trueșicopy_to_fb=Truepentru a aloca o imagine rezultat separată atunci când sursa trebuie păstrată. Conversiile de format și copiile geometrice sunt principalii membri ai acestei familii.Metodele de inspecție citesc pixelii și returnează un obiect rezultat – o listă de caracteristici detectate, o histogramă, un set de statistici – fără a modifica deloc imaginea sursă.
Această trihotomie este consecventă pe întreaga interfață. A ști căreia familii îi aparține o metodă spune aplicației la ce să se aștepte de la un apel: dacă pixelii sursei vor supraviețui intacți, dacă va fi alocată o imagine rezultat separată și dacă valoarea returnată este sursa însăși sau altceva.