OpenCV ArUco-Marker

Ammar Ali 21 Juni 2023
OpenCV ArUco-Marker

In diesem Tutorial wird die Erkennung von ArUco-Markern mit der Funktion cv2.aruco.detectMarkers() von OpenCV behandelt.

ArUco-Markererkennung mit OpenCV

ArUco-Marker sind Binärbilder für Posenschätzung, Kamerakalibrierung, Roboternavigation und Augmented-Reality-Anwendungen. In Computer-Vision-Anwendungen ist die Posenschätzung sehr wichtig und schwierig, aber wir können die ArUco-Marker verwenden, um es einfach zu machen.

ArUco-Marker sind binäre quadratische Bilder mit einem schwarzen Rand, und der innere Körper hat eine weiße Farbe, die sich je nach Marker ändert. Als Beispiel wird unten ein ArUco-Marker gezeigt.

Aruco-Marker

Der obige ArUco-Marker wird mithilfe einer Website(https://chev.me/arucogen/) generiert. Wir müssen das Wörterbuch, die Marker-ID und die Markergröße auswählen, um einen ArUco-Marker mit dieser Website(https://chev.me/arucogen/) zu generieren.

Ein ArUco-Ersteller besteht aus einem ArUco-Wörterbuch, einer Markierungsgröße und einer Markierungs-ID. Beispielsweise besteht ein 4x4_100-Wörterbuch aus 100 Markierungen mit einer Markierungsgröße von 4x4, was bedeutet, dass die Markierung aus 25 Bits besteht und jede Markierung eine eindeutige ID hat.

Wenn wir das vordefinierte Wörterbuch von ArUco-Markierungen verwenden, beginnt die Markierungs-ID bei 0 und endet bei der maximalen Anzahl von Markierungen, die vom Wörterbuch unterstützt werden. Der Erkennungsprozess gibt die vier Ecken des ArUco-Markers und die Markierungs-ID zurück.

Im ersten Schritt analysiert der Algorithmus die gegebenen Bilder, um quadratische Bilder zu finden. Der Algorithmus erhält die Zähler aller im gegebenen Bild vorhandenen Formen, die Informationen über die Ecken einer Form liefern, und die Formen, die nicht quadratisch sind, werden verworfen.

Im zweiten Schritt analysiert der Algorithmus die innere Codierung der verbleibenden Formen. Die Markierungsbits werden unter Verwendung von Schwellenwerten berechnet, und weiße und schwarze Bits werden getrennt.

Der Algorithmus prüft, ob die Bits zu einem der ArUco-Wörterbücher gehören oder nicht. Wenn die Bits zu einem bestimmten ArUco-Wörterbuch gehören, wird die ID des Markers zurückgegeben.

Wir können die Funktion detectMarkers() von OpenCV verwenden, um ArUco-Marker zu erkennen. Das erste Argument der Funktion detectMarkers() ist das Eingabebild, das die ArUco-Marker enthält.

Das zweite Argument der Funktion detectMarkers() ist das Wörterbuch, das wir durchsuchen möchten, um den ArUco-Marker zu finden. Das dritte Argument sind die Erkennungsparameter, und wir können die Funktion cv2.aruco.DetectorParameters_create() verwenden, um Standardparameter für die Erkennung von ArUco-Markern zu erstellen.

Die Funktion detectMarkers() gibt drei Ausgabeargumente zurück: Markierungsecken, Markierungs-ID und abgelehnte Markierungen. Nachdem wir die Ecken der ArUco-Marker gefunden haben, verwenden wir eine Schleife, um mit der Funktion cv2.line() ein Quadrat um den erkannten Marker zu zeichnen.

Wir werden auch die Markierungs-ID über die erkannte Markierung setzen, indem wir die Funktion cv2.putText() verwenden. Wir können auch die Mitte des Markers mit der Funktion cv2.circle() markieren.

Lassen Sie uns zum Beispiel in einem Bild vorhandene ArUco-Marker mit der Funktion cv2.aruco.detectMarkers() erkennen. Siehe Code unten.

import imutils
import cv2

aruco_image = cv2.imread("aruco markers.png")
aruco_image = imutils.resize(aruco_image, width=600)
cv2.imshow("img", aruco_image)
cv2.waitKey(0)
Aruco_Dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_5X5_100)
Aruco_Params = cv2.aruco.DetectorParameters_create()
(marker_corners, marker_id, rejected_markers) = cv2.aruco.detectMarkers(
    aruco_image, Aruco_Dict, parameters=Aruco_Params
)

if len(marker_corners) > 0:
    marker_id = marker_id.flatten()

    for (markerCorner, markerID) in zip(marker_corners, marker_id):
        marker_corners = markerCorner.reshape((4, 2))
        (top_Left, top_Right, bottom_Right, bottom_Left) = marker_corners
        top_Right = (int(top_Right[0]), int(top_Right[1]))
        bottom_Right = (int(bottom_Right[0]), int(bottom_Right[1]))
        bottom_Left = (int(bottom_Left[0]), int(bottom_Left[1]))
        top_Left = (int(top_Left[0]), int(top_Left[1]))

        cv2.line(aruco_image, top_Left, top_Right, (255, 0, 0), 2)
        cv2.line(aruco_image, top_Right, bottom_Right, (255, 0, 0), 2)
        cv2.line(aruco_image, bottom_Right, bottom_Left, (255, 0, 0), 2)
        cv2.line(aruco_image, bottom_Left, top_Left, (255, 0, 0), 2)
        cX = int((top_Left[0] + bottom_Right[0]) / 2.0)
        cY = int((top_Left[1] + bottom_Right[1]) / 2.0)
        cv2.circle(aruco_image, (cX, cY), 4, (0, 255, 0), -1)
        cv2.putText(
            aruco_image,
            str(markerID),
            (top_Left[0], top_Left[1] - 5),
            cv2.FONT_HERSHEY_SIMPLEX,
            2,
            (255, 0, 0),
            2,
        )
        print("Aruco Marker ID: {}".format(markerID))
        cv2.imshow("Image", aruco_image)
        cv2.waitKey(0)
cv2.destroyAllWindows()

Ausgang:

erkannte Marker

Im obigen Code haben wir die Funktion cv2.aruco.Dictionary_get() verwendet, um das wiederhergestellte ArUco-Markerwörterbuch abzurufen. Wir werden die Ecken der erkannten Markierungen durchlaufen, um ein Kästchen um sie herum zu zeichnen und ihre ID darauf zu setzen.

Wir haben auch eine if-Anweisung verwendet, um zu prüfen, ob Markierungsecken verfügbar sind oder nicht. Das erste Argument der Funktion cv2.line() ist das Bild, auf dem wir die Linie zeichnen wollen.

Das zweite und dritte Argument sind Endpunkte der Linie, und das vierte Argument ist die Farbe der Linie im RGB-Triplet-Format. Das fünfte Argument ist die Breite der Linie.

Das erste Argument der Funktion cv2.circle() ist das Eingabebild, auf dem wir den Kreis zeichnen wollen, das zweite Argument ist der Mittelpunkt des Kreises, das dritte Argument ist der Radius des Kreises, das vierte Argument ist die Farbe des Kreises, und das fünfte Argument wird verwendet, um den Kreis zu füllen.

Das erste Argument der Funktion cv2.putText() ist das Eingabebild, auf dem wir den Text platzieren möchten.

Das zweite Argument ist der Text, das dritte Argument ist der Punkt, an dem wir den Text platzieren möchten, das vierte Argument ist der Schriftstil, das fünfte Argument ist die Schriftskalierung, das sechste Argument ist die Farbe des Textes und die Das siebte Argument ist die Zeilenbreite des Textes. Wir müssen dasselbe Wörterbuch verwenden, um die Marker zu erstellen und zu erkennen.

Autor: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

Verwandter Artikel - Python OpenCV