Aujourd’hui, nous allons apprendre à détecter des lignes et des cercles dans une image, à l’aide d’une technique appelée transformée de Hough.
Qu’est-ce que l’espace de Hough ?
Avant de commencer à appliquer la transformation de Hough aux images, nous devons comprendre ce qu’est un espace de Hough, et nous allons l’apprendre à la manière d’un exemple.
Espace des paramètres
Lorsque nous travaillons avec des images, nous pouvons imaginer que l’image est une matrice 2d sur certaines coordonnées x et y, sous laquelle une ligne pourrait être décrite comme y = mx + b
Mais dans l’espace des paramètres, que nous appellerons espace de Hough, je peux représenter cette même ligne comme m
contre b
à la place, donc la caractérisation d’une ligne sur l’espace image, sera un point unique à la position m-b
dans l’espace de Hough.
Mais nous avons un problème cependant, avec y = mx + b
, nous ne pouvons pas représenter une ligne verticale, car la pente est infinie. Nous avons donc besoin d’une meilleure façon de paramétrer, les coordonnées polaires (rho et thêta).
Espace de Hough
- rho : décrit la distance de la ligne par rapport à l’origine
- theta : décrit l’angle s’éloignant de l’horizontale
Une observation très importante cependant, est ce qui se passe lorsque nous prenons plusieurs points autour d’une ligne, et que nous transformons dans notre espace de Hough.
Un point unique sur l’espace image se traduit par une courbe sur l’espace de Hough, avec la particularité que les points parmi une ligne sur l’espace image seront représentés par de multiples courbes avec un seul point de contact.
Et ce sera notre cible, trouver les points d’intersection d’un groupe de courbes.
Qu’est-ce que la transformée de Hough ?
La transformée de Hough est une méthode d’extraction de caractéristiques pour détecter des formes simples telles que des cercles, des lignes, etc dans une image.
La caractéristique « simple » est dérivée par la représentation de la forme en termes de paramètres. Une forme « simple » ne sera représentée que par quelques paramètres, par exemple une ligne peut être représentée par sa pente et son intercept, ou un cercle qui peut être représenté par x, y et le rayon.
Dans notre exemple de ligne, une transformée de Hough sera responsable du traitement des points sur l’image et du calcul des valeurs dans l’espace de Hough.
L’algorithme pour faire la transformation et ensuite trouver les courbes d’intersection est un peu compliqué, et donc hors de la portée de ce post. Cependant nous allons jeter un coup d’œil à une implémentation de cet algorithme, qui fait partie de la bibliothèque OpenCV.
Détection de lignes à l’aide d’OpenCV
Dans OpenCV, la détection de lignes à l’aide de la transformation de Hough est implémentée dans les fonctions HoughLines
et HoughLinesP
(Probabilistic Hough Transform). Nous nous concentrerons sur cette dernière.
La fonction attend les paramètres suivants :
-
image
: image source binaire 8 bits, à canal unique. L’image peut être modifiée par la fonction. -
lines
: Vecteur de sortie des lignes. Chaque ligne est représentée par un vecteur à 4 éléments (x_1, y_1, x_2, y_2) , où (x_1, y_1) et (x_2, y_2) sont les points d’arrivée de chaque segment de ligne détecté. -
rho
: Résolution de distance de l’accumulateur en pixels. -
theta
: Résolution d’angle de l’accumulateur en radians. -
threshold
: Paramètre de seuil de l’accumulateur. Seules sont renvoyées les lignes qui obtiennent suffisamment de votes -
minLineLength
: Longueur minimale des lignes. Les segments de ligne plus courts que cela sont rejetés. -
maxLineGap
: Écart maximal autorisé entre les points d’une même ligne pour les relier.
Trop compliqué ? c’est plus facile avec un exemple:
# 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)
Et voici le résultat:
Il est très important que nous utilisions réellement une image de bord seulement comme paramètre pour la transformation de Hough, sinon l’algorithme ne fonctionnera pas comme prévu.
Détection de cercles à l’aide d’OpenCV
Le processus se déroule à peu près de la même manière que pour les lignes, à l’exception que cette fois-ci nous utiliserons une fonction différente de la bibliothèque OpenCV. Nous utiliserons maintenant HoughCircles
, qui accepte les paramètres suivants :
-
image
: image d’entrée 8 bits, monocanal, en niveaux de gris. -
circles
: Vecteur de sortie des cercles trouvés. Chaque vecteur est codé comme un vecteur à virgule flottante à 3 éléments (x, y, rayon). -
circle_storage
: Dans la fonction C, il s’agit d’un stockage mémoire qui contiendra la séquence de sortie des cercles trouvés. -
method
: Méthode de détection à utiliser. Actuellement, la seule méthode implémentée est CV_HOUGH_GRADIENT , qui est fondamentalement 21HT -
dp
: Rapport inverse de la résolution de l’accumulateur à la résolution de l’image. Par exemple, si dp=1 , l’accumulateur a la même résolution que l’image d’entrée. Si dp=2 , l’accumulateur a une largeur et une hauteur deux fois moins grandes. -
minDist
: Distance minimale entre les centres des cercles détectés. Si le paramètre est trop petit, plusieurs cercles voisins peuvent être faussement détectés en plus d’un vrai. S’il est trop grand, certains cercles peuvent être manqués. -
param1
: Premier paramètre spécifique à la méthode. Dans le cas de CV_HOUGH_GRADIENT , il s’agit du seuil le plus élevé des deux passés au détecteur de bords Canny() (le plus bas est deux fois plus petit). -
param2
: Deuxième paramètre spécifique à la méthode. Dans le cas de CV_HOUGH_GRADIENT , il s’agit du seuil d’accumulation des centres de cercle à l’étape de détection. Plus il est petit, plus de faux cercles peuvent être détectés. Les cercles, correspondant aux plus grandes valeurs d’accumulateur, seront retournés en premier. -
minRadius
: Rayon minimal du cercle. -
maxRadius
: Rayon maximal du cercle.
N’oubliez pas que les paramètres doivent être différents, car nous ne pouvons pas décrire un cercle avec la même paramétrisation que nous avons utilisée pour les lignes, et à la place, nous devons utiliser une équation comme (x - x0)^^2 + (y - y0)^^2 = r^^2
.
Et au code:
# 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)
Notez que par rapport à l’exemple précédent, nous n’appliquons ici aucune fonction de détection des bords. C’est parce que la fonction HoughCircles
a une détection de canny intégrée.
Et le résultat:
Conclusion
La transformée de Hough est une excellente technique pour détecter des formes simples dans les images et a plusieurs applications, allant des applications médicales telles que l’analyse des rayons X, CT et IRM, aux voitures à conduite autonome. Si vous souhaitez en savoir plus sur l’espace de Hough, je vous recommande d’exécuter réellement le code, d’essayer différentes configurations par vous-même et de consulter la documentation OpenCV pour obtenir des informations supplémentaires.
Merci de lire !
.