5.20. Regresszió és hasonlóság

Az Image osztály két további mérése a képet a képpontértékek eloszlásától eltérő valamiként összegzi. A küszöbölt képpontok lineáris regressziója egy vonalat ad az alkalmazásnak, amellyel dolgozhat – a vonalkövető robot klasszikus bemenetét. A hasonlóságmérés egyetlen számot ad az alkalmazásnak, amely leírja, mennyire hasonlít két kép – egy aranykép-regressziós teszt vagy egy durvaváltozás-érzékelő természetes bemenetét.

5.20.1. Lineáris regresszió

Amikor egy kép előtér-képpontjai történetesen egy vonalat alkotnak a képkockán keresztül – a szalag azon a pályán, amelyet egy robot követ, a horizont vonala, egy út vagy egy folyosó éle –, az alkalmazás általában nem minden egyes előtér-képpontot akar. A rajtuk áthaladó legjobban illeszkedő vonalat akarja, úgy paraméterezve, hogy eldönthesse, hogyan áll a vonal, és hol metszi a képkockát.

A get_regression() végzi el ezt az illesztést. Ugyanazt a küszöbérték-tuple formát veszi, mint amit a binary() és a find_blobs() használ, azonosítja a küszöbértéknek megfelelő minden képpontot, és egyetlen line eredményt ad vissza, amely az ezeken a képpontokon áthaladó legjobban illeszkedő vonalat írja le:

line = img.get_regression([(0, 60)])
if line:
    img.draw_line((line.x1(), line.y1(),
                   line.x2(), line.y2()),
                  color=(255, 0, 0))

Az illesztés Theil-Sen lineáris regresszió – egy robusztus módszer, amely jobban tolerálja a kiugró értékeket, mint az ismertebb legkisebb négyzetes illesztés. Néhány, a valódi vonaltól távoli képpont nem torzítja el az eredményt úgy, ahogy a legkisebb négyzetek esetén tenné, ami megfelel egy valós küszöbkimenet zajos előterének valóságával.

A line eredmény hordozza a kép téglalapjára levágott végpontokat (x1, y1, x2, y2), a vonal hosszát és nagyságát (length, magnitude), valamint a vonal geometriai leírását poláris formában (theta, rho) – a vonal vízszinteshez viszonyított szögét és az origótól való merőleges távolságát. A poláris forma az, amit egy szabályozási hurok általában akar: a theta megmondja a robotnak, melyik irányba dől a vonal, a rho megmondja neki, hol metszi a vonal a képet, és a kettőre épülő visszacsatolási hurok a vonalon tartja középen a robotot.

Néhány kulcsszó-argumentum hangolja a robusztusságot és a költséget. Az x_stride és az y_stride képpontokat ugrik át az illesztés során – a nagyobb lépésközök olcsóbbá teszik a regressziót, kevesebb képpont illesztésének árán. Az area_threshold és a pixels_threshold elutasítja azokat a vonalakat, amelyek mögött nincs elég megfelelő képpont. A target_size átméretezi a bemenetet egy kisebb méretre az illesztés előtt – a regresszió gyorsabban fut a kép egy 80-szor-60-as helyettesítőjén, anélkül hogy a vonal irányának pontossága sokat veszítene.

Ha nem sikerült elfogadható vonalat illeszteni – ha a küszöbérték egyetlen képpontnak sem felelt meg, vagy olyan mintának felelt meg, amely nem néz ki vonalnak –, a metódus a None értéket adja vissza. A valós vonalkövető kód minden get_regression() hívást egy None ellenőrzéssel véd, mielőtt a vonal attribútumaihoz nyúlna.

5.20.2. Képhasonlóság

Egy másfajta mérés: ahelyett, hogy azt kérdeznénk, „mit tartalmaz a kép?”, azt kérdezzük, „mennyire hasonlít ez a két kép?”. A művelet, amelyhez nyúlni érdemes, a get_similarity(), amely a strukturális hasonlósági indexet (SSIM) számítja ki a forráskép és egy referenciakép között.

s = img.get_similarity(reference)
print(s.mean, s.stdev)

Az SSIM a képfeldolgozásban széles körben használt standard képhasonlósági metrika, mert úgy viselkedik, ahogy a hasonlóságról alkotott emberi intuíció – egy kis eltolás vagy egy kis fényerőváltozás kissé csökkenti a pontszámot, míg egy nagy strukturális változás (hiányzó objektum, eltérő jelenet) drámaian csökkenti azt. A pontszám a -1 és a +1 között mozog: a +1 azt jelenti, hogy a két kép azonos, a 0 azt, hogy nincs közöttük kapcsolat, a -1 pedig azt, hogy strukturálisan ellentétesek. A visszaadott similarity objektum felfedi a kép átlagos SSIM értékét, valamint a csempénkénti pontszámok szórását, minimumát és maximumát.

Az olyan összehasonlításnál, ahol a kis szám jobb a nagynál – egy regressziós teszt, amelynek a „semmi sem változott” esetében nullát kell jelentenie, és emelkednie kell, ahogy a változások felhalmozódnak –, a dssim=True jelző a strukturális eltérést adja vissza: az átlagos SSIM értéket 1-ből kivonva, így a visszaadott érték azonos képeknél 0.0, és emelkedik, ahogy a képek eltérnek egymástól.

5.20.3. Az SSIM felhasználási esetei

A két gyakori alkalmazás:

Aranykép-regressziós tesztelés. Egy tesztkeretrendszer rögzít egy referencia-képkockát ismerten jó körülmények között, és aranyképként tárolja. A későbbi tesztfutások ugyanazon körülmények között rögzítenek, és SSIM révén hasonlítják össze az aranyképpel. Egy bizonyos küszöbérték feletti pontszám (a tűréstől függően 0.95 vagy 0.98) sikert jelent; az alatti hibát. A tesztkeretrendszernek nem kell tudnia, mi változott – az SSIM pontszám a jelzés.

Durvaváltozás-érzékelés. Egy alkalmazás, amely a képkocka-különbségezés egy durvább változatát szeretné – olyat, amely figyelmen kívül hagyja a kis fényerőváltozásokat, de reagál a nagy strukturális változásokra –, használhatja az SSIM-et egy referencia-képkockával szemben a képpontonkénti difference() és az azt követő küszöbölés helyett. Az SSIM kevésbé érzékeny a megvilágítás elsodródására, mint a képpontonkénti különbségezés, ami jobb választássá teszi, amikor a cél a „a jelenet érdemben másnak tűnik” észlelése, nem pedig a „bármely egyedi képpont megváltozott”.

Mindkét alkalmazás ugyanazt a hívást használja – img.get_similarity(reference) –, és a visszaadott pontszám egy küszöbértékére indul el. A különbség csak az, hogy a küszöbérték magas-e (regressziós teszt, amely közel azonos egyezést keres) vagy alacsony (változásérzékelés, amely bármilyen nagy strukturális változást keres).

5.20.4. A transzformáló-és-összehasonlító forma

Egy hasznos finomság: a get_similarity() ugyanazokat az x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint és transform paramétereket fogadja el, mint a draw_image(). A referenciakép pozicionálása, méretezése és transzformálása ezekkel a paraméterekkel az SSIM-összehasonlítás lefutása előtt történik.

Ez azt jelenti, hogy egy alkalmazás megkérdezheti, „mennyire hasonló ez a jelenet egy referencia-képkockához egy ismert elmozdulás / elforgatás / méretezés után„, anélkül hogy egy előre transzformált referenciaképet kellene előkészítenie. Ez az olcsó módja annak, hogy felépítsünk egy követőt, amely egy paramétertérben keres, és jelenti, hogy a referencia melyik transzformációja illeszkedik legjobban az aktuális képkockához.