Étiquettes : ,

La libraire OpenCV est utilisée pour faire du traitement d’image notamment de la reconnaissance de forme et de couleur. La librairie possèdent des fonction d’acquisition et des algorithmes de traitement d’image qui permettent notamment de faire de la reconnaissance d’image assez simplement sans avoir à passer par de l’intelligence artificielle. C’est ce que nous allons voir dans ce tutoriel.

Ce tutoriel peut être appliqué à n’importe quel ordinateur possédant une installation de Python avec OpenCV et une Caméra. Notamment le Raspberry Pi.

Matériel

  • Ordinateur avec une installation de python3

Préparation de l’environnement de travail

Pour réaliser le script de reconnaissance de forme, nous installons les modules OpenCV, numpy et imutils pour manipuler et traiter les images.

pip3 install opencv-python numpy imutils

La détection des couleurs se fait à l’aide des modules webcolors et scipy (KDTree)

pip3 install webcolors scipy

Afin de tester et valider l’algorithme, nous créons une image contenant des objets de formes et de couleurs différentes. Vous pouvez créer votre propre image avec Paint ou utiliser celle-ci:

python_shapes_detection_base Reconnaissance de forme et de couleur avec Python

Principe de fonctionnement

Dans le code suivant, nous allons créer un classe détection de forme qui va nous permettre de sélectionner une forme en fonction du nombre de contours trouvé. Puis nous allons définir une fonction permettant de retrouver le nom de la couleur en fonction de son code RGB. Enfin nous allons utiliser OpenCV pour charger, filtrer et masquer l’image afin de détecter les formes et les couleurs contenues dans l’image.

Code complet de reconnaissance de forme simple et de couleur

Vous devez créer le fichier python ObjectDetection.py dans le même dossier que l’image que vous souhaitez analyser.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# import the necessary packages
import cv2
import numpy as np
import imutils

#colors
from webcolors import rgb_to_name,CSS3_HEX_TO_NAMES,hex_to_rgb #python3 -m pip install webcolors
from scipy.spatial import KDTree

def convert_rgb_to_names(rgb_tuple):
    # a dictionary of all the hex and their respective names in css3
    css3_db = CSS3_HEX_TO_NAMES#css3_hex_to_names
    names = []
    rgb_values = []    
    for color_hex, color_name in css3_db.items():
        names.append(color_name)
        rgb_values.append(hex_to_rgb(color_hex))
    
    kdt_db = KDTree(rgb_values)    
    distance, index = kdt_db.query(rgb_tuple)
    return names[index]
    
class ShapeDetector:
	def __init__(self):
		pass
	def detect(self, c):
		# initialize the shape name and approximate the contour
		shape = "unidentified"
		peri = cv2.arcLength(c, True)
		approx = cv2.approxPolyDP(c, 0.04 * peri, True)

		# if the shape is a triangle, it will have 3 vertices
		if len(approx) == 3:
			shape = "triangle"
		# if the shape has 4 vertices, it is either a square or
		# a rectangle
		elif len(approx) == 4:
			# compute the bounding box of the contour and use the
			# bounding box to compute the aspect ratio
			(x, y, w, h) = cv2.boundingRect(approx)
			ar = w / float(h)
			# a square will have an aspect ratio that is approximately
			# equal to one, otherwise, the shape is a rectangle
			shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
		# if the shape is a pentagon, it will have 5 vertices
		elif len(approx) == 5:
			shape = "pentagon"
		elif len(approx) == 6:
			shape = "hexagon"
		elif len(approx) == 10 or len(approx) == 12:
			shape = "star"
		# otherwise, we assume the shape is a circle
		else:
			shape = "circle"
		# return the name of the shape
		return shape	

if __name__ == '__main__':
	# load the image and resize it to a smaller factor so that
	# the shapes can be approximated better
	image = cv2.imread('python_shapes_detection_base.PNG')
	resized = imutils.resize(image, width=300)
	ratio = image.shape[0] / float(resized.shape[0])
	
	# convert the resized image to grayscale, blur it slightly,
	# and threshold it
	gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
	blurred = cv2.GaussianBlur(gray, (5, 5), 0)
	thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
	
	# find contours in the thresholded image and initialize the
	# shape detector
	cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
		cv2.CHAIN_APPROX_SIMPLE)
	cnts = imutils.grab_contours(cnts)
	sd = ShapeDetector()

	# loop over the contours
	for c in cnts:
		# compute the center of the contour
		M = cv2.moments(c)
		cX = int((M["m10"] / M["m00"]) * ratio)
		cY = int((M["m01"] / M["m00"]) * ratio)  
		
		#detect shape from contour
		shape = sd.detect(c)
		
		# resize the contour
		c = c.astype("float")
		c *= ratio
		c = c.astype("int")
		cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
		
		#draw contour with mask
		mask = np.zeros(image.shape[:2], np.uint8)
		cv2.drawContours(mask, [c], -1, 255, -1)
		img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
		
		#Convert to RGB and get color name
		imgRGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
		mean=cv2.mean(imgRGB, mask=mask)[:3]
		named_color = convert_rgb_to_names(mean)
		
		#get complementary color for text
		mean2 = (255-mean[0],255-mean[1],255-mean[2])
		
		#display shape name and color
		objLbl=shape+" {}".format(named_color)
		textSize = cv2.getTextSize(objLbl,cv2.FONT_HERSHEY_SIMPLEX,0.5,2)[0]
		cv2.putText(image, objLbl, (int(cX-textSize[0]/2),int(cY+textSize[1]/2)), cv2.FONT_HERSHEY_SIMPLEX,0.5,mean2, 2)
		
		#show image
		cv2.imshow("Image", image)
		#cv2.waitKey(0)
	cv2.waitKey(0)		

Résultat

Pour lancer le script, vous pouvez soit l’exécuter à partir de votre éditeur de code (comme Geany) ou bien lancer la commande suivante dans un terminal de commande ouvert dans votre dossier de travail.

$ python3 ObjectDetection.py

Une fois le code exécuté, l’image va s’afficher avec chacune des formes entourées de vert et un texte au centre de la forme contenant le nom et la couleur de la forme.

python_shapes_detection_result Reconnaissance de forme et de couleur avec Python

N.B.: Cet algorithme ne fonctionnera pas pour toute les formes. Pour détecter d’autres formes vous devez soit adapter la fonction detect de la classe ShapeDetector pour identifier tous les cas possibles soit passer par de l’intelligence artificielle.

Applications

Sources