Înțelegerea și implementarea detecției formei folosind transformată Hough cu OpenCV și Python

Imagine caracteristică

Astăzi vom învăța cum să detectăm linii și cercuri într-o imagine, cu ajutorul unei tehnici numite transformată Hough.

Ce este spațiul Hough?

Înainte de a începe să aplicăm transformarea Hough la imagini, trebuie să înțelegem ce este un spațiu Hough, iar acest lucru îl vom învăța prin intermediul unui exemplu.

Spațiu parametric

Când lucrăm cu imagini, ne putem imagina imaginea ca fiind o matrice 2d pe niște coordonate x și y, sub care o linie ar putea fi descrisă ca y = mx + b

Spațiu parametric

Spațiu parametric

Dar în spațiul parametric, pe care îl vom numi spațiul Hough, pot să reprezint aceeași linie ca m vs b în schimb, astfel încât caracterizarea unei linii în spațiul imaginii, va fi un singur punct la poziția m-b în spațiul Hough.

Spațiul Hough

Spațiul Hough

Dar avem totuși o problemă, cu y = mx + b, nu putem reprezenta o dreaptă verticală, deoarece panta este infinită. Așa că avem nevoie de o modalitate mai bună de parametrizare, coordonate polare (rho și theta).

Spațiu Hough

  • rho: descrie distanța dreptei față de origine
  • theta: descrie unghiul de îndepărtare față de orizontală
Coordonate polare de linie

Coordonate polare de linie

O observație foarte importantă totuși, este ce se întâmplă când luăm mai multe puncte în jurul unei drepte, și transformăm în spațiul nostru Hough.

Relația dintre puncte și linii în spațiul Hough

Relația dintre puncte și linii în spațiul Hough

Un singur punct în spațiul imaginii se traduce printr-o curbă în spațiul Hough, cu particularitatea că punctele dintre o linie în spațiul imaginii vor fi reprezentate prin mai multe curbe cu un singur punct de atingere.

Și aceasta va fi ținta noastră, găsirea punctelor în care un grup de curbe se intersectează.

Ce este transformarea Hough?

Transformarea Hough este o metodă de extragere a caracteristicilor pentru detectarea formelor simple, cum ar fi cercuri, linii, etc. într-o imagine.

Caracteristica „simplă” este derivată prin reprezentarea formei în termeni de parametri. O formă „simplă” va fi reprezentată doar de câțiva parametri, de exemplu, o linie poate fi reprezentată prin panta și interceptarea ei, sau un cerc care poate fi reprezentat prin x, y și raza.

În exemplul nostru de linie, o transformare Hough va fi responsabilă de procesarea punctelor de pe imagine și de calcularea valorilor în spațiul Hough.

Algoritmul pentru realizarea transformării și, ulterior, găsirea curbelor care se intersectează este puțin complicat și, prin urmare, iese din sfera de aplicare a acestei postări. Cu toate acestea, vom arunca o privire asupra unei implementări a acestui algoritm, care face parte din biblioteca OpenCV.

Detectarea liniilor folosind OpenCV

În OpenCV, detectarea liniilor cu ajutorul transformării Hough este implementată în funcțiile HoughLines și HoughLinesP (Probabilistic Hough Transform). Ne vom concentra asupra celei din urmă.

Funcția așteaptă următorii parametri:

  • image: Imagine sursă binară pe 8 biți, cu un singur canal. Imaginea poate fi modificată de către funcție.
  • lines: Vector de ieșire de linii. Fiecare linie este reprezentată de un vector cu 4 elemente (x_1, y_1, x_2, y_2) , unde (x_1,y_1) și (x_2, y_2) sunt punctele finale ale fiecărui segment de linie detectat.
  • rho: Rezoluția de distanță a acumulatorului în pixeli.
  • theta: Rezoluția unghiulară a acumulatorului în radiani.
  • threshold: Parametru de prag al acumulatorului. Sunt returnate numai liniile care primesc suficiente voturi
  • minLineLength: Lungimea minimă a liniei. Segmentele de linie mai scurte decât aceasta sunt respinse.
  • maxLineGap: Distanța maximă permisă între punctele de pe aceeași linie pentru a le lega.

Tot prea complicat? este mai ușor cu un exemplu:

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

Și iată rezultatul:

Exemplu de detectare a liniilor

Exemplu de detectare a liniilor

Este foarte important să folosim efectiv ca parametru pentru Transformarea Hough doar o imagine cu margini, altfel algoritmul nu va funcționa așa cum trebuie.

Detectarea cercurilor folosind OpenCV

Procesul se desfășoară aproximativ la fel ca în cazul liniilor, cu excepția faptului că de data aceasta vom folosi o funcție diferită din biblioteca OpenCV. Vom folosi acum HoughCircles, care acceptă următorii parametri:

  • image: Imagine de intrare pe 8 biți, cu un singur canal, în tonuri de gri.
  • circles: Vectorul de ieșire al cercurilor găsite. Fiecare vector este codificat ca un vector în virgulă mobilă cu 3 elemente (x, y, rază).
  • circle_storage: În funcția C, aceasta este o memorie de stocare care va conține secvența de ieșire a cercurilor găsite.
  • method: Metoda de detecție care trebuie utilizată. În prezent, singura metodă implementată este CV_HOUGH_GRADIENT , care este practic 21HT
  • dp: Raportul invers dintre rezoluția acumulatorului și rezoluția imaginii. De exemplu, dacă dp=1 , acumulatorul are aceeași rezoluție ca și imaginea de intrare. Dacă dp=2 , acumulatorul are lățimea și înălțimea la jumătate.
  • minDist: Distanța minimă între centrele cercurilor detectate. Dacă parametrul este prea mic, pot fi detectate în mod eronat mai multe cercuri vecine pe lângă unul adevărat. Dacă este prea mare, este posibil ca unele cercuri să nu fie detectate.
  • param1: Primul parametru specific metodei. În cazul CV_HOUGH_GRADIENT , este pragul cel mai mare dintre cele două transmise detectorului de margini Canny() (cel mai mic este de două ori mai mic).
  • param2: Al doilea parametru specific metodei. În cazul CV_HOUGH_GRADIENT , este pragul acumulatorului pentru centrele cercurilor în etapa de detecție. Cu cât este mai mic, cu atât mai multe cercuri false pot fi detectate. Cercurile, care corespund valorilor mai mari ale acumulatorului, vor fi returnate primele.
  • minRadius: Raza minimă a cercului.
  • maxRadius: Raza maximă a cercului.

Amintiți-vă că parametrii trebuie să fie diferiți, deoarece nu putem descrie un cerc cu aceeași parametrizare pe care am folosit-o pentru linii și, în schimb, trebuie să folosim o ecuație de tipul (x - x0)^^2 + (y - y0)^^2 = r^^2.

Și să trecem la cod:

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

Rețineți că, în comparație cu exemplul anterior, nu aplicăm aici nicio funcție de detectare a marginilor. Acest lucru se datorează faptului că funcția HoughCircles are încorporată detecția canny.

Și rezultatul:

Exemplu de detecție a cercului

Exemplu de detecție a cercului

Concluzie

Transformarea Hough este o tehnică excelentă pentru detectarea formelor simple în imagini și are mai multe aplicații, de la aplicații medicale, cum ar fi analizele cu raze X, CT și RMN, până la mașinile care se conduc singure. Dacă sunteți interesați să aflați mai multe despre spațiul Hough, vă recomand să rulați efectiv codul, să încercați singuri diferite configurații și să consultați documentația OpenCV pentru informații suplimentare.

Mulțumesc pentru lectură!

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.