5.20. Regrese a podobnost¶
Další dvě měření na třídě Image shrnují obraz jako něco jiného než rozložení hodnot pixelů. Lineární regrese prahovaných pixelů dává aplikaci přímku, na kterou může reagovat – klasický vstup pro robota sledujícího čáru. Měření podobnosti dává aplikaci jediné číslo popisující, jak si jsou dva obrazy podobné – přirozený vstup pro regresní test podle referenčního obrazu nebo detektor hrubých změn.
5.20.1. Lineární regrese¶
Když pixely popředí obrazu náhodou tvoří přímku napříč snímkem – páska na dráze, kterou robot sleduje, čára horizontu, okraj silnice nebo chodby – aplikace obvykle nechce každý jednotlivý pixel popředí. Chce přímku nejlépe proloženou všemi těmito pixely, parametrizovanou tak, aby mohla rozhodnout, jak je přímka orientovaná a kde protíná snímek.
get_regression() toto proložení provede. Bere stejnou formu n-tice prahů, jakou používají binary() a find_blobs(), identifikuje každý pixel odpovídající prahu a vrací jediný výsledek line popisující přímku nejlépe proloženou těmito pixely:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
Proložení je lineární regrese metodou Theil-Sen – robustní metoda, která toleruje odlehlé hodnoty lépe než známější metoda nejmenších čtverců. Malá hrstka pixelů daleko od skutečné přímky nezkreslí výsledek tak, jak by to udělala u metody nejmenších čtverců, což odpovídá realitě zašuměného popředí skutečného výstupu prahování.
Výsledek line nese koncové body oříznuté na obdélník obrazu (x1, y1, x2, y2), délku a velikost přímky (length, magnitude) a geometrický popis přímky v polární formě (theta, rho) – úhel přímky od vodorovné osy a její kolmou vzdálenost od počátku. Polární forma je to, co řídicí smyčka obvykle potřebuje: theta říká robotovi, kterým směrem se přímka naklání, rho mu říká, kde přímka protíná obraz, a zpětnovazební smyčka nad těmito dvěma udržuje robota uprostřed čáry.
Hrstka klíčových argumentů ladí robustnost a náklady. x_stride a y_stride přeskakují pixely při proložení – větší kroky činí regresi levnější za cenu proložení menšího počtu pixelů. area_threshold a pixels_threshold odmítají přímky, za kterými nestojí dostatek odpovídajících pixelů. target_size přeškáluje vstup na menší velikost před proložením – regrese běží rychleji na náhradě obrazu o rozměru 80 na 60 bez velké ztráty přesnosti směru přímky.
Pokud nelze proložit žádnou přijatelnou přímku – pokud práh neodpovídá žádným pixelům nebo odpovídá vzoru, který nevypadá jako přímka – metoda vrací None. Skutečný kód pro sledování čáry hlídá každé volání get_regression() kontrolou na None dříve, než sáhne po atributech přímky.
5.20.2. Podobnost obrazů¶
Jiný druh měření: místo otázky „co obraz obsahuje?“ se ptáme „jak si jsou tyto dva obrazy podobné?“. Operace, po které sáhnout, je get_similarity(), která počítá index strukturální podobnosti (SSIM) mezi zdrojovým obrazem a referenčním obrazem.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM je standardní metrika podobnosti obrazů používaná napříč zpracováním obrazu, protože se chová tak, jak se chová lidská intuice o podobnosti – malý posun nebo malá změna jasu sníží skóre nepatrně, zatímco velká strukturální změna (chybějící objekt, jiná scéna) jej sníží dramaticky. Skóre se pohybuje od -1 do +1: +1 znamená, že oba obrazy jsou totožné, 0 znamená, že spolu nesouvisí, a -1 znamená, že jsou strukturálně opačné. Vrácený objekt similarity zpřístupňuje průměrné SSIM napříč obrazem plus směrodatnou odchylku, minimum a maximum skóre jednotlivých dlaždic.
Pro druh porovnání, kde je malé číslo lepší než velké – regresní test, který by měl hlásit nulu při „nic se nezměnilo“ a stoupat s tím, jak se změny hromadí – vrací příznak dssim=True strukturální nepodobnost: průměrné SSIM odečtené od 1, takže návratová hodnota je 0.0 pro totožné obrazy a stoupá s tím, jak se liší.
5.20.3. Případy použití SSIM¶
Dvě běžné aplikace:
Regresní testování podle referenčního obrazu. Testovací rámec zachytí referenční snímek za známých dobrých podmínek a uloží jej jako referenční obraz. Následné testovací běhy zachytávají za stejných podmínek a porovnávají s referenčním obrazem pomocí SSIM. Skóre nad určitým prahem (0.95 nebo 0.98 podle tolerance) je úspěch; pod ním selhání. Testovací rámec nemusí vědět, co se změnilo – signálem je skóre SSIM.
Detekce hrubých změn. Aplikace, která chce hrubší verzi rozdílu snímků – takovou, která ignoruje malé změny jasu, ale reaguje na velké strukturální změny – může použít SSIM vůči referenčnímu snímku namísto difference() po pixelech následovaného prahem. SSIM je méně citlivé na posun osvětlení než rozdíl po pixelech, což z něj činí lepší volbu, když je cílem detekovat „scéna vypadá podstatně jinak“ spíše než „jakýkoli jednotlivý pixel se změnil.“
Obě aplikace používají stejné volání – img.get_similarity(reference) – a spouštějí se na prahu vráceného skóre. Rozdíl je jen v tom, zda je práh vysoký (regresní test, hledající téměř totožnou shodu) nebo nízký (detekce změn, hledající jakoukoli velkou strukturální změnu).
5.20.4. Forma transformace a porovnání¶
Užitečná jemnost: get_similarity() přijímá stejné parametry x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint a transform jako draw_image(). Referenční obraz je těmito parametry umístěn, zvětšen a transformován před spuštěním porovnání SSIM.
To znamená, že aplikace se může zeptat „jak podobná je tato scéna referenčnímu snímku po známém posunu / rotaci / změně měřítka“, aniž by připravovala předem transformovaný referenční obraz. Je to levný způsob, jak vytvořit sledovač, který prohledává prostor parametrů a hlásí, která transformace reference nejlépe odpovídá aktuálnímu snímku.