"Entschuldigung, ich habe erkannt ..." oder Himbeeren und Controller mithilfe der Tensorflow-Objekterkennungs-API erkannt

Ende letzten Jahres schrieb ich einen Artikel darüber, wie fasziniert mich die Fähigkeit war, Objekte in Bildern mithilfe neuronaler Netze zu erkennen. In diesem Artikel haben wir mit PyTorch entweder Himbeeren oder einen Arduino-ähnlichen Controller auf Video kategorisiert. Und trotz der Tatsache, dass ich PyTorch mochte, wandte ich mich an ihn, weil ich nicht sofort mit TensorFlow umgehen konnte. Aber ich habe versprochen, dass ich zum Thema Erkennung von Objekten im Video zurückkehren werde. Es scheint an der Zeit zu sein, das Versprechen zu halten.

In diesem Artikel werden wir auf unserem lokalen Computer versuchen, das fertige Modell in Tensorflow 1.13 und die Objekterkennungs-API für unsere eigenen Bilder neu zu trainieren und dann mit OpenCV Beeren und Controller im Videostream einer Webkamera zu erkennen.

Möchten Sie Ihre Fähigkeiten zur Beerenerkennung bis zum Sommer verbessern? Dann sind Sie unter Katze willkommen.



Inhalt:

Teil I: Einführung
Teil II: Trainieren des Modells in TenosrFlow
Teil III: Anwenden des Modells in OpenCV
Teil IV: Schlussfolgerung

Teil I: Einführung


Diejenigen, die den vorherigen Artikel über PyTorch gelesen haben, wissen bereits, dass ich ein Amateur in Fragen neuronaler Netze bin. Nehmen Sie diesen Artikel daher nicht als die ultimative Wahrheit wahr. Trotzdem hoffe ich, dass ich jemandem helfen kann, mit den Grundlagen der Videoerkennung mithilfe der Tensorflow-Objekterkennungs-API umzugehen.

Dieses Mal habe ich nicht versucht, ein Tutorial zu erstellen, daher ist der Artikel kürzer als gewöhnlich.
Zunächst ist das offizielle Tutorial zur Verwendung der Objekterkennungs-API auf einem lokalen Computer, gelinde gesagt, kaum erschöpfend. Als Neuling war ich völlig unzureichend und musste mich auf Blog-Artikel konzentrieren.

Um ehrlich zu sein, würde ich gerne TensorFlow 2.0 ausprobieren, aber in den meisten Veröffentlichungen waren Migrationsprobleme zum Zeitpunkt dieses Schreibens nicht vollständig gelöst. Daher habe ich mich am Ende für TF 1.13.2 entschieden.

Teil II: Modellunterricht bei TensorFlow


Ich habe Anweisungen zum Unterrichten des Modells aus diesem Artikel bzw. aus der ersten Hälfte gezogen, bis JavaScript angewendet wurde (Wenn Sie kein Englisch sprechen, können Sie einen Artikel zum gleichen Thema in Habré sehen ) .

In meinem Fall gibt es zwar mehrere Unterschiede:

  1. Ich habe Linux verwendet, weil Anaconda für Linux bereits Protobuf und Pycocoapi erstellt hat, sodass ich sie nicht selbst erstellen musste.
  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, , .

Für alle Fälle möchte ich sagen, dass ich keinen Grafikbeschleuniger verwendet habe. Die Schulung wurde nur zu Prozessorkapazitäten durchgeführt.

Eine Reihe von Bildern, eine Konfigurationsdatei, ein gespeichertes Diagramm sowie ein Skript zum Erkennen von Bildern mit OpenCV können wie immer von GitHub heruntergeladen werden .

Eine lange 23-stündige Modellschulung ist vergangen, der gesamte Tee im Haus wurde bereits getrunken: „Was? Wo? Wann?" inspiziert und jetzt ging meine Geduld endlich zu Ende.

Wir beenden das Training und speichern das Modell.

Installieren Sie OpenCV in derselben Umgebung wie "Anaconda" mit dem folgenden Befehl:

conda install -c conda-forge opencv

Ich habe schließlich Version 4.2 installiert.

Außerdem werden wir die Anweisungen aus diesem Artikel nicht mehr benötigen.

Nach dem Speichern des Modells habe ich einen Fehler gemacht, der mir nicht klar war: Ich habe sofort versucht, die zuvor im Training / Ordner in der Funktion verwendete Datei graph.pbtxt zu ersetzen:

cv2.dnn.readNetFromTensorflow()

Leider funktioniert dies nicht auf diese Weise und wir müssen noch eine Manipulation durchführen, um graph.pbtxt für OpenCV zu erhalten.

Höchstwahrscheinlich ist die Tatsache, dass ich jetzt berate, kein sehr guter Weg, aber für mich funktioniert es.

Laden Sie tf_text_graph_ssd.py herunter und legen Sie sie in tf_text_graph_common.py in dem Ordner ab, in dem sich unser gespeichertes Diagramm befindet (ich habe diesen Ordner inference_graph).
Gehen Sie dann zur Konsole in diesem Ordner und führen Sie von dort aus einen Befehl mit ungefähr den folgenden Inhalten aus:

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

Und das ist alles, was Sie brauchen, um unser Modell auf OpenCV hochzuladen.


Teil III: Wenden Sie das Modell in OpenCV an


Wie im Artikel über PyTorch über die Arbeit mit OpenCV habe ich den Programmcode aus dieser Veröffentlichung zugrunde gelegt .

Ich habe kleine Änderungen vorgenommen, um es ein wenig zu vereinfachen, aber da ich den Code nicht vollständig verstehe, werde ich ihn nicht kommentieren. Funktioniert und schön. Es ist klar, dass der Code besser hätte sein können, aber ich habe noch keine Zeit, mich für OpenCV-Tutorials zu setzen .

OpenCV-Code

# 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()


Also ist alles fertig. Wir starten das Modell, richten das Objektiv auf meinen alten CraftDuino und genießen das Ergebnis:



Auf den ersten Blick ist es überhaupt nicht schlecht, aber nur auf den ersten Blick.
Es sieht so aus, als ob das Modell in 23 Stunden umgeschult wurde, daher gibt es schwerwiegende Fehler bei der Definition von Objekten.

Hier ist eine visuelle Demonstration:



Wie Sie sehen können, definiert dieses Modell nicht nur ein Messer, sondern auch nur einen schwarzen Hintergrund als arduinoähnlichen Controller. Vielleicht liegt das daran, dass in den Trainingsdaten dunkle Bilder mit dem Arduino und seinen Analoga waren, auf denen das Modell in 23 Stunden stoßen konnte.

Infolgedessen musste ich meinen Computer für weitere 8 Stunden laden und ein neues Modell trainieren.

Bei ihr läuft es viel besser.

Hier ist ein Beispiel mit CraftDuino:



Lebende Himbeeren sind nicht zur Hand. Ich musste Bilder drucken. Auf dem Bildschirm des Telefons oder Monitors können Sie auch erkennen, aber auf dem Papier war es bequemer.



Lassen Sie uns überprüfen, wie das Modell den Arduino Nano erkennt, was zu gegebener ZeitDrzugrikFür mich habe ich mit Sensoren in mein Mega-Gerät eingelötet:



Wie Sie sehen, erkennt es recht gut, aber bei einem sehr schlechten Winkel und bei warmem Licht kann es einige Fragmente wie Himbeeren erkennen. Tatsächlich war es jedoch schwierig, einen fehlerhaften Rahmen in der Linse zu erfassen.

Lassen Sie uns nun überprüfen, wie sie die Objekte klassifiziert, für die sie nicht trainiert wurde.

Wieder ein Beispiel mit einem Messer und einem schwarzen Hintergrund:



Diesmal funktioniert alles so, wie es sollte.

Wir werden unser Modell anbieten, um den winzigen Canny 3-Controller zu erkennen, über den ich in einem früheren Artikel geschrieben habe .



Da unser Modell nichts anderes als Himbeeren und Arduino-ähnliche Controller kennt, können wir sagen, dass das Modell den Canny-Controller recht erfolgreich erkannt hat.

Wie beim Arduino Nano hängt vieles vom Winkel und der Beleuchtung ab.

Mit dem warmen Licht einer Glühlampe und mit einem erfolglosen Winkel kann der Controller nicht nur nicht erkannt, sondern sogar als Himbeere definiert werden. Zwar mussten diese Winkel wie im vergangenen Fall immer noch versuchen, sich in der Linse zu verfangen.



Nun, der letzte Fall ist eine Art Knicks für den Artikel über die Klassifizierung von Bildern in PyTorch . Wie beim letzten Mal sind der Einplatinencomputer Raspberry Pi 2 und sein Logo in einem Frame kompatibel. Im Gegensatz zum vorherigen Artikel, in dem wir das Klassifizierungsproblem gelöst und ein wahrscheinlichstes Objekt für das Bild ausgewählt haben, werden in diesem Fall sowohl das Logo als auch die Himbeere selbst erkannt.




Teil IV: Schlussfolgerung


Abschließend möchte ich sagen, dass ich trotz der Unerfahrenheit dieses kleinen Beispiels für die Arbeit mit der Tensorflow-Objekterkennungs-API sowohl freie Tage als auch einen Teil des Montags nicht bereue. Wenn zumindest ein wenig Verständnis für die Verwendung alles unglaublich neugierig wird. Während des Lernprozesses beginnen Sie, das Modell als lebendiges Modell zu betrachten und seine Erfolge und Misserfolge zu verfolgen.
Daher empfehle ich jedem, der mit diesem einen Tag nicht vertraut ist, etwas Eigenes zu erkennen.

Da es dabei gestiegen ist, müssen Sie nicht einmal eine echte Webcam kaufen. Tatsache ist, dass ich während der Vorbereitung des Artikels meine Webcam kaputt gemacht habe (den Fokusmechanismus gebrochen habe) und bereits gedacht habe, dass ich alles aufgeben müsste. Es stellte sich jedoch heraus, dass Sie mit Hilfe von Droidcam ein Smartphone anstelle einer Webcam verwenden können (nicht für Werbung zählen). Darüber hinaus erwies sich die Aufnahmequalität als viel besser als die einer kaputten Kamera, was die Qualität der Erkennung von Objekten im Bild stark beeinflusste.

Übrigens, da Anaconda einen normalen Pycocotool- Aufbau hatIch fand nur für Linux, und ich war zu faul, um zwischen Betriebssystemen zu wechseln. Ich habe diesen gesamten Artikel nur mit Open-Source-Software vorbereitet. Es gab Analoga von Word und Photoshop und sogar einen Treiber für den Drucker. Das erste Mal in meinem Leben geschah dies. Es stellte sich heraus, dass moderne Versionen von Linux-Betriebssystemen und Anwendungsprogrammen sehr praktisch sein können, selbst für Personen, die Microsoft OS seit mehr als 25 Jahren verwenden.

PS Wenn jemand weiß, wie die Objekterkennungs-API
für Tensorflow Version 2 und höher ordnungsgemäß ausgeführt wird, melden Sie sich bitte in PM oder in einem Kommentar ab.

Einen schönen Tag und gute Gesundheit!

All Articles