5.18. Histogramy a statistiky

Vedle operací, které mění pixely obrazu, nese třída Image rodinu metod, které je měří – shrnují rozložení hodnot pixelů, vracejí průměrný a mediánový jas, hledají optimální dělicí hodnotu mezi tmavými a světlými pixely a popisují rozptyl barevných kanálů. Tato měření slouží aplikacím dvěma způsoby: jako vstupy pro kód, který rozhoduje, jaký práh použít, jaký zisk nastavit a jak vypadá tónový profil scény; a jako diagnostické signály – „je scéna dostatečně světlá?“ – na které může aplikace reagovat, aniž by rozhodovala o jakémkoli konkrétním pixelu.

Výchozím bodem téměř každého měření je histogram.

5.18.1. Histogram

Histogram obrazu je počet pixelů s každou možnou hodnotou jasu. U obrazu ve stupních šedi je to seznam počtů indexovaný hodnotami 0255. U barevného obrazu jde o tři takové seznamy – jeden na každý kanál.

get_histogram() jej spočítá:

h = img.get_histogram()

Vrácený objekt je výsledek typu histogram, který zpřístupňuje seznamy intervalů (bins) pro jednotlivé kanály a několik dotazů na vyšší úrovni. Počty v intervalech jsou normalizované tak, aby jejich součet byl 1.0 – histogram popisuje profil rozložení spíše než absolutní počet pixelů, což činí měření porovnatelná napříč obrazy různých velikostí.

U obrazů ve stupních šedi má histogram jeden kanál intervalů, dostupný jako h.bins() (nebo ekvivalentně h[0]). U obrazů RGB565 se histogram počítá v barevném prostoru LAB představeném na stránce o binárním prahování, se třemi kanály intervalů dostupnými jako h.l_bins(), h.a_bins(), h.b_bins() (nebo h[0], h[1], h[2]). LAB je stejná volba, kterou používají metody prahování a sledování; histogramy se s prahy shodují v tom, v jakém prostoru se barva měří.

5.18.2. Intervaly a jejich počet

Výchozí histogram má jeden interval na každou možnou hodnotu pixelu – 256 intervalů pro 8bitový kanál. Někdy je to jemnější rozlišení, než aplikace potřebuje. Klasifikátoru, kterému jde jen o hrubý profil rozložení, může lépe posloužit menší počet intervalů – 32 nebo dokonce 8 intervalů – který běží rychleji a poskytuje čistší výsledek vůči šumu. Počet nastavuje klíčové slovo bins (a pro barvu l_bins, a_bins, b_bins pro jednotlivé kanály):

h = img.get_histogram(bins=32)

Vymezení pomocí ROI a prahu funguje stejně jako u všech ostatních měřicích metod. Předáním roi omezíte histogram na obdélník pixelů; předáním seznamu thresholds zahrnete pouze pixely odpovídající těmto rozsahům. Prahová forma je to, co dělá z „spočítej histogram pouze odpovídajících pixelů“ operaci na jediné volání – běžný vzor, když chce aplikace charakterizovat texturu již detekované oblasti, aniž by musela sama procházet pixely.

Histogram ve stupních šedi vykreslený jako řada sloupců napříč rozsahem jasu 0 až 255. Rozložení má dva vrcholy -- menší tmavý vrchol a větší světlý vrchol -- oddělené jasným údolím. Jsou překryty tři svislé čáry: Otsuův práh v údolí, průměr posunutý směrem k většímu světlému vrcholu a medián dále vpravo, kde kumulativní počet pixelů dosahuje poloviny.

Histogram ve stupních šedi se třemi překrytými souhrnnými měřeními: Otsuův práh (dělicí hodnota, která nejlépe rozděluje tmavé a světlé shluky), průměr a medián. Každé měření říká o stejném rozložení něco jiného.

5.18.3. Statistiky

Histogram je popisem četnosti každé hodnoty; statistiky jsou z něj odvozené číselné souhrny. Objekt statistics vrácený metodou get_statistics() nese standardní sadu:

  • mean – aritmetický průměr hodnot pixelů.

  • median – hodnota, pod níž leží polovina pixelů.

  • mode – nejčastější jednotlivá hodnota.

  • stdev – směrodatná odchylka, míra rozptylu kolem průměru.

  • min a max – nejtmavší a nejsvětlejší přítomné hodnoty pixelů.

  • lq a uq – dělicí hodnoty dolního a horního kvartilu.

U obrazu RGB565 dodávají formy pro jednotlivé kanály (l_mean, a_median, b_mode a tak dále) stejná měření kanál po kanálu.

Většina těchto čísel se uplatní v konkrétních souvislostech. mean a stdev spolu poskytují odhad šumu: scéna, která by měla být rovnoměrná, má malé stdev, zatímco šumící senzor dává téže scéně větší stdev. min a max udávají kontrast obrazu: čím jsou si bližší, tím plošší je scéna; čím dále od sebe, tím větší dynamický rozsah má algoritmus k dispozici. median je robustní střed, když má rozložení odlehlé hodnoty (několik velmi světlých pixelů netáhne medián tak, jako táhne průměr). mode je jediná nejčastější hodnota, užitečná pro nalezení úrovně pozadí obrazu, jehož pozadí pokrývá většinu pixelů.

get_statistics() interně spustí průchod histogramem a poté jej shrne; předání stejných argumentů thresholds a roi jako u dříve spočítaného histogramu vytvoří statistiky pro stejnou množinu pixelů.

5.18.4. Percentily a vyhledávání v CDF

Objekt histogram zpřístupňuje metodu get_percentile(), která převádí zlomek na hodnotu pixelu – hodnotu, pod níž leží požadovaný zlomek pixelů. h.get_percentile(0.5) je medián; h.get_percentile(0.05) a h.get_percentile(0.95) spolu dávají robustní min/max, který ignoruje spodních a horních 5 % jako odlehlé hodnoty.

To je forma, kterou aplikace používá, když chce charakterizovat rozsah hodnot pixelů, aniž by hrstka zatoulaných světlých nebo tmavých pixelů zkreslila výsledek. Robustní min/max z 5. a 95. percentilu je také přirozeným vstupem pro průchod natahování kontrastu – přemapování po pixelech, které pokrývá kapitola Tónové korekce.

5.18.5. Otsuova metoda

Histogramy odpovídají na další otázku, kterou stojí za to zmínit samostatně: máme-li obraz, jehož pixely se dělí do shluku „tmavých“ a „světlých“, jaká je dělicí hodnota mezi nimi? Stránka o prahování již pojmenovala tento mechanismus jeho výsledkem – jediným globálním prahem, který aplikace může předat metodě binary() – ale odložila jak. To jak je Otsuova metoda a sídlí na histogramu.

Intuice: obraz s jasným popředím a pozadím má ve svém histogramu jasu dva shluky s údolím mezi nimi. Správné místo pro prahování je dno údolí – hodnota, kde jsou oba shluky nejlépe oddělené. Otsuova metoda prohledá každou možnou dělicí hodnotu a vybere tu, kde jsou rozptyly uvnitř shluků nejmenší (což je totéž jako říci, že rozptyl mezi shluky je největší), a výsledkem je optimální binární rozdělení pro rozložení daného konkrétního obrazu.

Objekt histogram zpřístupňuje Otsuovu metodu přes get_threshold:

h = img.get_histogram()
t = h.get_threshold()

Vrácený objekt threshold má atributy value (pro stupně šedi) nebo l_value / a_value / b_value (pro barvu) nesoucí zvolenou dělicí hodnotu. Předání výsledku rovnou zpět metodě binary() poskytne samoladící globální práh, jehož dělicí hodnotu si volí samotný obraz:

img.binary([(t.value, 255)])

Tento vzor neřeší problém nerovnoměrného osvětlení, který řeší adaptivní práh založený na filtru; řeší otázku „jakou hodnotu mám použít jako řez?“, když je globální prahování již ten správný přístup. U scény, jejíž rozlišení popředí / pozadí je dobře definované, je hodnota, kterou Otsu vybere, obvykle v rozmezí několika jednotek od toho, co by člověk vybral okem.

5.18.6. Výpočet na rozdílovém obrazu

Užitečný detail u get_histogram() a get_statistics(): obě přijímají klíčové slovo difference, které bere další Image a počítá histogram (nebo statistiky) rozdílu po pixelech mezi zdrojem a tímto obrazem, aniž by alokovaly samostatný rozdílový obraz. To je levný způsob, jak se zeptat „jak moc se scéna změnila od referenčního snímku?“, aniž byste platili za explicitní volání difference(), jež by vytvořilo obraz, jehož jediným účelem je být změřen. U nepřetržitě běžícího skriptu pro detekci pohybu se úspora sčítá.