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ókpixels, 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 metaadatokcode, 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 foltdetektálás bemutatva egy bináris küszöbérték-maszk ellenében. A bal oldali panel az átmenő képpontok döntött ovális maszkját mutatja. A jobb oldali panel ugyanazt a maszkot mutatja, köré rajzolt tengelyhez igazított határoló dobozzal annotálva, középen kereszttel jelölt súlyponttal, az ovált a valódi szögében szorosan körülfogó szaggatott minimális területű elforgatott téglalappal, és a súlyponton átmenő, az ovál hosszanti irányában mutató főtengely-vonallal.

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.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 az 1.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 folt 1.0; a szaggatott vagy bevágott foltok alacsonyabbak.

  • Az image.get_major_axis_line() és az image.get_minor_axis_line() Line objektumokat 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() egy Circle objektumot 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 a draw_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)