5.18. Histograme și statistici¶
Pe lângă operațiile care modifică pixelii unei imagini, clasa Image oferă o familie de metode care îi măsoară – rezumă distribuția valorilor pixelilor, returnează luminozitatea medie și mediana, găsesc pragul optim între pixelii întunecați și cei luminoși, raportează dispersia canalelor de culoare. Măsurătorile alimentează aplicațiile în două moduri: ca intrări pentru codul care decide ce prag să folosească, ce amplificare (gain) să seteze, cum arată profilul tonal al scenei; și ca semnale de diagnostic – „este scena suficient de luminoasă?” – pe baza cărora o aplicație poate acționa fără a lua o decizie privind vreun pixel anume.
Punctul de plecare pentru aproape orice măsurătoare este histograma.
5.18.1. Histograma¶
Histograma unei imagini este o numărare a câți pixeli au fiecare valoare posibilă de luminozitate. Pentru o imagine în tonuri de gri, aceasta este o listă de numărători indexată după valorile de la 0 la 255. Pentru o imagine color, este vorba de trei astfel de liste – câte una pentru fiecare canal.
get_histogram() calculează una:
h = img.get_histogram()
Obiectul returnat este un rezultat histogram care expune listele de coșuri (bins) per canal și câteva interogări de nivel înalt asupra lor. Numărătorile din coșuri sunt normalizate astfel încât suma lor să fie 1.0 – histograma descrie profilul distribuției mai degrabă decât numărul absolut de pixeli, ceea ce face măsurătorile comparabile între imagini de dimensiuni diferite.
Pentru imaginile în tonuri de gri, histograma are un singur canal de coșuri, disponibil ca h.bins() (sau echivalent h[0]). Pentru imaginile RGB565, histograma este calculată în spațiul de culoare LAB introdus pe pagina despre pragul binar, cu trei canale de coșuri disponibile ca h.l_bins(), h.a_bins(), h.b_bins() (sau h[0], h[1], h[2]). LAB este aceeași alegere pe care o folosesc metodele de prag și de urmărire; histogramele sunt de acord cu pragurile asupra spațiului în care se măsoară culoarea.
5.18.2. Coșurile și numărul de coșuri¶
Histograma implicită are un coș per fiecare valoare posibilă de pixel – 256 de coșuri pentru un canal pe 8 biți. Uneori aceasta este o rezoluție mai fină decât are nevoie aplicația. Un clasificator căruia îi pasă doar de profilul aproximativ al distribuției ar putea fi mai bine servit de un număr mai mic de coșuri – 32 sau chiar 8 coșuri – ceea ce rulează mai repede și produce un rezultat mai curat împotriva zgomotului. Cuvântul-cheie bins (și cele per canal l_bins, a_bins, b_bins pentru culoare) setează numărul:
h = img.get_histogram(bins=32)
Restrângerea după ROI și după prag funcționează la fel ca pe orice altă metodă de măsurare. Transmiteți un roi pentru a limita histograma la un dreptunghi de pixeli; transmiteți o listă thresholds pentru a include doar pixelii care se potrivesc cu acele intervale. Forma cu prag este cea care face din „calculează histograma doar a pixelilor care se potrivesc” o operație într-un singur apel – un tipar frecvent atunci când o aplicație vrea să caracterizeze textura unei regiuni deja detectate fără a fi nevoită să parcurgă singură pixelii.
O histogramă în tonuri de gri cu trei măsurători de rezumat suprapuse: pragul lui Otsu (limita care separă cel mai bine grupurile de pixeli întunecați și luminoși), media și mediana. Fiecare măsurătoare spune ceva diferit despre aceeași distribuție.¶
5.18.3. Statistici¶
O histogramă este o descriere a frecvenței fiecărei valori; statisticile sunt rezumatele numerice derivate din ea. Obiectul statistics returnat de get_statistics() poartă setul standard:
mean– media aritmetică a valorilor pixelilor.median– valoarea sub care se află jumătate dintre pixeli.mode– cea mai frecventă valoare individuală.stdev– abaterea standard, o măsură a dispersiei în jurul mediei.minșimax– cele mai luminoase și cele mai întunecate valori de pixel prezente.lqșiuq– limitele cuartilei inferioare și superioare.
Pentru o imagine RGB565, formele per canal (l_mean, a_median, b_mode și așa mai departe) furnizează aceleași măsurători, canal cu canal.
Majoritatea acestor numere apar în contexte specifice. mean și stdev împreună oferă o estimare a zgomotului: o scenă care ar trebui să fie uniformă are un stdev mic, în timp ce un senzor zgomotos dă aceleiași scene un stdev mai mare. min și max oferă contrastul imaginii: cu cât sunt mai apropiate, cu atât scena este mai plată; cu cât sunt mai îndepărtate, cu atât algoritmul are mai mult interval dinamic cu care să lucreze. median este centrul robust atunci când distribuția are valori aberante (câțiva pixeli foarte luminoși nu trag mediana așa cum trag media). mode este singura valoare cea mai frecventă, utilă pentru a găsi nivelul de fundal al unei imagini al cărei fundal acoperă majoritatea pixelilor.
get_statistics() rulează intern parcurgerea histogramei și apoi o rezumă; transmiterea acelorași argumente thresholds și roi ca pentru o histogramă calculată anterior produce statisticile pentru același set de pixeli.
5.18.4. Percentile și căutări în CDF¶
Obiectul histogram expune o metodă get_percentile() care transformă o fracție într-o valoare de pixel – valoarea sub care se află fracția cerută de pixeli. h.get_percentile(0.5) este mediana; h.get_percentile(0.05) și h.get_percentile(0.95) oferă împreună un min/max robust care ignoră primele și ultimele 5% ca valori aberante.
Aceasta este forma pe care o folosește o aplicație atunci când vrea să caracterizeze intervalul valorilor pixelilor fără a lăsa o mână de pixeli rătăciți luminoși sau întunecați să distorsioneze răspunsul. Min/max-ul robust din percentilele 5 și 95 este de asemenea intrarea naturală pentru o etapă de întindere a contrastului – remaparea per pixel pe care o tratează pagina Corecții tonale.
5.18.5. Metoda lui Otsu¶
Histogramele răspund la o altă întrebare demnă de menționat separat: dată fiind o imagine ai cărei pixeli se împart într-un grup „întunecat” și unul „luminos”, care este limita dintre ele? Pagina despre praguri a numit deja mecanismul prin rezultatul său – un singur prag global pe care aplicația îl poate transmite către binary() – dar a amânat cum-ul. Cum-ul este metoda lui Otsu și se află pe histogramă.
Intuiția: o imagine cu un prim-plan și un fundal clare are două grupuri în histograma sa de luminozitate, cu o vale între ele. Locul potrivit pentru prag este fundul văii – valoarea la care cele două grupuri sunt cel mai bine separate. Metoda lui Otsu caută fiecare limită posibilă și o alege pe cea la care varianțele din interiorul grupurilor sunt cele mai mici (ceea ce este echivalent cu a spune că varianța dintre grupuri este cea mai mare), iar rezultatul este împărțirea binară optimă pentru distribuția acelei imagini particulare.
Obiectul histogram expune Otsu prin get_threshold:
h = img.get_histogram()
t = h.get_threshold()
Obiectul threshold returnat are atributele value (pentru tonuri de gri) sau l_value / a_value / b_value (pentru culoare) care poartă limita aleasă. Reintroducerea directă a rezultatului în binary() oferă un prag global care se auto-reglează, a cărui limită este aleasă de imaginea însăși:
img.binary([(t.value, 255)])
Acest tipar nu rezolvă problema iluminării neuniforme pe care o rezolvă pragul adaptiv bazat pe filtre; ceea ce rezolvă este întrebarea „la ce valoare ar trebui să tai?” atunci când pragul global este deja abordarea corectă. Pentru o scenă a cărei distincție prim-plan / fundal este bine definită, valoarea pe care o alege Otsu se află de obicei la câteva unități de ceea ce ar alege un om cu ochiul.
5.18.6. Calcul pe o imagine de diferență¶
Un detaliu util despre get_histogram() și get_statistics(): ambele acceptă un cuvânt-cheie difference care primește o altă Image și calculează histograma (sau statisticile) diferenței per pixel între sursă și acea imagine, fără a aloca o imagine de diferență separată. Aceasta este modalitatea ieftină de a întreba „cât de mult s-a schimbat scena de la cadrul de referință?” fără a plăti pentru un apel difference() explicit menit să producă o imagine al cărei unic scop este de a fi măsurată. Pentru un script de detectare a mișcării care rulează continuu, economia se adună.