5.27. Ympyröiden ja suorakulmioiden etsiminen

Viivat ja segmentit kattavat kaapatun kehyksen suorat reunat, mutta monet todellisen maailman piirteet, joita kamera etsii, eivät ole suoria. Pöydällä makaava kolikko on ympyrä. Painettu luokkanimi, muistilappu tai vinosti katsotun laatikon yläosa on nelikulmio. image-moduuli tarjoaa kummallekin oman tunnistimensa: Hough-tyyppisen haun ympyröille ja AprilTagista johdetun haun nelisivuisille muodoille.

Molemmat metodit noudattavat samaa kaavaa kuin viivatunnistimet – threshold säätää, kuinka monta ääntä tunnistus tarvitsee, roi rajaa hakua, ja palautetut oliot kantavat sekä sijainnin että luotettavuussuureen – mutta parametriavaruudet ja oikeat oletusarvot eroavat tarpeeksi ansaitakseen oman käsittelynsä.

5.27.1. Hough-ympyrät

find_circles() suorittaa Hough-muunnoksen ympyräversion. Jokainen Sobel-esikäsittelyn reunapikseli äänestää jokaista ympyrää, joka voisi kulkea sen kautta; tarpeeksi ääniä keränneet ympyrät palautetaan.

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))

threshold on ehdokasympyrän varrella olevien Sobel-reunasuuruuksien pienin summa. Suuremmat ympyrät piirtyvät useampien pikselien kautta ja tarvitsevat siksi korkeammat kynnysarvot läpäistäkseen; arvo, joka löytää 20 pikselin säteisen kolikon, laukeaa myös 100 pikselin reunan ympärillä olevasta kohinasta, kun taas suurelle kolikolle viritetty arvo jättää pienen huomaamatta. Kun tavoiteltu säteen alue tunnetaan, oikea kynnysarvo skaalautuu kehän mukaan – karkeasti threshold = 50 * 2 * pi * r antaa kohtuullisen lähtökohdan, ja oikea arvo löytyy lyhyellä virityskierroksella.

r_min, r_max ja r_step asettavat säteen haun. Ilman rajoja tunnistin etsisi kaikki säteet muutamasta pikselistä kuvan puolileveyteen asti, mikä on sekä hidasta että omiaan tuottamaan vääriä osumia. Asettamalla r_min ja r_max rajaamaan odotettua kohteen kokoa reilulla marginaalilla (esim. r_min=15, r_max=25 kolikolle, jonka tiedetään olevan noin 20 pikseliä) vähentää työtä huomattavasti ja parantaa äänten signaali-kohinasuhdetta. r_step säätää haun tarkkuutta; suuremmat askeleet ajavat nopeammin ja voivat jättää huomaamatta ympyrän, jonka todellinen säde osuu kahden näytteistetyn arvon väliin. Oletus r_step=2 on kohtuullinen kompromissi.

x_margin, y_margin ja r_margin säätävät lähekkäisten tunnistusten yhdistämistä, samaan tapaan kuin theta_margin ja rho_margin tekevät viivatunnistuksessa. Yksittäinen fyysinen ympyrä kuvassa äänestää ehdokasympyröiden ryppäästä, joiden keskipisteet ja säteet täsmäävät muutaman pikselin tarkkuudella; marginaalit tiivistävät kunkin ryppään huippuunsa ennen tuloslistan rakentamista. Suuremmat marginaalit palauttavat vähemmän, varmempia tunnistuksia; pienemmät marginaalit palauttavat enemmän tunnistuksia, mahdollisesti lähes kaksoiskappaleita.

x_stride ja y_stride askeltavat äänestysskannauksen, samaan tapaan kuin muissakin tunnistimissa. Oletus 2 ja 1 sopii useimmille kuville; molempien nostaminen arvoon 4 on tavanomainen nopeuskompromissi kuvalle, jonka tiedetään sisältävän suuria ympyröitä.

Jokainen palautettu Circle kantaa arvot x, y, r (keskipiste ja säde) sekä magnitude (äänten kokonaismäärä, hyödyllinen luotettavuuspisteenä lajittelussa tai suodatuksessa). Tunnistuksen piirtäminen takaisin kehykseen on yksi kutsu – draw_circle() ottaa (x, y, r) 3-monikon, joka on saatavilla suoraan tuloksesta muodossa (c.x, c.y, c.r).

5.27.2. Suorakulmiot

find_rects() lainaa nelikulmiotunnistimen AprilTag-putkesta – sama rutiini, joka paikantaa tagin ympärillä olevan mustan neliön, on tarjolla itsenäisenä yleiskäyttöisenä suorakulmioiden etsijänä.

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))

threshold on reunasuuruuksien pienin summa suorakulmion kehää pitkin. Painettu musta-valkoinen suorakulmio hyvin valaistussa kehyksessä ylittää helposti arvon 10000; heikko suorakulmio kuvioidulla taustalla voi tarvita laskua arvoon 2000 – jolloin vaihdetaan vääriä osumia herkkyyteen. Kuten ympyrätunnistimessa, oikea arvo löytyy nopealla virityskierroksella kohteiden ollessa näkyvissä.

Tunnistin on projektiivinen – se löytää nelikulmiot, joiden sivut ovat suoria mutta eivät välttämättä yhdensuuntaisia tai akselien suuntaisia. Vinosti katsottu luokkanimi näyttää kuvassa puolisuunnikkaalta, ja suorakulmiotunnistin löytää sen oikein; akselien suuntainen suorakulmio on vain rappeutunut erikoistapaus, jossa neljä kulmaa sattuvat muodostamaan suorakulmaisen laatikon. roi rajaa hakua; loput avainsana-argumentit ottavat oletuksensa AprilTag-putkesta eivätkä juuri tarvitse viritystä.

Jokainen palautettu Rect kantaa akselien suuntaisen rajauslaatikon – x, y, w, h sekä rect 4-monikon, jota draw_rectangle() odottaa – ja neljä tunnistettua kulmaa muodossa corners. Rajauslaatikko on se, mitä sovellus käyttää karkeaan sijaintiin ja kokoon; kulmat kuvaavat projektiivisen nelikulmion itsensä. Kun kamera katsoo tasaista kohdetta kulmasta ja sovelluksen täytyy kumota perspektiivivääristymä – lukea tekstiä luokkanimestä, näytteistää väriä tasaiselta alueelta – kulmat syötetään suoraan metodille rotation_corr() avainsanalla corners= (ks. linssi- ja perspektiivikorjaus), ja tuloksena on oikaistu suorakulmio valmiina mihin tahansa seuraavaan analyysiin.

Varoitus

Koska tunnistin on viritetty AprilTag-putken tarpeisiin – nelikulmiot, joilla on vahvat, korkeakontrastiset reunat, kuten musta tagin ääriviiva valkoisella paperilla – se ei ole löydä-jokainen-suorakulmio-kierros. Suorakulmiot, joilla on pehmeä kontrasti, kuvioidut reunat tai vilkas ympäristö, voivat jäädä kokonaan tunnistamatta. Kuinka hyvin se toimii, riippuu tilanteesta: testaa sitä todellisia kohteita vasten varhain, ennen kuin rakennat putken sen ympärille.

5.27.3. Kun tunnistin epäonnistuu

Erityisesti ympyrät hyötyvät syötteen esisuodatuksesta. Kohiseva kehys tuottaa runsaasti hajanaisia reunapikseleitä, jotka kaikki äänestävät, ja seurauksena syntyvässä Hough-avaruudessa on leveitä utuisia huippuja, joita yhdistäjän on vaikea erottaa. gaussian()- tai mean()-kierros ennen metodia find_circles() tasoittaa kohinan pois ja jättää todelliset reunat ehjiksi; tunnistin palauttaa puhtaammat huiput lyhyemmässä ajassa.

Suorakulmioilla yleinen vikatila on päinvastainen: pieni kontrasti suorakulmion ja sen taustan välillä tarkoittaa, ettei reunasuuruuksien summa koskaan ylitä arvoa threshold. histeq()-kierros, joka jakaa kirkkausalueen uudelleen koko 0–255-välille, palauttaa kontrastin, jota tunnistin tarvitsee. (Kontrastin on oltava olemassa jossakin kuvassa; histogrammin tasoitus voi vain vahvistaa sitä, mikä on jo olemassa.)