5.25. Foltok keresése¶
A küszöbölés a rögzített képkockát bináris maszkká alakította: minden képpont vagy átmegy a küszöbérték-teszten, vagy nem. Ez megválaszolja, hogy mely színek jelennek meg a jelenetben, amelyek érdeklik az alkalmazást, de azt nem, hogy hol – a maszk csupán 1-esek és 0-k tengere. A következő lépés a foltdetektálás: a maszk bejárása, az átmenő képpontok összefüggő régióinak megkeresése, és mindegyik visszaadása objektumként, amely rendelkezik pozícióval, mérettel, tájolással, valamint a többi tulajdonsággal, amelyre egy alkalmazás reagálhat.
A find_blobs() ennek a lépésnek az igáslova, és a leggyakoribb belépési pont az image modul eredményobjektum-világába. Egy színes labda követése, egy padlóra festett vonal nyomon követése, annak megszámolása, hány fényes pontot lát egy hőérzékelő, annak eldöntése, hogy egy kék LED be van-e kapcsolva vagy sem – ugyanaz a hívás mindezt lefedi. A bemenetek változnak (a küszöbértékek, a vizsgált terület, az eredményre alkalmazott szűrők), de a hívási minta ugyanaz.
5.25.1. Az alapvető hívás¶
A find_blobs egy küszöbérték-listát vesz át, és foltot leíró eredményobjektumok listáját adja vissza:
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))
Minden küszöbérték-tuple ugyanolyan formájú, mint a binary() metódusnak átadott küszöbértékek – hat bejegyzés (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi) egy RGB565 kép esetén (a határok LAB-ban értendők), két bejegyzés (lo, hi) egy szürkeárnyalatos kép esetén. Egyetlen hívásban legfeljebb 32 küszöbérték adható meg, ami a find_blobs() rugalmasságát adja: piros, zöld és kék jeladók egyszerre követhetők, mindegyik a saját foltjaival járul hozzá a visszaadott listához, és minden folt code tulajdonsága azonosítja, melyik küszöbértékhez illeszkedett.
A fenti draw_rectangle() és draw_cross() hívások a rögzített képkockát annotálják az IDE előnézete számára. A folt eredménye már tartalmazza a b.rect értéket (a határoló dobozt 4-tuple-ként) és a b.cx / b.cy értékeket (az egész számú súlypontot), így az észlelés visszarajzolása a képkockára két metódushívás.
5.25.2. Mit tartalmaz az eredmény¶
Minden Blob egy attribútum-tuple, amely összefogja mindazt, amit a detektor a régióról megmért. A tulajdonságok négy csoportra oszlanak.
A határoló doboz és súlypont csoport – x, y, w, h, rect, cx, cy, cxf, cyf – a folt pozícióját írja le. A rect az (x, y, w, h) 4-tuple, amelyet a rajzoló metódusok várnak; a cx és cy a súlypont egész számú képpont-koordinátákban; a cxf és cyf a súlypont szubpixeles lebegőpontos koordinátákban, ami akkor hasznos, amikor egy korábbi kalibráció törtértékű pozíciókat igényel.
A alakleírók – pixels, area, density, perimeter, roundness, elongation, compactness, rotation – leírják, hogyan néz ki a folt. A pixels az átmenő képpontok száma; az area a tengelyhez igazított határoló doboz területe (w * h); a density a kettő aránya, amely egy tömör téglalapnál 1.0 felé, egy vékony átlós vonásnál pedig 0.0 felé közelít. A roundness és a compactness egyaránt azt méri, mennyire kerek a folt, eltérő geometriai nézőpontból (a roundness a másodrendű momentumokból, a compactness a kerület-terület arányból); az elongation a kényelem kedvéért 1.0 - roundness. A rotation a fő tengely tájolása radiánban, amely megnyúlt foltoknál a legpontosabb, és közel kerek foltoknál zajossá válik (egy bizonytalan tengelynek nincs jól meghatározott iránya).
A küszöbérték- és összevonási metaadatok – code, count – azt azonosítják, melyik küszöbérték illeszkedett, és hány forrásfoltot vontak össze a visszaadottba. A code egy 32 bites bittérkép, amelyben minden illeszkedő küszöbértékhez egy bit van beállítva (egyetlen küszöbérték code == 1 értéket ad; egy összevont, többszínű folt esetén több bit is beállítható); a count értéke 1, hacsak a merge=True nem vont össze több észlelést egybe.
A sarkok csoport – corners, min_corners – a folt elforgatott geometriáját adja meg. A corners az (x, y) szélsőértékek 4-tuple-je, amelyeket a folt kontúrjából húznak ki, a bal felső saroktól az óramutató járásával megegyezően rendezve; a min_corners a foltot körülfogó, minimális területű elforgatott téglalap sarkainak 4-tuple-je. A minimális területű téglalap a szoros illeszkedés; a tengelyhez igazított rect a laza, képpontrácshoz igazított illeszkedés. Mindkettő hasznos lehet attól függően, hogy egy következő szakasznak tájolt vagy egyszerű dobozra van-e szüksége.
Egy folt hordozza a tengelyhez igazított határoló dobozt (rect, x, y, w, h), a súlypontot (cx, cy vagy a szubpixeles cxf, cyf), a minimális területű elforgatott téglalapot (min_corners plusz rotation), valamint az alábbi modul szintű segédfüggvények által kiszámított opcionális fő-/melléktengely-vonalakat.¶
5.25.3. A keresés szűrése¶
Egy rögzített képkocka jellemzően tartalmaz olyan képpontokat, amelyek nem az alkalmazás által keresett objektum miatt illeszkednek a küszöbértékhez: tükröződő csúcsfények, távoli háttérobjektumok, képzajt jelentő képpontok, amelyek véletlenül a LAB-tartományba esnek. A find_blobs() kulcsszavas argumentumai jelentik az első védvonalat.
A roi a keresést a képkocka egy régiójára korlátozza, ugyanúgy, ahogy minden más image modul metódus. Egy alkalmazás, amely tudja, hogy az objektum csak a látómező alsó felében jelenhet meg, átadja a roi=(0, h//2, w, h//2) értéket, és figyelmen kívül hagy mindent felette; a megspórolt idő a képkockasebességbe forgatható vissza.
Az area_threshold és a pixels_threshold egyaránt kiszűrik azokat a foltokat, amelyek túl kicsik ahhoz, hogy számítsanak. Az area_threshold eldobja azokat a foltokat, amelyek határoló dobozának területe kevesebb képpontnyi (jó a szórt zaj kiszűréséhez); a pixels_threshold eldobja azokat a foltokat, amelyeknek kevesebb átmenő képpontjuk van (jó az olyan foltok kiszűréséhez, amelyek nagyok, de ritkák, mint egy küszöbölt pontozott minta, amelynél itt-ott egy-két képpont illeszkedik). Mindkettő alapértéke 10; ezek százasokra emelése egy néhány centiméter széles előtér-célpontnál minden kis zajszemcsét eldob.
Az x_stride és az y_stride állítja be a képpontlépést, amelyet a szkennelő tesz, miközben egy nyomon követendő folt kezdetét keresi. A lépésköz nem a nyomon követés felbontása – a nyomon követés mindig a folt tényleges határát követi egyetlen képpont részletességgel –, hanem azt szabályozza, milyen gyorsan találja meg a szkennelés a kezdő képpontot. Amikor a foltokról ismert, hogy nagyok (egy ököl méretű színes célpont egy lábnyira a kamerától, könnyen száz képpont széles), az x_stride=4, y_stride=4 tizenhatszorosára csökkenti a szkennelési időt a detektálás gyakorlati vesztesége nélkül. Amikor a foltok kicsik (egy távoli LED-jeladó, néhány képpont széles), a lépésközöknek 1 értéken kell maradniuk, hogy ne lépjenek át rajtuk teljesen. Az invert megfordítja a küszöbérték-tesztet: az illeszkedésből nem-illeszkedés lesz, és a rutin az átmenni nem képes képpontok foltjait adja vissza helyette.
A threshold_cb egy Python visszahívás, amelyet minden folton meghív a küszöbölés után, de a végső eredménylista felépítése előtt. A visszahívás megkapja a foltot, és True értéket ad vissza a megtartásához, vagy False értéket az eldobásához. Ez a hely tetszőleges Python szintű szűrők alkalmazására olyan tulajdonságokra, amelyeket a kulcsszavas argumentumok nem tesznek közvetlenül elérhetővé – egy minimális sűrűség, egy konkrét forgatási tartomány, egy egyedi kódbit-kombináció az összevonás után. A kulcsszavas argumentumok natív kódban szűrnek, és gyorsan futnak; a visszahívás Pythonban fut, lassabb, de korlátlan abban, amit ki tud fejezni.
5.25.4. Átfedő foltok összevonása¶
A merge=True utófeldolgozza az eredménylistát, hogy összevonja azokat a foltokat, amelyek határoló téglalapjai átfedik egymást. A természetes felhasználás egy olyan célpont detektálása, amelynek színét a kamera több küszöbölt régióként látja tükröződő csúcsfények, árnyékvonalak vagy az objektumon eltérő megvilágítás miatt: egyetlen piros labda három-négy kis piros foltként térhet vissza, amelyek együttesen kirajzolják a labdát. A merge=True mellett a három folt egy nagy folttá válik, a rect lefedi az uniót, a code az összevont foltok kódjainak bitenkénti VAGY-a (így egy többszínű összevonás azonosítja, mely színek járultak hozzá), és a count jelenti, hány forrásfoltot vontak össze.
A margin növeli vagy zsugorítja a határoló téglalapokat az átfedési teszt előtt. A margin=2 esetén azok a foltok is összevonódnak, amelyek határoló téglalapjai 2 képponton belülre kerülnek egymáshoz; a margin=-2 esetén csak azok a foltok vonódnak össze, amelyek határoló téglalapjai legalább 2 képponttal átfedik egymást. A természetes hangolás: pozitív margó azokhoz a foltokhoz, amelyeket a küszöbölés szomszédos darabokra tört; negatív margó a szorosan csoportosuló, különálló objektumok elkülönítésének megtartásához.
A merge_cb minden jelölt páron lefut, mielőtt az összevonás megtörténik. A visszahívás megkapja a két foltot, és True értéket ad vissza az összevonás engedélyezéséhez, vagy False értéket annak megakadályozásához. Ez a megfelelő eszköz olyan összevonások keresztellenőrzésére, amelyeket a geometriai szabály elmulaszt – például két olyan folt összevonásának megtagadására, amelyek rotation szögei egy küszöbértéknél nagyobb mértékben térnek el egymástól, vagy egy kis folt összevonásának megtagadására egy sokkal nagyobbal, ha a kicsi csupán zajszemcse.
5.25.5. Projekciós hisztogramok¶
Az x_hist_bins_max és az y_hist_bins_max opcionális projekciós hisztogramokat csatol minden folthoz. A projekciós hisztogram az átmenő képpontok száma egy tengely mentén: az X tengelyű hisztogram a folt határoló dobozán belül oszloponként összegzi az átmenő képpontokat, az Y tengelyű hisztogram pedig soronként. Mindkettő alapértéke nulla – a hisztogramok nem kerülnek kiszámításra, hacsak nem adnak meg nullától eltérő max értéket, mivel egyébként minden detektáláshoz munkát adnának.
Amikor kiszámításra kerülnek, a hisztogramok olcsó 1D-s jelet biztosítanak, amelyen egy alkalmazás további elemzést futtathat: egy függőleges csík pozíciójának detektálását a folton belül, egy kétszínű célpont töréspontjának megkeresését, annak megszámolását, hány rés jelenik meg a hosszanti tengely mentén. Ezeket az x_hist_bins és y_hist_bins tulajdonságokba töltik fel minden Blob objektumon.
5.25.6. További geometriai segédfüggvények¶
Néhány további geometriai mérőszám modul szintű függvényként él, amelyek egy foltot vesznek át, és a kért mérőszámot adják vissza:
Az
image.get_solidity()a folt tömörségét adja vissza – a képpontok elosztva a konvex burok területével. Egy tömör, kitöltött régió közel van az1.0értékhez; egy beöblösödésekkel rendelkező folt (egy patkó, egy szétterpesztett ujjú kéz) jócskán alá esik.Az
image.get_convexity()a konvexitást adja vissza – a konvex burok kerülete elosztva a folt kerületével. Egy tökéletesen konvex folt1.0; a szaggatott vagy bevágott foltok alacsonyabbak.Az
image.get_major_axis_line()és azimage.get_minor_axis_line()Lineobjektumokat ad vissza a folt fő- és melléktengelye mentén, az elforgatott minimális területű téglalapból származtatva.Az
image.get_enclosing_circle()egyCircleobjektumot ad vissza, amely körülfogja a foltot – akkor hasznos, amikor egy következő szakasz egy kört szeretne rajzolni vagy ahhoz tesztelni.Az
image.get_enclosed_ellipse()az(cx, cy, rx, ry, rotation)5-tuple-t adja vissza egy olyan ellipszishez, amely a folt minimális területű téglalapjába van beírva. Az értékek közvetlenül adraw_ellipse()metódusba táplálhatók.
5.25.7. Küszöbérték automatikus megtanulása¶
Egy foltdetektor csak annyira jó, amilyen küszöbértékekkel futtatják, és egy célszínhez tartozó megfelelő küszöbérték megtalálásának munkája önmagában is feladat. Két gyakori minta csökkenti ezt a munkát.
Az első az interaktív kiválasztás az IDE-ben: rögzítsen egy képkockát, húzzon egy téglalapot a célszín egy példánya köré, és hagyja, hogy az IDE küszöbérték-szerkesztője jelentse az általa látott LAB-határokat. Ezek a határok bekerülnek a szkriptbe a find_blobs() küszöbértékeiként, és a detektor készen áll.
A második a programozott automatikus tanulás: egy a kamerán futó kalibrációs rutin rögzít egy képkockát, vesz egy hisztogramot egy ismert foltról, ahol a célpont van (get_histogram() a roi= argumentummal), és leolvassa a folt értéktartományát a hisztogramról a get_percentile() segítségével. Az 5. percentilis adja meg minden csatorna alsó határát, a 95. pedig a felsőt, figyelmen kívül hagyva a mindkét végén lévő elszórt kiugró képpontokat. Egy RGB565 képen egyetlen percentilis-hívás egyszerre jelenti mindhárom LAB-csatornát, így a két hívás előállítja azt a hat számot, amelyet a find_blobs() vár:
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)