5.18. Hisztogramok és statisztikák¶
A képpontokat módosító műveletek mellett az Image osztály olyan metódusok családját is hordozza, amelyek mérik azokat – összegzik a képpontértékek eloszlását, visszaadják az átlagos és medián fényerőt, megkeresik a sötét és világos képpontok közötti optimális határt, valamint jelzik a színcsatornák szórását. A mérések kétféleképpen táplálják az alkalmazásokat: egyrészt bemenetként annak a kódnak, amely eldönti, milyen küszöbértéket használjon, milyen erősítést állítson be, hogyan néz ki a jelenet tonális profilja; másrészt diagnosztikai jelzésként – „elég világos-e a jelenet?” –, amelyre az alkalmazás úgy reagálhat, hogy egyetlen konkrét képpontról sem hoz döntést.
Szinte minden mérés kiindulópontja a hisztogram.
5.18.1. A hisztogram¶
A kép hisztogramja annak megszámolása, hogy hány képpont rendelkezik az egyes lehetséges fényerőértékekkel. Egy szürkeárnyalatos kép esetében ez a 0 és 255 közötti értékekkel indexelt számlálók listája. Egy színes kép esetében három ilyen lista – csatornánként egy.
A get_histogram() kiszámol egyet:
h = img.get_histogram()
A visszaadott objektum egy histogram eredmény, amely felfedi a csatornánkénti rekeszlistákat és néhány magas szintű lekérdezést rajtuk. A rekeszek értékei normalizáltak, így összegük 1.0 – a hisztogram az eloszlás profilját írja le, nem az abszolút képpontszámot, ami a méréseket eltérő méretű képek között is összehasonlíthatóvá teszi.
Szürkeárnyalatos képeknél a hisztogram egyetlen rekeszcsatornával rendelkezik, amely a h.bins() (vagy ezzel egyenértékűen a h[0]) révén érhető el. RGB565 képeknél a hisztogram a binárisküszöbölés oldalon bemutatott LAB színtérben kerül kiszámításra, három rekeszcsatornával, amelyek a h.l_bins(), h.a_bins(), h.b_bins() (vagy h[0], h[1], h[2]) révén érhetők el. A LAB ugyanaz a választás, amelyet a küszöbölési és követési metódusok használnak; a hisztogramok egyetértenek a küszöbértékekkel abban, hogy a szín milyen térben mérendő.
5.18.2. Rekeszek és a rekeszek száma¶
Az alapértelmezett hisztogramban minden lehetséges képpontértékre egy rekesz jut – egy 8 bites csatornánál 256 rekesz. Néha ez finomabb felbontás, mint amennyire az alkalmazásnak szüksége van. Egy osztályozónak, amely csak az eloszlás durva profiljával törődik, jobban megfelelhet egy kisebb rekeszszám – 32 vagy akár 8 rekesz –, amely egyrészt gyorsabban fut, másrészt tisztább, zajjal szembeni eredményt ad. A bins kulcsszó (és színhez a csatornánkénti l_bins, a_bins, b_bins) állítja be a számot:
h = img.get_histogram(bins=32)
A ROI- és küszöbérték-hatókör ugyanúgy működik, mint minden más mérési metódusnál. Adj át egy roi értéket, hogy a hisztogramot egy képpont-téglalapra korlátozd; adj át egy thresholds listát, hogy csak az ezeknek a tartományoknak megfelelő képpontokat foglald bele. A küszöbértékes forma teszi a „számítsd ki csak a megfelelő képpontok hisztogramját” műveletet egyetlen hívássá – gyakori minta, amikor egy alkalmazás egy már észlelt terület textúráját akarja jellemezni anélkül, hogy magának kellene végigjárnia a képpontokat.
Egy szürkeárnyalatos hisztogram három összegző méréssel rávetítve: az Otsu-küszöbérték (a határvonal, amely legjobban szétválasztja a sötét és világos klasztereket), az átlag és a medián. Mindegyik mérés mást mond el ugyanarról az eloszlásról.¶
5.18.3. Statisztikák¶
A hisztogram minden érték gyakoriságának leírása; a statisztikák az ebből származtatott numerikus összegzések. A get_statistics() által visszaadott statistics objektum a szokásos készletet hordozza:
mean– a képpontértékek számtani átlaga.median– az az érték, amely alatt a képpontok fele helyezkedik el.mode– a leggyakoribb egyetlen érték.stdev– a szórás, az átlag körüli szóródás mértéke.minésmax– a jelen lévő legvilágosabb és legsötétebb képpontértékek.lqésuq– az alsó és felső kvartilis határértékek.
Egy RGB565 kép esetében a csatornánkénti formák (l_mean, a_median, b_mode és így tovább) ugyanazokat a méréseket szolgáltatják csatornánként.
E számok többsége konkrét kontextusokban merül fel. A mean és a stdev együtt zajbecslést ad: egy olyan jelenet, amelynek egyenletesnek kellene lennie, kis stdev értékkel rendelkezik, míg egy zajos érzékelő ugyanannak a jelenetnek nagyobb stdev értéket ad. A min és a max a kép kontrasztját adja: minél közelebb vannak, annál laposabb a jelenet; minél távolabb vannak, annál nagyobb dinamikatartománnyal dolgozhat az algoritmus. A median a robusztus középpont, amikor az eloszlásban kiugró értékek vannak (néhány nagyon világos képpont nem húzza el a mediánt úgy, ahogy az átlagot elhúzza). A mode az egyetlen leggyakoribb érték, amely hasznos egy olyan kép háttérszintjének megtalálásához, amelynek háttere a képpontok többségét lefedi.
A get_statistics() belül lefuttatja a hisztogram-menetet, majd összegzi azt; ha ugyanazokat a thresholds és roi argumentumokat adjuk át, mint egy korábban kiszámított hisztogramnál, akkor ugyanarra a képpontkészletre vonatkozó statisztikákat kapjuk.
5.18.4. Percentilisek és CDF-kikeresések¶
A histogram objektum egy get_percentile() metódust kínál, amely egy törtszámot képpontértékké alakít – azzá az értékké, amely alatt a képpontok kért hányada helyezkedik el. A h.get_percentile(0.5) a medián; a h.get_percentile(0.05) és a h.get_percentile(0.95) együtt robusztus min/max értéket ad, amely az alsó és felső 5%-ot kiugró értékként figyelmen kívül hagyja.
Ezt a formát használja egy alkalmazás, amikor a képpontértékek tartományát akarja jellemezni anélkül, hogy hagyná, hogy néhány elszórt világos vagy sötét képpont torzítsa a választ. Az 5. és 95. percentilisből származó robusztus min/max egyúttal a kontrasztnyújtási menet természetes bemenete is – a képpontonkénti újraleképezés, amelyet a Tonális korrekciók tárgyal.
5.18.5. Otsu-módszer¶
A hisztogramok egy másik, önmagában is említésre méltó kérdésre adnak választ: ha adott egy kép, amelynek képpontjai egy „sötét” és egy „világos” klaszterre oszlanak, mi a határvonal közöttük? A küszöbölési oldal már megnevezte a mechanizmust az eredménye alapján – egyetlen globális küszöbérték, amelyet az alkalmazás átadhat a binary() metódusnak –, de elhalasztotta a hogyant. A hogyan az Otsu-módszer, és a hisztogramon él.
Az intuíció: egy tiszta előtérrel és háttérrel rendelkező képnek két klasztere van a fényerő-hisztogramjában, közöttük egy völggyel. A küszöbölés helyes helye a völgy alja – az az érték, ahol a két klaszter a legjobban szétválik. Az Otsu-módszer minden lehetséges határvonalat végigvizsgál, és azt választja ki, ahol a klasztereken belüli szórások a legkisebbek (ami ugyanaz, mintha azt mondanánk, hogy a klaszterek közötti szórás a legnagyobb), az eredmény pedig az adott kép eloszlásához tartozó optimális bináris felosztás.
A histogram objektum az Otsut a get_threshold révén kínálja fel:
h = img.get_histogram()
t = h.get_threshold()
A visszaadott threshold objektumnak value (szürkeárnyalatoshoz) vagy l_value / a_value / b_value (színhez) attribútumai vannak, amelyek a kiválasztott határvonalat hordozzák. Az eredményt közvetlenül visszatáplálva a binary() metódusba egy önhangoló globális küszöbértéket kapunk, amelynek határvonalát maga a kép választja meg:
img.binary([(t.value, 255)])
Ez a minta nem oldja meg az egyenetlen megvilágítás problémáját, amelyet a szűrőalapú adaptív küszöbölés old meg; amit megold, az a „milyen értéknél vágjak?” kérdés, amikor a globális küszöbölés már eleve a helyes megközelítés. Egy olyan jelenetnél, amelynek előtér/háttér megkülönböztetése jól meghatározott, az Otsu által választott érték általában néhány egységen belül van attól, amit egy ember szemmel választana.
5.18.6. Számítás különbségi képen¶
Egy hasznos részlet a get_histogram() és a get_statistics() metódusokról: mindkettő elfogad egy difference kulcsszót, amely egy másik Image objektumot vesz, és a forrás és az adott kép közötti képpontonkénti különbség hisztogramját (vagy statisztikáit) számítja ki anélkül, hogy külön különbségi képet allokálna. Ez az olcsó módja annak, hogy megkérdezzük, „mennyit változott a jelenet a referencia-képkocka óta?”, anélkül hogy egy explicit difference() hívásért fizetnénk, amely egy olyan képet állít elő, amelynek egyetlen célja, hogy megmérjük. Egy folyamatosan futó mozgásérzékelő szkript esetében a megtakarítás összeadódik.