OpenCV ArUco 마커
이 튜토리얼에서는 OpenCV의 cv2.aruco.detectMarkers()
기능을 사용하여 ArUco 마커 감지에 대해 설명합니다.
OpenCV를 사용한 ArUco 마커 감지
ArUco 마커는 포즈 추정, 카메라 보정, 로봇 내비게이션 및 증강 현실 애플리케이션을 위한 바이너리 이미지입니다. 컴퓨터 비전 애플리케이션에서 포즈 추정은 매우 중요하고 어렵지만 ArUco 마커를 사용하면 쉽게 할 수 있습니다.
ArUco 마커는 검정색 테두리가 있는 이진 정사각형 이미지이며 내부 바디는 마커에 따라 변경되는 흰색을 가집니다. 예를 들어 ArUco 마커는 아래와 같습니다.
위의 ArUco 마커는 website(https://chev.me/arucogen/)를 사용하여 생성됩니다. 이 website(https://chev.me/arucogen/)를 사용하여 ArUco 마커를 생성하려면 사전, 마커 ID 및 마커 크기를 선택해야 합니다.
ArUco Maker는 ArUco 사전, 마커 크기 및 마커 ID로 구성됩니다. 예를 들어 4x4_100
사전은 100
마커로 구성되며 4x4
마커 크기는 마커가 25비트로 구성되고 각 마커에 고유한 ID가 있음을 의미합니다.
미리 정의된 ArUco 마커 사전을 사용하는 경우 마커 ID는 0부터 시작하여 사전에서 지원하는 최대 마커 수에서 끝납니다. 감지 프로세스는 ArUco 메이커의 네 모서리와 마커 ID를 반환합니다.
첫 번째 단계에서 알고리즘은 주어진 이미지를 분석하여 사각형 모양 이미지를 찾습니다. 알고리즘은 주어진 이미지에 있는 모든 모양의 카운터를 가져와 모양의 모서리에 대한 정보를 제공하고 정사각형이 아닌 모양은 폐기합니다.
두 번째 단계에서 알고리즘은 나머지 모양의 내부 코드화를 분석합니다. 마커 비트는 임계값을 사용하여 계산되며 흰색과 검은색 비트가 분리됩니다.
알고리즘은 비트가 ArUco 사전에 속하는지 여부를 확인합니다. 비트가 특정 ArUco 사전에 속하는 경우 마커의 ID가 반환됩니다.
OpenCV의 detectMarkers()
기능을 사용하여 ArUco 마커를 감지할 수 있습니다. detectMarkers()
함수의 첫 번째 인수는 ArUco 마커를 포함하는 입력 이미지입니다.
detectMarkers()
함수의 두 번째 인수는 ArUco 마커를 찾기 위해 검색하려는 사전입니다. 세 번째 인수는 감지 매개변수이며 cv2.aruco.DetectorParameters_create()
함수를 사용하여 ArUco 마커 감지를 위한 기본 매개변수를 생성할 수 있습니다.
detectMarkers()
함수는 마커 모서리, 마커 ID 및 거부된 마커의 세 가지 출력 인수를 반환합니다. ArUco 마커의 모서리를 찾은 후 루프를 사용하여 cv2.line()
함수를 사용하여 감지된 마커 주위에 사각형을 그립니다.
또한 cv2.putText()
함수를 사용하여 감지된 마커 위에 마커 ID를 배치합니다. cv2.circle()
함수를 사용하여 마커의 중심을 표시할 수도 있습니다.
예를 들어 cv2.aruco.detectMarkers()
기능을 사용하여 이미지에 있는 ArUco 마커를 감지해 보겠습니다. 아래 코드를 참조하십시오.
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()
출력:
위의 코드에서 cv2.aruco.Dictionary_get()
함수를 사용하여 복원된 ArUco 마커 사전을 가져왔습니다. 감지된 마커의 모서리를 반복하여 주위에 상자를 그리고 그 위에 ID를 배치합니다.
또한 if
문을 사용하여 마커 코너를 사용할 수 있는지 여부를 확인했습니다. cv2.line()
함수의 첫 번째 인수는 선을 그리려는 이미지입니다.
두 번째 및 세 번째 인수는 선의 끝점이고 네 번째 인수는 RGB 3색 형식의 선 색상입니다. 다섯 번째 인수는 선의 너비입니다.
cv2.circle()
함수의 첫 번째 인수는 원을 그리려는 입력 이미지이고, 두 번째 인수는 원의 중심이고, 세 번째 인수는 원의 반경이고, 네 번째 인수는 원의 색상, 다섯 번째 인수는 원을 채우는 데 사용됩니다.
cv2.putText()
함수의 첫 번째 인수는 텍스트를 입력하려는 입력 이미지입니다.
두 번째 인수는 텍스트, 세 번째 인수는 텍스트를 넣을 위치, 네 번째 인수는 글꼴 스타일, 다섯 번째 인수는 글꼴 크기, 여섯 번째 인수는 텍스트 색상, 일곱 번째 인수는 텍스트의 행 너비입니다. 마커를 생성하고 감지하려면 동일한 사전을 사용해야 합니다.