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.
Reconnaissance d’objets en temps réel avec MobileNet
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="Chemin vers le fichier prototxt de Caffe")
ap.add_argument("-m", "--modele", required=True,help="Chemin vers le modèle pré-entrainé de Caffe")
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.
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.
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.
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").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)
Il ne nous reste plus qu’à afficher les détections :
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()
breakOn 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.
Il ne nous reste plus qu’à lancer notre programme !
python3 reconnaissance_objet_camera.py -p MobileNetSSD_deploy.prototxt.txt -m MobileNetSSD_deploy.caffemodel

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