5.18. Histogrammit ja tilastot¶
Niiden toimintojen ohella, jotka muuttavat kuvan pikseleitä, Image-luokka sisältää joukon menetelmiä, jotka mittaavat niitä – tekevät yhteenvedon pikseliarvojen jakaumasta, palauttavat keskimääräisen ja mediaanikirkkauden, etsivät optimaalisen rajan tummien ja kirkkaiden pikselien välillä sekä raportoivat värikanavien hajonnan. Mittaukset palvelevat sovelluksia kahdella tavalla: syötteinä koodille, joka päättää, mitä kynnysarvoa käytetään, mikä vahvistus asetetaan ja miltä näkymän sävyprofiili näyttää; sekä diagnostisina signaaleina – ”onko näkymä riittävän kirkas?” – joiden perusteella sovellus voi toimia ilman, että se tekee päätöstä mistään tietystä pikselistä.
Lähtökohta lähes jokaiselle mittaukselle on histogrammi.
5.18.1. Histogrammi¶
Kuvan histogrammi on laskelma siitä, kuinka monella pikselillä on kukin mahdollinen kirkkausarvo. Harmaasävykuvalle se on luettelo lukumääristä, jotka on indeksoitu arvoilla 0 – 255. Värikuvalle se on kolme tällaista luetteloa – yksi kullekin kanavalle.
get_histogram() laskee sellaisen:
h = img.get_histogram()
Palautettu objekti on histogram-tulos, joka tarjoaa kanavakohtaiset lokeroluettelot ja muutamia korkean tason kyselyitä niihin. Lokeroiden lukumäärät on normalisoitu niin, että niiden summa on 1.0 – histogrammi kuvaa jakauman profiilia eikä absoluuttista pikselimäärää, mikä tekee mittauksista vertailukelpoisia eri kokoisten kuvien välillä.
Harmaasävykuvilla histogrammissa on yksi lokerokanava, joka on saatavilla muodossa h.bins() (tai vastaavasti h[0]). RGB565-kuvilla histogrammi lasketaan LAB-väriavaruudessa, joka esiteltiin binäärikynnystyssivulla, ja kolme lokerokanavaa ovat saatavilla muodoissa h.l_bins(), h.a_bins(), h.b_bins() (tai h[0], h[1], h[2]). LAB on sama valinta, jota kynnys- ja seurantamenetelmät käyttävät; histogrammit ovat yhtä mieltä kynnysarvojen kanssa siitä, missä avaruudessa väriä mitataan.
5.18.2. Lokerot ja lokeroiden lukumäärä¶
Oletushistogrammissa on yksi lokero kutakin mahdollista pikseliarvoa kohti – 256 lokeroa 8-bittiselle kanavalle. Joskus tämä on hienompi resoluutio kuin sovellus tarvitsee. Luokitin, joka välittää vain jakauman karkeasta profiilista, voi olla parempi palveltu pienemmällä lokeromäärällä – 32 tai jopa 8 lokeroa – mikä sekä toimii nopeammin että tuottaa puhtaamman tuloksen kohinaa vastaan. bins-avainsana (ja kanavakohtaiset l_bins, a_bins, b_bins värille) asettaa lukumäärän:
h = img.get_histogram(bins=32)
ROI:n ja kynnysarvon rajaus toimivat samalla tavalla kuin kaikilla muillakin mittausmenetelmillä. Anna roi rajataksesi histogrammin pikselien suorakulmioon; anna thresholds-luettelo sisällyttääksesi vain ne pikselit, jotka vastaavat näitä alueita. Kynnysarvomuoto tekee ”lasketaan histogrammi vain vastaavista pikseleistä” -toiminnosta yhden kutsun operaation – yleinen kaava, kun sovellus haluaa kuvata jo havaitun alueen tekstuuria joutumatta itse käymään pikseleitä läpi.
Harmaasävyhistogrammi, jonka päälle on asetettu kolme yhteenvetomittausta: Otsun kynnysarvo (raja, joka jakaa parhaiten tummat ja kirkkaat ryppäät), keskiarvo ja mediaani. Kukin mittaus kertoo jotain erilaista samasta jakaumasta.¶
5.18.3. Tilastot¶
Histogrammi on kuvaus jokaisen arvon esiintyvyydestä; tilastot ovat siitä johdetut numeeriset yhteenvedot. get_statistics()-menetelmän palauttama statistics-objekti sisältää vakiojoukon:
mean– pikseliarvojen aritmeettinen keskiarvo.median– arvo, jonka alapuolelle puolet pikseleistä jää.mode– yleisin yksittäinen arvo.stdev– keskihajonta, keskiarvon ympärillä olevan hajonnan mitta.minjamax– läsnä olevat kirkkaimmat ja tummimmat pikseliarvot.lqjauq– alemman ja ylemmän kvartiilin rajat.
RGB565-kuvalle kanavakohtaiset muodot (l_mean, a_median, b_mode ja niin edelleen) tuottavat samat mittaukset kanava kanavalta.
Useimmat näistä luvuista tulevat esiin tietyissä yhteyksissä. mean ja stdev yhdessä antavat kohinaestimaatin: tasaiselta näyttävän näkymän stdev on pieni, kun taas kohiseva sensori antaa samalle näkymälle suuremman stdev:n. min ja max antavat kuvan kontrastin: mitä lähempänä ne ovat toisiaan, sitä litteämpi näkymä; mitä kauempana, sitä enemmän dynamiikkaa algoritmilla on käytössään. median on robusti keskipiste, kun jakaumassa on poikkeavia arvoja (muutama hyvin kirkas pikseli ei vedä mediaania samalla tavalla kuin se vetää keskiarvoa). mode on yleisin yksittäinen arvo, hyödyllinen sellaisen kuvan taustatason löytämiseen, jonka tausta kattaa suurimman osan pikseleistä.
get_statistics() suorittaa histogrammilaskennan sisäisesti ja tekee siitä sitten yhteenvedon; samojen thresholds- ja roi-argumenttien antaminen kuin aiemmin lasketulle histogrammille tuottaa tilastot samalle pikselijoukolle.
5.18.4. Persentiilit ja CDF-haut¶
histogram-objekti tarjoaa get_percentile()-menetelmän, joka muuntaa murto-osan pikseliarvoksi – arvoksi, jonka alapuolelle pyydetty murto-osa pikseleistä jää. h.get_percentile(0.5) on mediaani; h.get_percentile(0.05) ja h.get_percentile(0.95) antavat yhdessä robustin min/max-arvon, joka jättää huomiotta alimmat ja ylimmät 5 % poikkeavina arvoina.
Tätä muotoa sovellus käyttää, kun se haluaa kuvata pikseliarvojen aluetta päästämättä kourallista harhautuneita kirkkaita tai tummia pikseleitä vinouttamaan vastausta. Robusti min/max 5. ja 95. persentiilistä on myös luonnollinen syöte kontrastinvenytysvaiheelle – pikselikohtaiselle uudelleenkuvaukselle, jonka Sävykorjaukset kattaa.
5.18.5. Otsun menetelmä¶
Histogrammit vastaavat toiseen kysymykseen, joka kannattaa nostaa esiin omanaan: kun annetaan kuva, jonka pikselit jakautuvat ”tummaan” ja ”kirkkaaseen” ryppääseen, mikä on niiden välinen raja? Kynnystyssivu jo nimesi mekanismin sen tuloksen kautta – yksittäisen globaalin kynnysarvon, jonka sovellus voi antaa binary()-menetelmälle – mutta lykkäsi kuinka-osuutta. Kuinka on Otsun menetelmä, ja se sijaitsee histogrammissa.
Intuitio: kuvalla, jossa on selvä etuala ja tausta, on kaksi rypästä kirkkaushistogrammissaan, ja niiden välissä on laakso. Oikea paikka kynnystää on laakson pohja – arvo, jossa kaksi rypästä erottuvat parhaiten. Otsun menetelmä etsii jokaisen mahdollisen rajan ja valitsee sen, jossa ryppäiden sisäiset varianssit ovat pienimmät (mikä on sama asia kuin sanoa, että ryppäiden välinen varianssi on suurin), ja tulos on optimaalinen binäärinen jako kyseisen kuvan jakaumalle.
histogram-objekti tarjoaa Otsun menetelmän get_threshold-kautta:
h = img.get_histogram()
t = h.get_threshold()
Palautetulla threshold-objektilla on value (harmaasävylle) tai l_value / a_value / b_value (värille) -attribuutit, jotka kantavat valittua rajaa. Tuloksen syöttäminen suoraan takaisin binary()-menetelmälle antaa itsesäätyvän globaalin kynnysarvon, jonka rajan valitsee kuva itse:
img.binary([(t.value, 255)])
Tämä kaava ei ratkaise epätasaisen valaistuksen ongelmaa, jonka suodatinpohjainen mukautuva kynnysarvo ratkaisee; sen sijaan se ratkaisee ”millä arvolla minun pitäisi leikata?” -kysymyksen, kun globaali kynnystys on jo oikea lähestymistapa. Näkymälle, jonka etuala/tausta-erottelu on hyvin määritelty, Otsun valitsema arvo on yleensä muutaman yksikön sisällä siitä, minkä ihminen valitsisi silmämääräisesti.
5.18.6. Laskenta erotuskuvasta¶
Hyödyllinen yksityiskohta get_histogram()- ja get_statistics()-menetelmistä: molemmat hyväksyvät difference-avainsanan, joka ottaa toisen Image-objektin ja laskee histogrammin (tai tilastot) lähteen ja kyseisen kuvan välisestä pikselikohtaisesta erotuksesta ilman, että erillistä erotuskuvaa varataan. Tämä on edullinen tapa kysyä ”kuinka paljon näkymä on muuttunut vertailukehyksestä?” maksamatta erillisestä difference()-kutsusta, joka tuottaisi kuvan, jonka ainoa tarkoitus on tulla mitatuksi. Jatkuvasti toimivassa liiketunnistusskriptissä säästö kertyy.