Dans l’article d’aujourd’hui, nous allons nous attaquer à notre premier problème qui est de retrouver un dé dans une image et d’en déduire le chiffre représenté.
Pour ce faire nous nous attaquerons à la question de la reconnaissance de formes pour extraire le carré représentant un dé dans l’image ainsi que les points représentant le chiffre de la face.
Nous étudierons également les différentes fonctions permettant de rajouter des formes et du texte sur une image.
Cet article étant une initiation à la reconnaissance des dés, nous nous baserons sur des images simples ne contenant qu’un seul dé et où la luminosité est constante. Si vous débutez dans OpenCV, je vous invite à consulter cet article.
Nous allons effectuer 3 étapes principales:
C’est parti !
import cv2
import numpy as np
img=cv2.imread('Dice_2.jpg')
HSV=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
V=HSV[:,:,2]
V=cv2.GaussianBlur(V, (5, 5), 0)
_,thresh=cv2.threshold(V,200,255,cv2.THRESH_BINARY) Les lignes 1 à 4 permettent le chargement de la bibliothèque OpenCV , de NumPy, ainsi que le chargement de l’image.
Nous changeons de repère colorimétrique à la ligne 5 où nous transformons notre image RGB en image HSV.
Le modèle HSV est une représentation des images en 3 composantes: la teinte de la couleur(Hue), la Saturation (l’intensité de la couleur) et la Valeur (la « brillance » de la couleur).
Il est ainsi aisé repérer les objets brillant de la scène en étudiant uniquement la composante V de l’image (ligne 6).
Nous effectuons un lissage de l’image à la ligne 7 afin d’enlever les éventuels bruits de l’image.
Enfin nous effectuons, ligne 8, un seuillage de l’image afin de n’étudier que les parties brillantes de l’image.
Nous obtenons ainsi une image binaire, où le dé est parfaitement identifiable.
Nous allons maintenant nous occuper de l’obtention des coordonnées du dé dans l’image:
_,cnts,_ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
if len(approx) >= 4 and area > 100:
(x, y, w, h) = cv2.boundingRect(approx)
cv2.rectangle(img, (x, y), (x + w, y + h), (200, 0, 0), 2) La fonction findContours() (ligne 10) permet d’obtenir, comme son nom l’indique, tous les contours présents dans une image binaire.
Pour chaque contour obtenu, nous calculons l’aire et la périphérie de la forme (lignes 12-13).
Nous allons ensuite faire une approximation de notre forme (ligne 14).
L’approximation de contour est un algorithme permettant de réduire le nombre de points permettant de définir une courbe. L’idée de cette méthode est d’approcher une courbe (un contour) par une série de courtes droites.
Le contour de notre dé devrait pouvoir être approché par une série de 4 droites correspondant à ces 4 côtés. Cependant à cause de la luminosité et de la forme du dé, un nombre supérieur de droites et nécessaire.
Nous définissons donc (ligne 15) comme condition que le nombre de droites doit être supérieur ou égal à 4. De plus nous mettons comme condition que l’aire de la forme soit supérieure à 100 afin d’éliminer les éventuels bruits.
Afin d’obtenir le rectangle encadrant de notre forme (ligne 16), nous utilisons la fonction boundingRect() qui renvoie les coordonnées du rectangle dans lequel se situe la forme. Nous pouvons ainsi tracer le rectangle obtenu sur notre image initiale (ligne 17).
Maintenant que nous connaissons la position du dé, nous pouvons étudier son nombre de points.
crop=V[y:y+h,x:x+w]
_, thresh2 = cv2.threshold(crop, 100, 255, cv2.THRESH_BINARY_INV)
dilated = cv2.dilate(thresh2, kernel=np.ones((5,5 ),'int'))
_,cnts2,_ = cv2.findContours(dilated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
nombre=0
for c in cnts2:
area = cv2.contourArea(c)
if area > 100:
nombre+=1
cv2.putText(img,str(nombre),((int(x+w)),int((y+h/2))),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
print("Valeur du dé : "+ str(nombre)) Nous commençons par extraire de la composante de la luminance (Value) la zone correspondant au dé (ligne 19) et nous effectuons un seuil permettant de mettre en avant les zones sombres de l’image (ligne 20).
Nous effectuons ensuite une opération morphologique ligne 21: une dilatation permettant de corriger les déformations provenant de l’éclairage:
Nous effectuons de nouveau une recherche de contours ligne 22. Et nous comptabilisons les formes ayant une aire supérieure à 100 (lignes 24-28).
Enfin nous fonction putText() (ligne 29) permet de rajouter sur l’image d’origine, la valeur du dé:
Nous avons dans cet article mis en place un moyen simple pour reconnaitre la valeur d’un dé à partir d’une image. Pour ce faire, nous avons eu besoin d’utiliser des seuils afin de faciliter la détection de contour.
Ce procédé est cependant extrêmement sensible aux changements d’illumination de la scène, ainsi qu’à l’orientation des dés.
Nous verrons dans un prochain article comment il est possible d’améliorer notre système de reconnaissance.
Détecter les voies de circulation est une étape incontournable pour la réalisation d’un système de…
Dans cet article, nous allons voir comment capturer simplement une image grâce au module raspicam…
Aujourd’hui nous allons utiliser Dlib et OpenCV pour détecter les repères faciaux (facial landmarks) dans…
Nous avons vu dans un précédent article comment utiliser l’algorithme MobileNetSSD pour la reconnaissance d’objet…
Dans cet article, nous nous intéressons à l’utilisation des réseaux de neurones convolutifs dans le…
Derrière ce titre un peu trompeur, nous n’allons pas trouver Charlie dans une image, mais…
View Comments