Marcadores OpenCV ArUco

Ammar Ali 21 junio 2023
Marcadores OpenCV ArUco

Este tutorial discutirá la detección de marcadores ArUco utilizando la función cv2.aruco.detectMarkers() de OpenCV.

Detección de marcador ArUco usando OpenCV

Los marcadores ArUco son imágenes binarias para estimación de poses, calibración de cámaras, navegación de robots y aplicaciones de realidad aumentada. En las aplicaciones de visión por computadora, la estimación de la pose es muy importante y difícil, pero podemos usar los marcadores ArUco para hacerlo más fácil.

Los marcadores ArUco son imágenes cuadradas binarias con un borde negro y el cuerpo interior tiene un color blanco, que cambia según el marcador. Por ejemplo, a continuación se muestra un marcador ArUco.

marcador aruco

El marcador ArUco anterior se genera utilizando un sitio web. Debemos seleccionar el diccionario, la identificación del marcador y el tamaño del marcador para generar un marcador ArUco usando este sitio web.

Un fabricante de ArUco consta de un diccionario ArUco, el tamaño del marcador y la identificación del marcador. Por ejemplo, un diccionario 4x4_100 consta de 100 marcadores con un tamaño de marcador 4x4, lo que significa que el marcador se compone de 25 bits y cada marcador tendrá una ID única.

Si usamos el diccionario predefinido de marcadores ArUco, el identificador del marcador comenzará desde 0 y terminará en el número máximo de marcadores que admite el diccionario. El proceso de detección devolverá las cuatro esquinas del fabricante ArUco y la identificación del marcador.

En el primer paso, el algoritmo analizará las imágenes dadas para encontrar imágenes de forma cuadrada. El algoritmo obtendrá los contadores de todas las formas presentes en la imagen dada, lo que dará información sobre las esquinas de una forma, y las formas que no sean cuadradas serán descartadas.

En el segundo paso, el algoritmo analizará la codificación interna de las formas restantes. Los bits de marcador se calcularán utilizando umbrales y los bits blanco y negro se separarán.

El algoritmo comprobará si los bits pertenecen o no a alguno de los diccionarios de ArUco. Si los bits pertenecen a un diccionario ArUco específico, se devolverá el ID del marcador.

Podemos usar la función detectMarkers() de OpenCV para detectar marcadores ArUco. El primer argumento de la función detectMarkers() es la imagen de entrada que contiene los marcadores ArUco.

El segundo argumento de la función detectMarkers() es el diccionario que queremos buscar para encontrar el marcador ArUco. El tercer argumento son los parámetros de detección, y podemos usar la función cv2.aruco.DetectorParameters_create() para crear parámetros por defecto para la detección de marcadores ArUco.

La función detectMarkers() devuelve tres argumentos de salida: esquinas de marcador, ID de marcador y marcadores rechazados. Después de encontrar las esquinas de los marcadores ArUco, usaremos un bucle para dibujar un cuadrado alrededor del marcador detectado usando la función cv2.line().

También pondremos el ID del marcador encima del marcador detectado usando la función cv2.putText(). También podemos marcar el centro del marcador usando la función cv2.circle().

Por ejemplo, detectemos marcadores ArUco presentes en una imagen usando la función cv2.aruco.detectMarkers(). Vea el código a continuación.

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

Producción:

marcadores detectados

En el código anterior, usamos la función cv2.aruco.Dictionary_get() para obtener el diccionario de marcadores ArUco restaurado. Recorreremos las esquinas de los marcadores detectados para dibujar un cuadro alrededor de ellos y colocar su ID encima de ellos.

También usamos una declaración if para verificar si las esquinas de los marcadores están disponibles o no. El primer argumento de la función cv2.line() es la imagen sobre la que queremos dibujar la línea.

Los argumentos segundo y tercero son puntos finales de la línea, y el cuarto argumento es el color de la línea en formato de triplete RGB. El quinto argumento es el ancho de la línea.

El primer argumento de la función cv2.circle() es la imagen de entrada sobre la que queremos dibujar el círculo, el segundo argumento es el centro del círculo, el tercer argumento es el radio del círculo, el cuarto argumento es el color del círculo, y el quinto argumento se usa para llenar el círculo.

El primer argumento de la función cv2.putText() es la imagen de entrada sobre la que queremos poner el texto.

El segundo argumento es el texto, el tercer argumento es el punto en el que queremos poner el texto, el cuarto argumento es el estilo de fuente, el quinto argumento es la escala de fuente, el sexto argumento es el color del texto y el el séptimo argumento es el ancho de línea del texto. Tenemos que usar el mismo diccionario para crear y detectar los marcadores.

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

Artículo relacionado - Python OpenCV