5.20. Regresija i sličnost¶
Još dva mjerenja na klasi Image sažimaju sliku kao nešto drugo od distribucije vrijednosti piksela. Linearna regresija pragovanih piksela daje aplikaciji liniju na koju može reagirati – klasični ulaz za robota koji slijedi liniju. Mjerenje sličnosti daje aplikaciji jedan broj koji opisuje koliko su dvije slike slične – prirodan ulaz za regresijski test sa zlatnom slikom ili detektor velikih promjena.
5.20.1. Linearna regresija¶
Kada pikseli prednjeg plana slike slučajno tvore liniju preko sličice – traka na stazi koju robot slijedi, linija horizonta, rub ceste ili hodnika – aplikacija obično ne želi svaki pojedini piksel prednjeg plana. Želi liniju najboljeg pristajanja kroz sve njih, parametriziranu tako da može odlučiti kako je linija orijentirana i gdje presijeca sličicu.
get_regression() izvodi to pristajanje. Prima isti oblik n-torke praga koji koriste binary() i find_blobs(), identificira svaki piksel koji odgovara pragu i vraća jedan rezultat line koji opisuje liniju najboljeg pristajanja kroz te piksele:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
Pristajanje je Theil-Sen linearna regresija – robusna metoda koja bolje podnosi netipične vrijednosti od poznatijeg pristajanja najmanjih kvadrata. Mala šačica piksela daleko od prave linije ne iskrivljuje rezultat onako kako bi to činila kod najmanjih kvadrata, što odgovara stvarnosti šumnog prednjeg plana stvarnog izlaza praga.
Rezultat line nosi krajnje točke odrezane na pravokutnik slike (x1, y1, x2, y2), duljinu i magnitudu linije (length, magnitude) te geometrijski opis linije u polarnom obliku (theta, rho) – kut linije od vodoravne i njezinu okomitu udaljenost od ishodišta. Polarni oblik je ono što upravljačka petlja obično želi: theta govori robotu na koju stranu je linija nagnuta, rho govori gdje linija presijeca sliku, a povratna petlja na to dvoje održava robota centriranim na liniji.
Šačica ključnih argumenata ugađa robusnost i cijenu. x_stride i y_stride preskaču piksele tijekom pristajanja – veći koraci čine regresiju jeftinijom uz cijenu pristajanja manjeg broja piksela. area_threshold i pixels_threshold odbacuju linije iza kojih nema dovoljno odgovarajućih piksela. target_size ponovno skalira ulaz na manju veličinu prije pristajanja – regresija se brže izvodi na surogatu slike veličine 80 puta 60 bez velikog gubitka u točnosti smjera linije.
Ako se nije mogla pristati nijedna prihvatljiva linija – ako prag nije odgovarao nijednom pikselu ili je odgovarao uzorku koji ne izgleda kao linija – metoda vraća None. Pravi kod za slijeđenje linije čuva svaki poziv get_regression() provjerom None prije nego što posegne za atributima linije.
5.20.2. Sličnost slika¶
Drugačija vrsta mjerenja: umjesto pitanja „što slika sadrži?”, pitamo „koliko su slične ove dvije slike?”. Operacija za koju treba posegnuti je get_similarity(), koja izračunava Indeks strukturne sličnosti (SSIM) između izvorne slike i referentne slike.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM je standardna metrika sličnosti slika korištena u obradi slike jer se ponaša onako kako se ponaša ljudska intuicija o sličnosti – mali pomak ili mala promjena svjetline blago smanjuje rezultat, dok velika strukturna promjena (nedostajući objekt, drugačija scena) drastično ga smanjuje. Rezultat se kreće od -1 do +1: +1 znači da su dvije slike identične, 0 znači da su nepovezane, a -1 znači da su strukturno suprotne. Vraćeni objekt similarity izlaže srednji SSIM preko slike, plus standardnu devijaciju, min i max rezultata po pločici.
Za vrstu usporedbe gdje je mali broj bolji od velikog – regresijski test koji bi trebao prijaviti nulu na „ništa nije promijenjeno” i rasti kako se promjene nakupljaju – zastavica dssim=True vraća strukturnu nesličnost: srednji SSIM oduzet od 1, tako da je povratna vrijednost 0.0 za identične slike i raste kako se razlikuju.
5.20.3. Slučajevi upotrebe za SSIM¶
Dvije uobičajene primjene:
Regresijsko testiranje sa zlatnom slikom. Testni okvir hvata referentnu sličicu pod poznato dobrim uvjetima i pohranjuje je kao zlatnu sliku. Naredna testna izvođenja hvataju pod istim uvjetima i uspoređuju sa zlatnom slikom pomoću SSIM-a. Rezultat iznad nekog praga (0.95 ili 0.98 ovisno o toleranciji) je prolaz; ispod je neuspjeh. Testni okvir ne treba znati što se promijenilo – SSIM rezultat je signal.
Detekcija velikih promjena. Aplikacija koja želi grublju verziju razlikovanja sličica – onu koja zanemaruje male promjene svjetline, ali reagira na velike strukturne promjene – može koristiti SSIM naspram referentne sličice umjesto difference() po pikselu nakon kojeg slijedi prag. SSIM je manje osjetljiv na pomicanje osvjetljenja od razlikovanja po pikselu, što ga čini boljim izborom kada je cilj detektirati „scena izgleda bitno drugačije” umjesto „bilo koji pojedini piksel se promijenio.”
Obje primjene koriste isti poziv – img.get_similarity(reference) – i okidaju na pragu vraćenog rezultata. Razlika je samo u tome je li prag visok (regresijski test, traženje gotovo identičnog podudaranja) ili nizak (detekcija promjene, traženje bilo koje velike strukturne promjene).
5.20.4. Oblik transformiraj-pa-usporedi¶
Korisna suptilnost: get_similarity() prihvaća iste parametre x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint i transform kao draw_image(). Referentna slika se pozicionira, skalira i transformira tim parametrima prije nego što se SSIM usporedba pokrene.
To znači da aplikacija može upitati „koliko je ova scena slična referentnoj sličici nakon poznatog pomaka / rotacije / skaliranja” bez pripreme unaprijed transformirane referentne slike. To je jeftin način za izgradnju pratitelja koji pretražuje prostor parametara i izvještava koja transformacija reference najbolje odgovara trenutnoj sličici.