"Désolé, j'ai reconnu ..." ou reconnaissez les framboises et les contrôleurs à l'aide de l'API de détection d'objets Tensorflow

À la fin de l'année dernière, j'ai écrit un article sur la façon dont j'ai été intrigué par la capacité de reconnaître des objets dans des images à l'aide de réseaux de neurones. Dans cet article, en utilisant PyTorch, nous avons classé les framboises ou un contrôleur de type arduino en vidéo. Et malgré le fait que j'aimais PyTorch, je me suis tourné vers lui parce que je ne pouvais pas traiter TensorFlow tout de suite. Mais j'ai promis de revenir sur la question de la reconnaissance des objets dans la vidéo. Il semble que le moment soit venu de tenir la promesse.

Dans cet article, nous allons essayer sur notre machine locale de recycler le modèle fini dans Tensorflow 1.13 et l'API de détection d'objets sur notre propre ensemble d'images, puis de l'utiliser pour reconnaître les baies et les contrôleurs dans le flux vidéo d'une caméra Web à l'aide d'OpenCV.

Vous voulez améliorer vos compétences de reconnaissance des baies d'ici l'été? Alors vous êtes les bienvenus sous chat.



Contenu:

Partie I: introduction
Partie II: former le modèle dans TenosrFlow
Partie III: appliquer le modèle dans OpenCV
Partie IV: conclusion

Partie I: Introduction


Ceux qui ont lu l'article précédent sur PyTorch savent déjà que je suis un amateur de questions de réseaux de neurones. Par conséquent, ne percevez pas cet article comme la vérité ultime. Mais quoi qu'il en soit, j'espère pouvoir aider quelqu'un à gérer les bases de la reconnaissance vidéo en utilisant l'API de détection d'objets Tensorflow.

Cette fois, je n'ai pas essayé de faire un tutoriel, donc l'article sera plus court que d'habitude.
Pour commencer, le didacticiel officiel sur l'utilisation de l'API de détection d'objets sur une machine locale, pour le moins, n'est pas exhaustif. En tant que novice, j'étais complètement insuffisant et j'ai dû me concentrer sur les articles de blog.

Pour être honnête, je voudrais essayer TensorFlow 2.0, mais dans la plupart des publications, au moment d'écrire ces lignes, les problèmes de migration n'étaient pas complètement résolus. J'ai donc finalement opté pour TF 1.13.2.

Partie II: enseigner un modèle à TensorFlow


J'ai tiré des instructions pour enseigner le modèle à partir de cet article , ou plutôt de sa première moitié, jusqu'à ce que JavaScript soit appliqué (si vous ne parlez pas anglais, vous pouvez voir un article sur le même sujet dans Habré ) .

Certes, dans mon cas, il existe plusieurs différences:

  1. J'ai utilisé Linux car Anaconda pour Linux a déjà construit protobuf et pycocoapi, donc je n'ai pas eu à les construire moi-même.
  2. TensorFlow 1.13.2, Object Detection API 1.13 , TensorFlow 1.13.2. master TF 1.15, 1.13.
  3. numpy — 1.17.5, 1.18 .
  4. faster_rcnn_inception_v2_coco ssd_mobilenet_v2_coco, , .

Au cas où, je dirais que je n'ai pas utilisé d'accélérateur graphique. La formation a été effectuée uniquement sur les capacités du processeur.

Un ensemble d'images, un fichier de configuration, un graphique enregistré, ainsi qu'un script pour reconnaître les images à l'aide d'OpenCV, comme toujours, peuvent être téléchargés depuis GitHub .

Une longue formation de modèle de 23 heures s'est écoulée, tout le thé de la maison a déjà été bu, «Quoi? Où? Quand?" inspecté et maintenant ma patience a finalement pris fin.

Nous arrêtons la formation et enregistrons le modèle.

Installez OpenCV dans le même environnement que "Anaconda" avec la commande suivante:

conda install -c conda-forge opencv

J'ai finalement installé la version 4.2.

De plus, les instructions de cet article ne seront plus nécessaires.

Après avoir enregistré le modèle, j'ai fait une erreur qui n'était pas évidente pour moi, à savoir, j'ai immédiatement essayé de remplacer le fichier graph.pbtxt utilisé précédemment dans le dossier training / dans la fonction:

cv2.dnn.readNetFromTensorflow()

Malheureusement, cela ne fonctionne pas de cette façon et nous devrons effectuer une autre manipulation pour obtenir graph.pbtxt pour OpenCV.

Très probablement, le fait que je conseille maintenant n'est pas un très bon moyen, mais pour moi, cela fonctionne.

Téléchargez tf_text_graph_ssd.py , et aussi tf_text_graph_common.py mettez-les dans le dossier où se trouve notre graphique enregistré (j'ai ce dossier inference_graph).
Accédez ensuite à la console dans ce dossier et exécutez-y une commande d'environ le contenu suivant:

python tf_text_graph_ssd.py --input frozen_inference_graph.pb --config pipeline.config --output graph.pbtxt

Et c'est tout ce qu'il reste pour télécharger notre modèle sur OpenCV.


Partie III: appliquer le modèle dans OpenCV


Comme dans l'article sur PyTorch concernant le travail avec OpenCV, j'ai pris comme base le code du programme de cette publication .

J'ai fait de petits changements pour le simplifier un peu plus, mais comme je ne comprends pas bien le code, je ne le commenterai pas. Fonctionne et sympa. Il est clair que le code aurait pu être meilleur, mais je n'ai pas encore le temps de m'asseoir pour les tutoriels OpenCV .

Code OpenCV

# USAGE
# based on this code https://proglib.io/p/real-time-object-detection/
# import the necessary packages
from imutils.video import VideoStream
from imutils.video import FPS
import numpy as np
import imutils
import time
import cv2

prototxt="graph.pbtxt"
model="frozen_inference_graph.pb"
min_confidence = 0.5

# initialize the list of class labels MobileNet SSD was trained to
# detect, then generate a set of bounding box colors for each class
CLASSES = ["background", "duino","raspb"]
COLORS = [(40,50,60),((140,55,130)),(240,150,25)]

# load our serialized model from disk
print("[INFO] loading model...")

net =cv2.dnn.readNetFromTensorflow(model,prototxt)

# initialize the video stream, allow the cammera sensor to warmup,
# and initialize the FPS counter
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(0.5)
fps = FPS().start()

# loop over the frames from the video stream
while True:
	# grab the frame from the threaded video stream and resize it
	# to have a maximum width of 400 pixels
	frame = vs.read()
	frame = imutils.resize(frame, width=300)

	# grab the frame dimensions and convert it to a blob
	(h, w) = frame.shape[:2]
	blob = cv2.dnn.blobFromImage(frame, size=(300, 300), swapRB=True)

	# pass the blob through the network and obtain the detections and
	# predictions
	net.setInput(blob)
	detections = net.forward()

	# loop over the detections
	for i in np.arange(0, detections.shape[2]):
		# extract the confidence (i.e., probability) associated with
		# the prediction
		print (detections)
		confidence = detections[0, 0, i, 2]

		if confidence > min_confidence:
			# extract the index of the class label from the
			# `detections`, then compute the (x, y)-coordinates of
			# the bounding box for the object
			idx = 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")

			# draw the prediction on the frame
			label = "{}: {:.2f}%".format(CLASSES[idx],
				confidence * 100)
			cv2.rectangle(frame, (startX, startY), (endX, endY),
				COLORS[idx], 2)
			y = startY - 15 if startY - 15 > 15 else startY + 15
			cv2.putText(frame, label, (startX, y+3),
				cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 1)

	# show the output frame
	cv2.imshow("Frame", frame)
	key = cv2.waitKey(1) & 0xFF

	# if the `q` key was pressed, break from the loop
	if key == ord("q"):
		break

	# update the FPS counter
	fps.update()

# stop the timer and display FPS information
fps.stop()
print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))

# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()


Donc, tout est prêt. Nous lançons le modèle, pointons l'objectif vers mon ancien CraftDuino et apprécions le résultat:



à première vue, ce n'est pas mal du tout, mais ce n'est qu'à première vue.
On dirait qu'en 23 heures, le modèle a été recyclé, donc il donne de graves erreurs lors de la définition des objets.

Voici une démonstration visuelle:



Comme vous pouvez le voir, non seulement un couteau, mais même juste un fond noir, ce modèle le définit comme un contrôleur de type Arduino. C'est peut-être parce que dans les données d'entraînement, il y avait des images sombres avec l'Arduino et ses analogues, sur lesquelles le modèle a réussi à se cogner en 23 heures.

En conséquence, j'ai dû charger mon ordinateur pendant encore 8 heures et former un nouveau modèle.

Les choses vont beaucoup mieux avec elle.

Voici un exemple avec CraftDuino:



Les framboises vivantes ne sont pas à portée de main. J'ai dû imprimer des photos. Depuis l'écran du téléphone ou du moniteur, vous pouvez également reconnaître, mais à partir du papier, c'était plus pratique.



Vérifions comment le modèle reconnaît l'Arduino nano, qui en temps vouluDrzugrikpour moi, j'ai soudé dans mon méga appareil avec des capteurs:



comme vous pouvez le voir, il reconnaît assez bien, mais avec un très mauvais angle et sous un éclairage chaud, il peut reconnaître certains fragments comme les framboises. Mais en fait, une monture avec une erreur était difficile à saisir dans l'objectif.

Voyons maintenant comment elle classe les objets sur lesquels elle n'a pas été formée.

Encore une fois, un exemple avec un couteau et un fond noir:



cette fois, tout fonctionne comme il se doit.

Nous proposerons notre modèle pour reconnaître le petit contrôleur Canny 3, dont j'ai parlé dans un article précédent .



Étant donné que notre modèle ne sait rien, sauf les framboises et les contrôleurs de type arduino, nous pouvons dire que le modèle a reconnu le contrôleur Canny avec succès.

Certes, comme dans le cas de l'Arduino nano, cela dépend beaucoup de l'angle et de l'éclairage.

Avec la lumière chaude d'une lampe à incandescence et avec un angle infructueux, le contrôleur peut non seulement ne pas être reconnu, mais même être défini comme framboise. Certes, comme dans le cas précédent, ces angles devaient encore essayer de s'accrocher à l'objectif.



Eh bien, le dernier cas est une sorte de révérence pour l'article sur la classification des images dans PyTorch . Comme la dernière fois, l'ordinateur monocarte Raspberry Pi 2 et son logo sont compatibles dans un seul cadre. Contrairement à l'article précédent, dans lequel nous avons résolu le problème de classification et choisi un objet le plus probable pour l'image, dans ce cas, le logo et la framboise elle-même sont reconnus.




Partie IV: Conclusion


En conclusion, je tiens à dire que malgré l'inexpérience de ce petit exemple de travail avec l'API de détection d'objets Tensorflow, cela a pris deux jours de congé et une partie de lundi, je ne regrette rien. Quand au moins un peu de compréhension sur la façon de l'utiliser, tout devient incroyablement curieux. Dans le processus d'apprentissage, vous commencez à considérer le modèle comme un modèle vivant, à suivre ses succès et ses échecs.
Par conséquent, je recommande à tous ceux qui ne connaissent pas ce jour d'essayer de reconnaître quelque chose qui leur est propre.

De plus, comme il a augmenté au cours du processus, vous n'avez même pas besoin d'acheter une vraie webcam. Le fait est que lors de la préparation de l'article, j'ai réussi à casser ma webcam (cassé le mécanisme de mise au point) et pensais déjà que je devrais tout abandonner. Mais il s'est avéré qu'avec l'aide de Droidcam, vous pouvez utiliser un smartphone au lieu d'une webcam (ne comptez pas pour la publicité). De plus, la qualité de prise de vue s'est avérée bien meilleure que celle d'un appareil photo cassé, ce qui a grandement influencé la qualité de reconnaissance des objets dans l'image.

Soit dit en passant, puisque Anaconda a une construction normale de pycocotoolsJe n'ai trouvé que pour Linux, et j'étais trop paresseux pour basculer entre les systèmes d'exploitation, j'ai préparé cet article entier uniquement en utilisant un logiciel open source. Il y avait des analogues de Word et de Photoshop et même un pilote pour l'imprimante. La première fois de ma vie, cela s'est produit. Il s'est avéré que les versions modernes du système d'exploitation Linux et des programmes d'application peuvent être très pratiques, même pour une personne utilisant Microsoft OS depuis plus de 25 ans.

PS Si quelqu'un sait comment exécuter correctement l'API de détection d'objets
pour Tensorflow version 2 et supérieure, veuillez vous désabonner en PM ou dans un commentaire.

Passez une bonne journée et bonne santé!

All Articles