Nous avons vu dans un précédent article comment utiliser l’algorithme MobileNetSSD pour la reconnaissance d’objet dans une image. Dans cet article, nous allons mettre en place ce détecteur pour la reconnaissance d’objet en temps réel.

Pour rappel, MobileNet est un réseau de neurones convolutifs, développé par Google, permettant de classifier 21 types d’objets et présentant des avantages tels que légèreté, rapidité et précision.

Ce réseau de neurones est associé au réseau de neurones Single Shot Multibox Detector (SSD) permettant d’identifier toutes les zones dans l’image présentant un élément à classifier.

La combinaison de MobileNet et de SSD permet d’obtenir une méthode rapide et efficace de détection d’objets basée sur l’apprentissage profond.

Le modèle que nous utilisons est une implémentation sous Caffe entrainée par Chuangi305.

En bas de cet article, vous trouverez un bouton pour télécharger le code source, ainsi que modèles entraînés, utilisés dans cet article.

Reconnaissance d’objet en temps réel avec MobileNet et OpenCV

Nous commençons par importer les bibliothèques nécessaires pour le fonctionnement de notre programme.

import numpy as np
import argparse
import cv2

Puis nous analysons aux lignes 5 à 9 les arguments donnés par l’utilisateur lors de l’appel du programme

ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", required=True,help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--modele", required=True,help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confiance", type=float, default=0.2,help="probabilité minimale pour filtrer les détections faibles")
args = vars(ap.parse_args())

Nous initialisons ensuite les labels des différentes classes, ainsi que les couleurs pour les représenter.

CLASSES = ["arriere-plan", "avion", "velo", "oiseau", "bateau", "bouteille", "autobus", "voiture", "chat", "chaise", "vache", "table","chien", "cheval", "moto", "personne", "plante en pot", "mouton", "sofa", "train", "moniteur"]
couleurs = np.random.uniform(0, 255, size=(len(CLASSES), 3))

Comme vous pouvez le constater, le modèle entrainer permet de détecter 21 types d’objets différents, ce qui change du classificateur que nous avions entrainer pour détecter uniquement les bouteilles de bière.

Maintenant que les représentations des classes sont initialisés, nous pouvons charger le modèle (l.17) et démarrer de la caméra (l.18)

net = cv2.dnn.readNet(args["prototxt"], args["modele"])
cap = cv2.VideoCapture(0)

La fonction cv2.dnn.readNet() d’OpenCV permet de charger un réseau d’apprentissage profond. Elle prend en entrée le fichier de configuration du réseau, ainsi que le modèle pré-entrainé. Elle permet de détecter automatiquement le framework utilisé et il est alors possible de donner en argument des fichiers Caffe, TensorFlow, Torch, DarkNet, …

Enfin nous récupérons une première image (l. 20) afin d’obtenir la taille des images fournies par la caméra (l. 21). Nous utilisons cette information afin de calculer la nouvelle taille que dois avoir l’image à traiter, tout en conservant les proportions (l. 22-23)

ret,image=cap.read()
(h, w) = image.shape[:2]
new_h=300
new_w=int(w*( new_h / float(h)))

Nous pouvons maintenant passer à la mise en place de la reconnaissance d’objet à chaque nouvelle image capturée.

while True:
	ret,image=cap.read()
	image=cv2.resize(image,(new_w,new_h))
	blob = cv2.dnn.blobFromImage(image,0.007843, (300, 300),127.5)

Nous récupérons donc une nouvelle image (l. 26), puis nous la rétrécissons (l. 27) avant d’appliquer le modèle (l. 28). Pour en savoir plus sur les valeurs passées en arguments, je vous invite à aller voir les explications sur la fonction blobFromImage().

net.setInput(blob)
detections = net.forward()

Nous donnons ensuite l’image pré-traitée comme entrée du réseau de neurones (l. 30), puis nous réalisons les calculs des différentes couches du réseau de neurones (l. 31). Nous obtenons un tableau comprenant les résultats de la dernière couche du réseau.

Affichage des résultats

Un des arguments que nous avons défini lors de l’appel du programme est la confiance, permettant de conserver les résultats les plus sûrs.

Pour chaque objet détecté (l. 33), nous récupérons sa valeur de confiance (l. 34), afin de ne garder que les détections suffisamment sûres (l. 35).

Par la suite, nous récupérons l’index de la classe correspondant à l’objet détecté (l. 36) ainsi que ses coordonnées (l. 37) que nous convertissons en entier (l. 38).

for i in np.arange(0, detections.shape[2]):
	confiance = detections[0, 0, i, 2]
	if confiance > args["confiance"]:
		index = int(detections[0, 0, i, 1])
		box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
		(startX, startY, endX, endY) = box.astype("int")

Il ne nous reste plus qu’à afficher les détections :

On commence par créer les labels que l’on affichera à coté des détections (l. 40). Ces labels sont composés du nom de l’objet, ainsi que le score de confiance que nous arrondissons à 2 décimales après la virgule.

Puis, nous en profitons pour préparer la position de ce label (l. 41). Nous souhaitons qu’il apparaisse en haut à gauche du rectangle encadrant, sauf dans le cas où l’objet détecté correspond à l’image en elle-même. Dans ce cas, le label sera positionné 20 pixels sous le coin en haut à gauche.

Enfin, nous traçons le rectangle encadrant (l. 42), le label (l. 43) et nous affichons l’image traitée (l. 45-46). Nous en profitons pour mettre une condition d’arrêt, à savoir, quand la touche « q » est pressée.

			label = str(CLASSES[index]) +" : " + str(round((confiance * 100),2))
			y = startY - 20 if startY - 20 > 20 else startY + 20
			cv2.rectangle(image, (startX, startY), (endX, endY),COLORS[index], 2)
			cv2.putText(image, label, (startX, y),cv2.FONT_HERSHEY_SIMPLEX, 1.5, COLORS[index], 3)
	
	cv2.imshow("Frame", image)
	if cv2.waitKey(1) & 0xFF == ord('q'):
		cap.release()
		break

Résultats

Il ne nous reste plus qu’à lancer notre programme !

python3 reconnaissance_objet_camera.py -p MobileNetSSD_deploy.prototxt.txt  -m MobileNetSSD_deploy.caffemodel
Application de MobileNet-SSD pour la reconnaissance d'objet en temps réel

Le programme fonctionne à environ 7 images par seconde et à part quelques erreurs sur le type d’animal présent, les résultats sont plutôt satisfaisants 🙂


0 commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.