Tänään opettelemme havaitsemaan viivoja ja ympyröitä kuvassa Hough-muunnoksen avulla.
Mikä on Hough-avaruus?
Ennen kuin alamme soveltaa Hough-muunnosta kuviin, meidän on ymmärrettävä, mikä Hough-avaruus on, ja opimme sen esimerkin avulla.
Parametriavaruus
Kun työskentelemme kuvien kanssa, voimme kuvitella kuvan olevan 2d-matriisi joidenkin x- ja y-koordinaattien yli, jonka alla viivaa voitaisiin kuvata y = mx + b
Mutta parametriavaruudessa, jota kutsumme Hough-avaruudeksi, voin esittää saman viivan sen sijaan m
vs. b
, joten viivan luonnehdinta kuva-avaruudessa on yksi piste asennossa m-b
Hough-avaruudessa.
Mutta meillä on kuitenkin ongelma, y = mx + b
:n kanssa emme voi esittää pystysuoraa viivaa, koska kaltevuus on ääretön. Tarvitsemme siis paremman parametrisoinnin, polaarikoordinaatit (rho ja theta).
Hough-avaruus
- rho: kuvaa viivan etäisyyttä origosta
- theta: kuvaa kulmaa poispäin vaakatasosta
Ensimmäinen tärkeä havainto on kuitenkin se, mitä tapahtuu, kun otamme useamman pisteen ympärillemme viivan ympärillemme ja muunnamme sen Hough-avaruuteen.
Yksittäinen piste kuva-avaruudessa muunnetaan käyräksi Hough-avaruudessa, sillä erityispiirteellä, että pisteitä viivan joukossa kuva-avaruudessa edustaa useampi käyrä yhdellä kosketuspisteellä.
Ja tämä on kohteemme, eli niiden pisteiden löytäminen, joissa joukko käyriä leikkaa toisiaan.
Mikä on Hough-muunnos?
Hough-muunnos on ominaisuuksien louhintamenetelmä, jolla voidaan havaita yksinkertaisia muotoja, kuten ympyröitä, viivoja jne. kuvassa.
”Yksinkertainen” ominaisuus johdetaan muodon esitystavasta parametrien avulla. ”Yksinkertainen” muoto esitetään vain muutamalla parametrilla, esimerkiksi viiva voidaan esittää sen kaltevuudella ja leikkauspisteellä tai ympyrä, joka voidaan esittää x:llä, y:llä ja säteellä.
Viivaesimerkissämme Hough-muunnos vastaa kuvan pisteiden käsittelystä ja arvojen laskemisesta Hough-avaruuteen.
Algoritmi, jolla muunnos saadaan tapahtumaan ja jonka avulla sen jälkeen etsitään risteävät käyrästöt, on hiukan monimutkainen ja siten tämän postauksen ulkopuolelle jäävä asia. Tutustumme kuitenkin tämän algoritmin toteutukseen, joka on osa OpenCV-kirjastoa.
Viivojen havaitseminen OpenCV:n avulla
OpenCV:ssä viivojen havaitseminen Hough-muunnoksen avulla on toteutettu funktioissa HoughLines
ja HoughLinesP
(Probabilistic Hough Transform). Keskitymme jälkimmäiseen.
Funktio odottaa seuraavia parametreja:
-
image
: 8-bittinen, yksikanavainen binäärinen lähdekuva. Funktio voi muokata kuvaa. -
lines
: Rivien lähtövektori. Jokainen viiva esitetään 4-alkioisella vektorilla (x_1, y_1, x_2, y_2) , jossa (x_1,y_1) ja (x_2, y_2) ovat kunkin havaitun viivasegmentin loppupisteet. -
rho
: Akun etäisyysresoluutio pikseleinä. -
theta
: Akkumulaattorin kulmaresoluutio radiaaneina. -
threshold
: Akkumulaattorin kynnysarvoparametri. Vain ne rivit palautetaan, jotka saavat tarpeeksi ääniä -
minLineLength
: Rivin vähimmäispituus. Tätä lyhyemmät viivasegmentit hylätään. -
maxLineGap
: Suurin sallittu väli samalla viivalla olevien pisteiden välillä niiden yhdistämiseksi.
Yli liian monimutkaista? helpompaa esimerkin avulla:
# Read image img = cv2.imread('lanes.jpg', cv2.IMREAD_COLOR)# Convert the image to gray-scalegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Find the edges in the image using canny detectoredges = cv2.Canny(gray, 50, 200)# Detect points that form a linelines = cv2.HoughLinesP(edges, 1, np.pi/180, max_slider, minLineLength=10, maxLineGap=250)# Draw lines on the imagefor line in lines: x1, y1, x2, y2 = line cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)# Show resultcv2.imshow("Result Image", img)
Ja tässä on tulos:
On erittäin tärkeää, että käytämme Hough-muunnoksen parametrina oikeasti pelkkää reunaa sisältävää kuvaa, muutoin algoritmi ei toimi tarkoitetulla tavalla.
Ympyröiden havaitseminen OpenCV:n avulla
Prosessi menee suunnilleen samalla tavalla kuin viivojen kohdalla, sillä erotuksella, että tällä kertaa käytämme eri funktiota OpenCV-kirjastosta. Käytämme nyt HoughCircles
, joka hyväksyy seuraavat parametrit:
-
image
: 8-bittinen, yksikanavainen, harmaasävyinen syöttökuva. -
circles
: Löydettyjen ympyröiden lähtövektori. Jokainen vektori on koodattu 3-alkioisena liukulukuvektorina (x, y, säde). -
circle_storage
: C-funktiossa tämä on muistivarasto, joka sisältää löydettyjen ympyröiden tulostussarjan. -
method
: Käytettävä havaintomenetelmä. Tällä hetkellä ainoa toteutettu menetelmä on CV_HOUGH_GRADIENT , joka on periaatteessa 21HT -
dp
: Akkumulaattorin resoluution käänteinen suhde kuvan resoluutioon. Esimerkiksi jos dp=1 , akulla on sama resoluutio kuin tulokuvalla. Jos dp=2 , akun leveys ja korkeus ovat puolet pienemmät. -
minDist
: Havaittujen ympyröiden keskipisteiden välinen vähimmäisetäisyys. Jos parametri on liian pieni, oikean ympyrän lisäksi saatetaan virheellisesti havaita useita naapuriympyröitä. Jos se on liian suuri, osa ympyröistä voi jäädä huomaamatta. -
param1
: Ensimmäinen menetelmäkohtainen parametri. Jos kyseessä on CV_HOUGH_GRADIENT , se on Canny()-reunanilmaisimelle annetuista kahdesta kynnysarvosta korkeampi (alempi on kaksi kertaa pienempi). -
param2
: Toinen menetelmäkohtainen parametri. Jos kyseessä on CV_HOUGH_GRADIENT , se on ympyrän keskipisteiden akkumulaattorikynnys tunnistusvaiheessa. Mitä pienempi se on, sitä enemmän vääriä ympyröitä voidaan havaita. Suurempia akkumulaattoriarvoja vastaavat ympyrät palautetaan ensin. -
minRadius
: Pienin ympyrän säde. -
maxRadius
: Suurin ympyrän säde.
Muista, että parametrien on oltava erilaiset, sillä emme voi kuvata ympyrää samalla parametrisoinnilla, jota käytimme viivojen kohdalla, vaan sen sijaan meidän on käytettävä yhtälöä kuten (x - x0)^^2 + (y - y0)^^2 = r^^2
.
Ja koodiin:
# Read image as gray-scaleimg = cv2.imread('circles.png', cv2.IMREAD_COLOR)# Convert to gray-scalegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Blur the image to reduce noiseimg_blur = cv2.medianBlur(gray, 5)# Apply hough transform on the imagecircles = cv2.HoughCircles(img_blur, cv2.HOUGH_GRADIENT, 1, img.shape/64, param1=200, param2=10, minRadius=5, maxRadius=30)# Draw detected circlesif circles is not None: circles = np.uint16(np.around(circles)) for i in circles: # Draw outer circle cv2.circle(img, (i, i), i, (0, 255, 0), 2) # Draw inner circle cv2.circle(img, (i, i), 2, (0, 0, 255), 3)
Huomaa, että edelliseen esimerkkiin verrattuna emme sovella tässä kohtaa reunantunnistusfunktiota. Tämä johtuu siitä, että funktiossa HoughCircles
on sisäänrakennettu canny-tunnistus.
Ja lopputulos:
Johtopäätös
Hough-muunnos on erinomainen tekniikka yksinkertaisten kuvien havaitsemiseen kuvissa, ja sillä on useita sovelluksia lääketieteellisistä sovellutuksista, kuten esimerkiksi röntgenkuvauksen, tietokonetomografian (CT:n), tietokonekerroskuvauksen (TT:n) ja magneettikuvauksen (MRI:n) analyysista, aina itsestäänajaviin autoihin. Jos olet kiinnostunut tietämään lisää Hough-avaruudesta, suosittelen, että suoritat itse koodin, kokeilet itse erilaisia konfiguraatioita ja tutustut OpenCV:n dokumentaatioon lisätietojen saamiseksi.
Kiitos lukemisesta!