5.25. Pronalaženje mrlja¶
Pragom je snimljena sličica pretvorena u binarnu masku: svaki piksel ili prolazi test praga ili ne prolazi. To odgovara na pitanje koje boje važne za aplikaciju se pojavljuju u sceni, ali ne i gdje – maska je samo more jedinica i nula. Sljedeći korak je detekcija mrlja: prolazak kroz masku, pronalaženje povezanih područja prolazećih piksela i vraćanje svakog od njih kao objekta s položajem, veličinom, orijentacijom i ostalim svojstvima na koja aplikacija može reagirati.
find_blobs() je glavna metoda za taj korak i najčešća je ulazna točka u svijet objekata rezultata modula image. Praćenje obojene loptice, slijeđenje crte naslikane na podu, brojanje koliko svijetlih točaka termalni senzor vidi, odlučivanje je li plavi LED upaljen ili ugašen – isti poziv pokriva sve njih. Ulazi se mijenjaju (pragovi, pretraživano područje, filtri primijenjeni na rezultat), ali obrazac poziva je isti.
5.25.1. Osnovni poziv¶
find_blobs prima popis pragova i vraća popis objekata rezultata mrlja:
thresholds = [(30, 100, 15, 127, 15, 127)] # LAB threshold for red
blobs = img.find_blobs(thresholds)
for b in blobs:
img.draw_rectangle(b.rect, color=(255, 0, 0))
img.draw_cross(b.cx, b.cy, color=(255, 0, 0))
Svaka n-torka praga ima isti oblik kao pragovi proslijeđeni metodi binary() – šest unosa (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi) za RGB565 sliku (granice su u LAB-u), dva unosa (lo, hi) za sliku u sivim tonovima. U jednom pozivu može se dati do 32 praga, što metodu find_blobs() čini tako fleksibilnom: crveni, zeleni i plavi svjetionici mogu se pratiti istovremeno, svaki pridonoseći svojim mrljama vraćenom popisu, a svojstvo code svake mrlje označava kojem pragu odgovara.
Pozivi draw_rectangle() i draw_cross() iznad označavaju snimljenu sličicu za pregled u IDE-u. Rezultat mrlje već nosi b.rect (granični okvir kao 4-torku) te b.cx / b.cy (cjelobrojni centroid), pa je crtanje detekcije natrag u sličicu pitanje dvaju poziva metoda.
5.25.2. Što rezultat sadrži¶
Svaka Blob je n-torka atributa koja objedinjuje sve što je detektor izmjerio o području. Svojstva se dijele u četiri skupine.
Skupina graničnog okvira i centroida – x, y, w, h, rect, cx, cy, cxf, cyf – opisuje položaj mrlje. rect je 4-torka (x, y, w, h) koju metode crtanja očekuju; cx i cy su centroid u cjelobrojnim pikselskim koordinatama; cxf i cyf su centroid u sub-pikselskim float koordinatama, korisni kada uzvodna kalibracija mari za razlomljene položaje.
Deskriptori oblika – pixels, area, density, perimeter, roundness, elongation, compactness, rotation – opisuju kako mrlja izgleda. pixels je broj prolazećih piksela; area je površina graničnog okvira poravnatog s osima (w * h); density je omjer tih dviju vrijednosti, koji se približava 1.0 za puni pravokutnik i pada prema 0.0 za tanak dijagonalni potez. roundness i compactness oboje ocjenjuju koliko je mrlja okrugla, iz različitih geometrijskih kutova (roundness iz momenata drugog reda, compactness iz omjera opsega i površine); elongation je 1.0 - roundness radi praktičnosti. rotation je orijentacija glavne osi u radijanima, koja je najtočnija na izduženim mrljama, a postaje šumna na gotovo okruglima (dvosmislena os nema dobro definiran smjer).
Metapodaci praga i spajanja – code, count – označavaju koji prag odgovara i koliko je izvornih mrlja spojeno u vraćenu. code je 32-bitna bitmapa s jednim postavljenim bitom po odgovarajućem pragu (jedan prag daje code == 1; spojena višebojna mrlja može imati postavljeno više bitova); count je 1 osim ako merge=True nije spojio nekoliko detekcija u jednu.
Skupina kutova – corners, min_corners – daje rotiranu geometriju mrlje. corners je 4-torka ekstrema (x, y) izvučenih iz konture mrlje, poredanih u smjeru kazaljke na satu od gornjeg lijevog kuta; min_corners je 4-torka kutova za rotirani pravokutnik najmanje površine koji obuhvaća mrlju. Pravokutnik najmanje površine je tijesno prianjanje; rect poravnat s osima je labavo prianjanje poravnato s pikselskom mrežom. Oba su korisna ovisno o tome treba li nizvodni stupanj orijentiran okvir ili običan.
Mrlja nosi granični okvir poravnat s osima (rect, x, y, w, h), centroid (cx, cy ili sub-pikselski cxf, cyf), rotirani pravokutnik najmanje površine (min_corners uz rotation) te opcionalne linije glavne / sporedne osi izračunate pomoćnim funkcijama na razini modula u nastavku.¶
5.25.3. Filtriranje pretrage¶
Snimljena sličica obično sadrži piksele koji odgovaraju pragu iz razloga drukčijih od objekta do kojeg je aplikaciji stalo: zrcalni odsjaji, udaljeni pozadinski objekti, šumni pikseli slike koji slučajno padaju u LAB raspon. Imenovani argumenti metode find_blobs() su prva linija obrane.
roi ograničava pretragu na područje sličice, baš kao i svaka druga metoda modula image. Aplikacija koja zna da se objekt može pojaviti samo u donjoj polovici vidnog polja prosljeđuje roi=(0, h//2, w, h//2) i zanemaruje sve iznad; ušteđeno vrijeme vraća se u brzinu sličica.
area_threshold i pixels_threshold oboje filtriraju mrlje koje su premale da bi bile bitne. area_threshold odbacuje mrlje čiji granični okvir ima manje od tog broja piksela površine (dobro za filtriranje raspršenog šuma); pixels_threshold odbacuje mrlje koje imaju manje od tog broja prolazećih piksela (dobro za filtriranje mrlja koje su velike ali rijetke, poput uzorka točkanja s pragom gdje se ovdje-ondje podudara jedan ili dva piksela). Obje zadane vrijednosti su 10; podizanjem na stotine za prednji cilj širok nekoliko centimetara odbacuje se svaka mrvica sitnog šuma.
x_stride i y_stride postavljaju pikselski korak koji skener čini dok traži mrlju za početak praćenja. Korak nije razlučivost praćenja – praćenje uvijek slijedi stvarnu granicu mrlje s detaljima na razini jednog piksela – nego upravlja koliko brzo pretraga pronalazi početni piksel. Kada se zna da su mrlje velike (obojeni cilj veličine šake na pola metra od kamere, lako stotinjak piksela širok), x_stride=4, y_stride=4 skraćuje vrijeme pretrage šesnaest puta bez praktičnog gubitka u detekciji. Kada su mrlje male (udaljeni LED svjetionik, širok nekoliko piksela), koraci moraju ostati na 1 kako ih se ne bi posve preskočilo. invert obrće test praga: podudaranje postaje nepodudaranje i rutina vraća mrlje neprolazećih piksela umjesto toga.
threshold_cb je Python povratni poziv pozvan na svakoj mrlji nakon određivanja praga, ali prije nego što je izgrađen konačni popis rezultata. Povratni poziv prima mrlju i vraća True da je zadrži ili False da je odbaci. Ovdje je mjesto za primjenu proizvoljnih filtara na razini Pythona na svojstva koja imenovani argumenti ne izlažu izravno – minimalna gustoća, određeni raspon rotacije, prilagođena kombinacija bitova koda nakon spajanja. Imenovani argumenti su filtri u izvornom kodu i izvode se brzo; povratni poziv izvodi se u Pythonu i sporiji je, ali neograničen u onome što može izraziti.
5.25.4. Spajanje preklapajućih mrlja¶
merge=True naknadno obrađuje popis rezultata kako bi spojio mrlje čiji se granični pravokutnici preklapaju. Prirodna upotreba je detekcija cilja čiju boju kamera vidi kao više područja s pragom zbog zrcalnih odsjaja, linija sjene ili neujednačenog osvjetljenja preko objekta: jedna crvena loptica može se vratiti kao tri ili četiri male crvene mrlje koje, uzete zajedno, tvore loptu. S merge=True tri mrlje postaju jedna velika mrlja, rect pokriva uniju, code je bitovni OR kodova spojenih mrlja (pa višebojno spajanje označava koje su boje pridonijele), a count izvještava koliko je izvornih mrlja spojeno.
margin povećava ili smanjuje granične pravokutnike prije testa preklapanja. S margin=2 mrlje čiji granični pravokutnici dođu unutar 2 piksela jedan od drugoga ipak se spajaju; s margin=-2 spajaju se samo mrlje čiji se granični pravokutnici preklapaju za barem 2 piksela. Prirodno podešavanje: pozitivna margina za rukovanje mrljama koje je prag razbio na susjedne dijelove; negativna margina za držanje tijesno grupiranih različitih objekata odvojenima.
merge_cb izvodi se na svakom kandidatskom paru prije nego što se spajanje dogodi. Povratni poziv prima dvije mrlje i vraća True da dopusti spajanje ili False da ga spriječi. Ovo je pravi alat za unakrsnu provjeru spajanja koja geometrijsko pravilo promaši – na primjer, odbijanje spajanja dviju mrlja čiji se kutovi rotation razlikuju više od praga ili odbijanje spajanja male mrlje u mnogo veću ako je mala samo mrljica.
5.25.5. Projekcijski histogrami¶
x_hist_bins_max i y_hist_bins_max pridružuju opcionalne projekcijske histograme svakoj mrlji. Projekcijski histogram je broj prolazećih piksela uzduž jedne osi: histogram X-osi zbraja prolazeće piksele po stupcu unutar graničnog okvira mrlje, a histogram Y-osi zbraja po retku. Oba zadano iznose nulu – histogrami se ne računaju osim ako se ne navede max različit od nule, jer bi inače dodavali posao svakoj detekciji.
Kada se izračunaju, histogrami pružaju jeftin 1-D signal na kojem aplikacija može pokrenuti daljnju analizu: otkrivanje položaja okomite pruge unutar mrlje, pronalaženje točke prijeloma dvobojnog cilja, brojanje koliko se praznina pojavljuje uzduž duge osi. Popunjavaju se kao svojstva x_hist_bins i y_hist_bins na svakoj Blob.
5.25.6. Dodatni geometrijski pomoćnici¶
Pregršt daljnjih geometrijskih mjera postoji kao funkcije na razini modula koje primaju mrlju i vraćaju traženu mjeru:
image.get_solidity()vraća čvrstoću mrlje – piksele podijeljene s površinom konveksne ljuske. Puno ispunjeno područje blizu je1.0; mrlja s udubinama (potkova, ruka s raširenim prstima) pada znatno niže.image.get_convexity()vraća konveksnost – opseg konveksne ljuske podijeljen s opsegom mrlje. Savršeno konveksna mrlja iznosi1.0; nazubljene ili urezane mrlje su niže.image.get_major_axis_line()iimage.get_minor_axis_line()vraćaju objekteLineuzduž glavne i sporedne osi mrlje, izvedene iz rotiranog pravokutnika najmanje površine.image.get_enclosing_circle()vraćaCirclekoji obuhvaća mrlju – korisno kada nizvodni stupanj želi krug za crtanje ili testiranje.image.get_enclosed_ellipse()vraća 5-torku(cx, cy, rx, ry, rotation)za elipsu upisanu u pravokutnik najmanje površine mrlje. Vrijednosti se izravno uvode udraw_ellipse().
5.25.7. Automatsko učenje praga¶
Detektor mrlja dobar je samo onoliko koliko i pragovi s kojima se izvodi, a posao pronalaženja pravog praga za boju cilja sam je za sebe problem. Dva uobičajena obrasca smanjuju taj posao.
Prvi je interaktivni odabir u IDE-u: snimite sličicu, povucite pravokutnik oko primjera ciljne boje i pustite IDE-ov uređivač praga da izvijesti o LAB granicama koje vidi. Te granice spuste se u skriptu kao pragovi metode find_blobs() i detektor je spreman.
Drugi je programsko automatsko učenje: kalibracijska rutina koja se izvodi na kameri snima sličicu, uzima histogram poznate mrlje gdje je cilj (get_histogram() s roi=) i očitava raspon vrijednosti mrlje s histograma pomoću get_percentile(). 5. percentil postavlja donju granicu svakog kanala, a 95. njegovu gornju granicu, zanemarujući zalutale izdvojene piksele na oba kraja. Na RGB565 slici jedan poziv percentila izvještava sva tri LAB kanala odjednom, pa dva poziva proizvode šest brojeva koje find_blobs() očekuje:
h = img.get_histogram(roi=patch)
lo = h.get_percentile(0.05)
hi = h.get_percentile(0.95)
threshold = (lo.l_value, hi.l_value,
lo.a_value, hi.a_value,
lo.b_value, hi.b_value)