5.27. Körök és téglalapok keresése

A vonalak és szakaszok a rögzített képkocka egyenes éleit fedik le, de a kamera által keresett valós jellemzők jó része nem egyenes. Egy asztalon fekvő érme egy kör. Egy nyomtatott címke, egy öntapadós cetli vagy egy ferdén nézett doboz teteje egy négyszög. Az image modul mindegyikhez külön detektort kínál: egy Hough-stílusú keresést a körökhöz és egy AprilTag alapú keresést a négyoldalú alakzatokhoz.

Mindkét módszer ugyanazt a sablont követi, mint a vonaldetektorok – a threshold szabályozza, hogy egy észleléshez hány szavazat szükséges, a roi szűkíti a keresést, a visszaadott objektumok pedig egyaránt hordoznak pozíciót és megbízhatósági nagyságot –, de a paramétertér és a megfelelő alapértékek eléggé eltérnek ahhoz, hogy külön tárgyalást érdemeljenek.

5.27.1. Hough-körök

A find_circles() a Hough-transzformáció körkörös változatát futtatja. A Sobel-előfeldolgozásból származó minden élképpont szavaz minden olyan körre, amely áthaladhat rajta; az elegendő szavazatot összegyűjtő körök kerülnek visszaadásra.

circles = img.find_circles(threshold=3500,
                            x_margin=10, y_margin=10, r_margin=10,
                            r_min=10, r_max=80, r_step=2)

for c in circles:
    img.draw_circle((c.x, c.y, c.r), color=(255, 0, 0))

A threshold a Sobel-élnagyságok minimális összege a jelölt kör mentén. A nagyobb körök több képpontot rajzolnak ki, így nagyobb küszöbértékre van szükségük az átjutáshoz; egy olyan érték, amely megtalál egy 20 képpont sugarú érmét, egy 100 képpontos él körüli zajra is rárepül, míg egy a nagy érméhez hangolt érték elszalasztja a kicsit. Ha a célsugár tartománya ismert, a megfelelő küszöbérték a kerülettel skálázódik – nagyjából a threshold = 50 * 2 * pi * r ad ésszerű kiindulópontot, a megfelelő érték pedig egy rövid hangolási menetből adódik.

Az r_min, r_max és r_step állítja be a sugárkeresést. Korlátok nélkül a detektor néhány képponttól a kép félszélességéig minden sugarat végigkeresne, ami egyszerre lassú és melegágya a téves találatoknak. Ha az r_min és r_max értékét a várt célméret köré bőséges ráhagyással állítjuk be (pl. r_min=15, r_max=25 egy körülbelül 20 képpontos ismert érméhez), az jelentősen csökkenti a munkát és javítja a szavazatok jel-zaj viszonyát. Az r_step szabályozza a keresés finomságát; a nagyobb lépések gyorsabban futnak, és elszalaszthatnak egy olyan kört, amelynek valódi sugara két mintavételezett érték közé esik. Az alapértelmezett r_step=2 ésszerű kompromisszum.

Az x_margin, y_margin és r_margin a közeli észlelések összevonását szabályozza, ugyanúgy, ahogy a theta_margin és rho_margin teszi a vonaldetektálásnál. A képen egyetlen fizikai kör jelölt körök egész fürtjére szavaz, amelyek középpontja és sugara néhány képponton belül megegyezik; a margók a fürtöket a csúcsukra zsugorítják, mielőtt felépül az eredménylista. A nagyobb margók kevesebb, de magabiztosabb észlelést adnak vissza; a kisebb margók több észlelést adnak vissza, esetleg közeli duplikátumokkal.

Az x_stride és y_stride lépteti a szavazó pásztázást, ugyanúgy, mint a többi detektorban. Az alapértelmezett 2 és 1 a legtöbb képhez megfelelő; mindkettő 4-re emelése a szokásos sebesség-kompromisszum nagy köröket tartalmazó kép esetén.

Minden visszaadott Circle hordozza az x, y, r értékeket (a középpontot és a sugarat) és a magnitude értéket (a szavazatok összegét, amely rendezésnél vagy szűrésnél megbízhatósági pontszámként hasznos). Az észlelés visszarajzolása a képkockába egyetlen hívás – a draw_circle() az (x, y, r) 3-as elemet várja, amely közvetlenül elérhető az eredményről (c.x, c.y, c.r) formában.

5.27.2. Téglalapok

A find_rects() az AprilTag-folyamatból kölcsönzi a négyszögdetektort – ugyanaz a rutin, amely a tag körüli fekete négyzetet megtalálja, önállóan, általános célú téglalapkeresőként is elérhető.

rects = img.find_rects(threshold=12000)

for r in rects:
    img.draw_rectangle(r.rect, color=(0, 255, 0))
    for corner in r.corners:
        img.draw_circle((corner[0], corner[1], 4),
                        color=(0, 255, 0))

A threshold az élnagyságok minimális összege a téglalap kerülete mentén. Egy jól megvilágított képkockán egy nyomtatott fekete-fehér téglalap könnyedén túllépi a 10000 értéket; egy mintázott háttéren lévő halvány téglalapnál előfordulhat, hogy 2000-re kell csökkenteni – a téves találatokat az érzékenységre cserélve. A kördetektorhoz hasonlóan a megfelelő érték egy gyors hangolási menetből adódik, a célzott célpontokkal a látómezőben.

A detektor projektív – olyan négyszögeket talál, amelyek oldalai egyenesek, de nem feltétlenül párhuzamosak vagy tengelyhez igazítottak. Egy ferdén nézett címke a képen trapéznak látszik, és a téglalapdetektor helyesen megtalálja; egy tengelyhez igazított téglalap csak az a degenerált eset, amikor a négy sarok véletlenül derékszögű dobozt alkot. A roi korlátozza a keresést; a többi kulcsszavas argumentum az AprilTag-folyamat alapértékeit veszi át, és ritkán igényel hangolást.

Minden visszaadott Rect hordozza a tengelyhez igazított határoló dobozt – x, y, w, h, valamint a rect 4-es elemet, amelyet a draw_rectangle() vár –, és a négy észlelt sarkot corners formában. A határoló dobozt az alkalmazás a durva pozícióhoz és mérethez használja; a sarkok magát a projektív négyszöget írják le. Amikor a kamera ferdén néz egy lapos célpontot, és az alkalmazásnak vissza kell vonnia a trapéztorzítást – címkén lévő szöveg olvasása, szín mintavételezése egy lapos foltról –, a sarkok közvetlenül a rotation_corr() metódusba táplálhatók a corners= kulcsszóval (lásd lencse- és perspektívakorrekció), és a kimenet a rektifikált téglalap, készen az ezt követő bármilyen elemzésre.

Figyelem

Mivel a detektor arra van hangolva, amire az AprilTag-folyamatnak szüksége van – erős, nagy kontrasztú szegélyű négyszögekre, mint egy fehér papíron lévő fekete tag körvonala –, ez nem minden-téglalapot-megtaláló menet. A lágy kontrasztú, mintázott élű vagy zsúfolt környezetű téglalapok teljesen észrevétlenek maradhatnak. Hogy mennyire jól működik, az helyzetfüggő: tesztelje a valós célpontokon korán, mielőtt köré épít egy folyamatot.

5.27.3. Amikor a detektor mellélő

Különösen a körök profitálnak a bemenet előszűréséből. Egy zajos képkocka rengeteg szórt élképpontot eredményez, amelyek mind szavaznak, az így kapott Hough-tér pedig széles, elmosódott csúcsokkal rendelkezik, amelyeket az összevonó nehezen tud szétválasztani. Egy gaussian() vagy mean() menet a find_circles() előtt elsimítja a zajt, és érintetlenül hagyja a valódi éleket; a detektor tisztább csúcsokat ad vissza, rövidebb idő alatt.

Téglalapoknál a gyakori hibamód az ellenkezője: a téglalap és háttere közötti alacsony kontraszt azt jelenti, hogy az élnagyságok összege soha nem lépi túl a threshold értéket. Egy histeq() menet, amely a fényerőtartományt a teljes 0-tól 255-ig terjedő sávra osztja újra, helyreállítja a detektor által igényelt kontrasztot. (A kontrasztnak léteznie kell valahol a képen; a hisztogramkiegyenlítés csak azt tudja felerősíteni, ami már ott van.)