OpenCV – ArUco マーカーの作成、検出方法

目次

概要

OpenCV で ArUco マーカー画像を作成、画像から ArUco マーカーを検出する方法について解説します。

ArUco マーカー

ArUco (Augmented Reality University of Cordoba marker) マーカーとは、拡張現実のアプリケーションで使用することを意図して設計された視覚的なマーカー (通称 AR マーカー, Augmented Reality Markers) の一種で、カメラで簡単に認識できるようになっています。

ArUco マーカー画像を作成する

OpenCV で ArUco マーカーを作成する方法を解説します。

  1. ArUco マーカーには、マーカーの大きさと数に応じて、辞書がいくつか存在します。cv2.aruco.getPredefinedDictionary() に辞書 ID を指定して、50 種類のマーカーが含まれる辞書を取得します。例えば、辞書 ID が cv2.aruco.DICT_4X4_50 の場合、マーカーのサイズは 4x4 で、50 種類のマーカーがあることを意味します。
  2. marker_dict.generateImageMarker(id, sidePixels) を使用して、辞書内のマーカー ID が id であるマーカーを、解像度が (sidePixels, sidePixels) の画像として生成します。
In [1]:
import cv2
from IPython.display import Image, display


def imshow(img):
    """ndarray 配列をインラインで Notebook 上に表示する。"""
    ret, encoded = cv2.imencode(".png", img)
    display(Image(encoded))
In [2]:
import cv2


# Marker Dictionary を作成する。
marker_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_50)
marker_img = marker_dict.generateImageMarker(id=0, sidePixels=200)
imshow(marker_img)

画像に ArUco マーカーを描画する

大きな画像に ArUco マーカーを貼り付けた画像を作成したい場合、以下のコードを使用してください。

In [3]:
import cv2
import numpy as np


def paste(src, dst, x, y):
    """画像を貼り付ける。"""
    dst = dst.copy()
    src_h, src_w = src.shape[:2]
    dst_h, dst_w = dst.shape[:2]

    # 貼り付け範囲を計算する。
    # (x, y, x + src_w, y + src_h) と (0, 0, dst_w, dst_h) の共通部分を求める。
    dst_x1 = max(0, x)
    dst_x2 = min(x + src_w, dst_w)
    dst_y1 = max(0, y)
    dst_y2 = min(y + src_h, dst_h)

    if dst_x1 >= dst_x2 or dst_y1 >= dst_y2:
        return dst  # 貼り付け範囲がない場合

    dst[dst_y1:dst_y2, dst_x1:dst_x2] = src[
        dst_y1 - y : dst_y2 - y, dst_x1 - x : dst_x2 - x
    ]

    return dst


def create_marker_img(
    img_size,
    position,
    marker_size,
    dict_id=cv2.aruco.DICT_4X4_100,
    makrer_id=0,
    background=(255, 255, 255),
):
    """マーカー画像を作成する。"""
    img_w, img_h = img_size  # 背景画像の大きさ
    x, y = position  # 貼り付ける位置

    # 背景画像を作成する。
    img = np.full((img_h, img_w, 3), background, dtype=np.uint8)

    # マーカー画像を作成する。
    marker_dict = cv2.aruco.getPredefinedDictionary(dict_id)
    marker_img = marker_dict.generateImageMarker(id=makrer_id, sidePixels=marker_size)
    marker_img = cv2.cvtColor(marker_img, cv2.COLOR_GRAY2BGR)

    # 背景画像にマーカー画像を貼り付ける。
    dst = paste(marker_img, img, x, y)

    return dst


img = create_marker_img((640, 480), (50, 50), marker_size=100, background=(200, 200, 0))
cv2.imwrite("marker.png", img)

辞書の種類

マーカーのサイズや種類に応じて、以下の辞書が選択できます。 例えば、マーカーで区別したい物体が 200 種類ある場合、200 種類以上のマーカーが必要となるため、cv2.aruco.DICT_4X4_250 を選択します。

辞書 ID サイズ 種類
cv2.aruco.DICT_4X4_50 4 50
cv2.aruco.DICT_4X4_100 4 100
cv2.aruco.DICT_4X4_250 4 250
cv2.aruco.DICT_4X4_1000 4 1000
cv2.aruco.DICT_5X5_50 5 50
cv2.aruco.DICT_5X5_100 5 100
cv2.aruco.DICT_5X5_250 5 250
cv2.aruco.DICT_5X5_1000 5 1000
cv2.aruco.DICT_6X6_50 6 50
cv2.aruco.DICT_6X6_100 6 100
cv2.aruco.DICT_6X6_250 6 250
cv2.aruco.DICT_6X6_1000 6 1000
cv2.aruco.DICT_7X7_50 7 50
cv2.aruco.DICT_7X7_100 7 100
cv2.aruco.DICT_7X7_250 7 250
cv2.aruco.DICT_7X7_1000 7 1000
cv2.aruco.DICT_APRILTAG_16H5 4 30
cv2.aruco.DICT_APRILTAG_16h5 4 30
cv2.aruco.DICT_APRILTAG_25H9 5 35
cv2.aruco.DICT_APRILTAG_25h9 5 35
cv2.aruco.DICT_APRILTAG_36H11 6 587
cv2.aruco.DICT_APRILTAG_36h11 6 587
cv2.aruco.DICT_APRILTAG_36H10 6 2320
cv2.aruco.DICT_APRILTAG_36h10 6 2320
cv2.aruco.DICT_ARUCO_ORIGINAL 5 1024
cv2.aruco.DICT_ARUCO_MIP_36H12 6 250
cv2.aruco.DICT_ARUCO_MIP_36h12 6 250

ArUco マーカーを検出する

sample.jpg

In [4]:
import cv2

img = cv2.imread("sample.jpg")

# 検出対象の辞書 ID を指定して、マーカー辞書を作成する。
marker_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)

# マーカーを検出する。
params = cv2.aruco.DetectorParameters()
detector = cv2.aruco.ArucoDetector(marker_dict, params)
corners, ids, rejectedImgPoints = detector.detectMarkers(img)
for corner, marker_id in zip(corners, ids):
    print(f"マーカー ID: {marker_id}, 4点の座標: {corner}")

# 検出されたマーカーを描画する。
cv2.aruco.drawDetectedMarkers(img, corners, ids)

# rejectedImgPoints を描画する。
for points in rejectedImgPoints:
    cv2.polylines(img, points.astype(np.int64), isClosed=True, color=(0, 0, 255))

imshow(img)
マーカー ID: [40], 4点の座標: [[[359. 310.]
  [404. 310.]
  [410. 350.]
  [362. 350.]]]
マーカー ID: [98], 4点の座標: [[[427. 255.]
  [469. 256.]
  [477. 289.]
  [434. 288.]]]
マーカー ID: [62], 4点の座標: [[[233. 273.]
  [190. 273.]
  [196. 241.]
  [237. 241.]]]
マーカー ID: [23], 4点の座標: [[[298. 185.]
  [334. 186.]
  [335. 212.]
  [297. 211.]]]
マーカー ID: [124], 4点の座標: [[[425. 163.]
  [430. 186.]
  [394. 186.]
  [390. 162.]]]
マーカー ID: [203], 4点の座標: [[[195. 155.]
  [230. 155.]
  [227. 178.]
  [190. 178.]]]

コメント

コメントする

目次