In Python habe ich, insbesondere mit Unterstützung von OpenCV, versucht, ein rotes Objekt am Bild der Videokamera zu erkennen, also habe ich einen Artikel verfasst.
Aufgrund der Verwendung von OpenCV ist es möglich, C / C ++ anstelle von Python zu verwenden. Wenn Sie es jedoch mit Python erstellen, können Sie es mit überraschend geringem Arbeitsaufwand schreiben. Es ist erstaunlich.
Also habe ich versucht, einen Artikel w zu schreiben
Der Begriff Algorithmus ist cool zu verwenden, aber nicht so hoch. Ich möchte auf den Mechanismus zur Erkennung roter Objekte eingehen.
Ich denke, es gibt RGB als Standardmethode zum Ausdrücken von Farben. Durch Ausdrücken der Helligkeit von R, G und B von 0 bis 255 wird eine 24-Bit-Farbe. Kann dieses RGB also zur Bestimmung von Rot verwendet werden? Es ist eigentlich ziemlich schwierig. Zum Beispiel ist R = 255, G = 0, B = 0 rot, egal wer was sagt. Aber was ist mit R = 10, G = 0, B = 0? Ist das nicht eher schwarz als rot? Ich fühle mich so. Mit anderen Worten, es ist schwierig, den Farbton mit RGB zu beurteilen.
Daher verwenden wir eine Datenstruktur namens HSV-Farbraum. \ (Weitere Informationen finden Sie unter [Wikipedia](https://ja.wikipedia.org/wiki/HSV Farbraum) )
Erstellen wir nun eine Funktion und konvertieren sie in den HSV-Farbraum. Das Importieren von OpenCV und Numpy ist ein Standard.
import cv2
import numpy as np
def find_rect_of_target_color(image):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV_FULL)
h = hsv[:, :, 0]
s = hsv[:, :, 1]
Bis zu diesem Punkt wurden die H- und S-Komponenten des Bildes extrahiert. Die H-Komponente ist Farbton (Farbton). Eigentlich dreht es sich in 360 Schritten wie ein Kreis: rot → grün → blau → rot. Wie ich zu Beginn schrieb, ist es schwierig, den Farbton mit RGB zu beurteilen, aber wenn man ihn einmal auf HSV umgestellt hat, ist es sehr einfach, ihn anhand des Farbtons zu beurteilen, wenn man sich H ansieht.
Im Fall von OpenCV werden H, S und V alle in 256 Schritten gehalten (wenn COLOR_BGR2HSV_FULL
angegeben ist), daher sollte das ursprüngliche H 360 Schritte betragen, es wird jedoch auf 256 Schritte gerundet. Berücksichtigen Sie diese Seite und fahren Sie fort.
Apropos Rot in Farbton (Farbton), es ist ungefähr 280 bis 28 ° einschließlich des violetten Bereichs. Wenn Sie dies in 256 Schritten neu berechnen, werden es meiner Meinung nach etwa 200 bis 20 sein. Daher ist der Bereich, in dem der Wert von H ist (H <20 | H> 200), rot.
Achten Sie auch auf die Farbtiefe. Selbst wenn der Farbton (Farbton) rot ist, nähert er sich, wenn die Farbe hell genug ist, Weiß oder Schwarz an. Es ist notwendig, die S-Komponente und die Sättigung gleichzeitig zu beurteilen. Dies liegt normalerweise im Bereich von 0 bis 255, und je größer die Zahl, desto "lebendiger" ist sie. Da es sich um ein rotes Urteil handelt, fügen wir es hier unter der Bedingung hinzu, dass der Wert von S (S> 128) ist.
Wenn Sie diese numpy zusammenschreiben, sieht es folgendermaßen aus.
mask = np.zeros(h.shape, dtype=np.uint8)
mask[((h < 20) | (h > 200)) & (s > 128)] = 255
Jetzt haben Sie die Maskendaten, die den roten Teil zeigen. (255 für Rot, 0 für Nichtrot) Aber das ist nicht das Ende. Diese Maskendaten zeigen nur "wo die Punkte rötlich sind" im Bild.
Schließlich möchte ich, solange es ein rotes Objekt erkennt, einen Punktblock einer bestimmten Größe erkennen. So wie es jetzt ist, ist es nur eine Gruppe von Punkten, und es gibt keine Einheit. Um diese Daten, die nur ein Punkt sind, als Block zu erkennen, betrachten wir zunächst eine sogenannte "Kontur". Sobald Sie eine Kontur haben, kennen Sie die Masse, die von dieser Kontur umgeben ist.
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Die Kombination von OpenCV und Python ist großartig. Sie können es in nur einer Zeile schreiben. Schauen wir uns nun den Inhalt von "Konturen" an. Tatsächlich wurde die Kontur bei der Herstellung bereits in Stücken angeordnet.
rects = []
for contour in contours:
approx = cv2.convexHull(contour)
rect = cv2.boundingRect(approx)
rects.append(rect)
Ich werde das gleiche noch einmal schreiben, aber die Kombination von OpenCV und Python ist großartig. Es ist wirklich prägnant.
cv2.convexHull ()
ist eine Funktion, die eine konvexe Form berechnet, die eine ungleichmäßige Masse enthält. Die "Kontur" enthält Punktinformationen, die den Umriss bilden. Da es sich jedoch nur um einen Umriss handelt, hat sie eine sehr komplizierte Form, wie eine Rias-Küste. Es ist "cv2.convexHull ()", das daraus ein 2D-Polygon macht, das aussieht wie eine Tasche, die sich umhüllt. Der Rückgabewert "approx" ist ein Array von (X, Y).
Dann berechnet cv2.boundingRect ()
das Rechteck, in das das beutelförmige Polygon passt. Es gibt rechteckige Informationen des Formulars zurück (x, y, Breite, Höhe).
Bis zu diesem Punkt wurden die Informationen zur Punktgruppe in einer Liste von Rechtecken für jeden Block gesammelt.
Lassen Sie uns nun verbinden, was ich separat geschrieben habe.
import cv2
import numpy as np
def find_rect_of_target_color(image):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV_FULL)
h = hsv[:, :, 0]
s = hsv[:, :, 1]
mask = np.zeros(h.shape, dtype=np.uint8)
mask[((h < 20) | (h > 200)) & (s > 128)] = 255
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
rects = []
for contour in contours:
approx = cv2.convexHull(contour)
rect = cv2.boundingRect(approx)
rects.append(np.array(rect))
return rects
Nur das. Mit genau diesem haben wir eine Funktion, die ein Array von Rechtecken zurückgibt, die die roten Punkte im gegebenen Bild identifizieren.
Nachdem ich es bisher gemacht habe, möchte ich seinen Betrieb bestätigen. Verarbeiten wir in Echtzeit mit dem Bild der Videokamera.
if __name__ == "__main__":
capture = cv2.VideoCapture()
while cv2.waitKey(30) < 0:
_, frame = capture.read()
rects = find_rect_of_target_color(frame)
for rect in rects:
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness=2)
cv2.imshow('red', frame)
capture.release()
cv2.destroyAllWindows()
Wie ist das? Haben Sie die erwarteten Ergebnisse erzielt? Es ist meine Erwartung, aber ich denke, es war ein schlechtes Ergebnis. Das liegt daran, dass sowohl große als auch kleine Rechtecke als "rote Objekte" erkannt werden. Es ist Unsinn, sich so etwas wie Lärm als "Objekt" vorzustellen. Lassen Sie es uns ausdünnen, weil es eine bestimmte Größe hat.
Hier ist eine kleine Empfehlung, nur das größte Rechteck zu einem "roten Objekt" zu machen. Haben Sie das rote Objekt vor der Kamera gehalten, um ein rotes Objekt zu erkennen? Mit anderen Worten, ich wollte es erkennen. Oft möchten Sie die größte Kopie erkennen.
Ändern Sie Folgendes, damit derjenige mit dem größten Bereich aus der erhaltenen rechteckigen Liste gesucht wird.
if __name__ == "__main__":
capture = cv2.VideoCapture()
while cv2.waitKey(30) < 0:
_, frame = capture.read()
rects = find_rect_of_target_color(frame)
if len(rects) > 0:
rect = max(rects, key=(lambda x: x[2] * x[3]))
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness=2)
cv2.imshow('red', frame)
capture.release()
cv2.destroyAllWindows()
Das war's für diese Zeit. Ich bin beeindruckt, dass die Kombination von Python + OpenCV sehr praktisch ist.
Recommended Posts