本記事では、OpenCV + PythonでArUcoマーカを生成・検出するまでの手順について解説します。

使用した環境

・Ubuntu 18.04 LTS
・Python 3.6.9
・OpenCV 4.5.5

Python版OpenCVと拡張モジュール群のインストール

以下のコマンドを実行し、Python版OpenCVと拡張モジュール群のインストールを行います。

sudo apt install python3-pip
python3 -m pip install opencv-python
python3 -m pip install opencv-contrib-python

以下のエラーが発生した場合、pipの更新を行ってください。
【エラー内容】
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
 File “<string>”, line 1, in <module>
 File “/tmp/pip-build-a565ypsb/opencv-python/setup.py”, line 10, in <module>
 import skbuild
 ModuleNotFoundError: No module named ‘skbuild’
-------------------------------------------------------
Command “python setup.py egg_info” failed with error code 1 in /tmp/pip-build-a565ypsb/opencv-python/

【更新コマンド】

python3 -m pip install -U pip

ArUcoマーカの自動生成

以下のプログラムをコピーし実行すると、ArUcoマーカが自動生成されます。本プログラムで生成できるArUcoマーカの種類は、9行目の「aruco.DICT_4X4_50」で指定しています。これは、「DICT_ビット数_ID数」となっており、ビット数は縦横のビット数を指し、ID数は生成できるマーカの数を指しています。今回は、「aruco.DICT_4X4_50」なので、縦横が4ビットで、生成できるマーカの数が0~49の計50個となります。

cd ~/
mkdir -p ArMarker/script
cd ~/ArMarker/script
gedit arMarkerGenerator.py
sudo chmod 755 arMarkerGenerator.py
python3 arMarkerGenerator.py
#!/usr/bin/env python3
# coding: utf-8
import cv2
import numpy as np
# ArUcoのライブラリを導入
aruco = cv2.aruco

# 4x4のマーカ, IDは50までの辞書を使用
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
pixel = 150
offset = 10
cnt = 9

def generateArMarker():
	# 白いブランク画像を生成
	img = np.zeros((pixel + offset, pixel + offset), dtype=np.uint8)
	img += 255

	x_offset = y_offset = int(offset) // 2
	# 9枚のマーカを作成する
	for i in range(cnt):
		# 150x150ピクセルで画像を作成
		ar_image = aruco.drawMarker(dictionary, i, pixel, 3)
		# ファイル名の指定
		filename = "ar" + str(i) + ".png"
		# ブランク画像の上にArUcoマーカを重ねる
		img[y_offset:y_offset + ar_image.shape[0], x_offset:x_offset + ar_image.shape[1]] = ar_image
		# グレースケールからRGBへ変換
		rgb_img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
		
		# ArUcoマーカの画像を結合
		if (i % 3 == 0):
			hconcat_img = rgb_img
		elif (i % 3 <= 2):
			hconcat_img = cv2.hconcat([hconcat_img, rgb_img])
			if (i % 3 == 2 and i // 3 == 0):
				vconcat_img = hconcat_img
			elif (i % 3 == 2 and i // 3 > 0):
				vconcat_img = cv2.vconcat([vconcat_img, hconcat_img])

		# 1枚ごとのArUcoマーカを出力
		cv2.imwrite(filename, rgb_img)

	# 結合したArUcoマーカを出力
	cv2.imwrite("ar" + str(cnt) + ".png", vconcat_img)
        
if __name__ == "__main__":
    generateArMarker()

15~17行目で白色画像を生成しArUcoマーカを重ねています。これは、ArUcoマーカ単体の画像からマーカの検出を行う際に、ArUcoマーカの境界が判別できない影響でマーカの検出に失敗するためです。


図 1. 自動生成したArUcoマーカ

画像からArUcoマーカを検出

以下のプログラムをコピーし実行することで、「ArUcoマーカの自動生成」で生成した画像からArUcoマーカを検出します。

cd ~/ArMarker/script
gedit arMarkerRecognizer.py
sudo chmod 755 arMarkerRecognizer.py
python3 arMarkerRecognizer.py
#!/usr/bin/env python3
# coding: utf-8
import cv2
# ArUcoのライブラリを導入
aruco = cv2.aruco

# 4x4のマーカー, IDは50までの辞書を使用
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()

cnt = 9

def recognizeArMarker():
	for i in range(cnt + 1):
		# 入力ファイル名
		input_file_nm = "ar" + str(i) + ".png"
		# 出力ファイル名
		output_file_nm = "ar_detection" + str(i) + ".png"
		# 入力ファイルの読み込み
		input_img = cv2.imread(input_file_nm)
		# ArUcoマーカの検出
		corners, ids, rejectedCandidates = aruco.detectMarkers(input_img, dictionary, parameters=parameters)
		# ArUcoマーカの検出結果の描画
		ar_image = aruco.drawDetectedMarkers(input_img, corners, ids)

		# ArUcoマーカの検出結果をファイル出力
		cv2.imwrite(output_file_nm, ar_image)

if __name__ == "__main__":
    recognizeArMarker()

 


図 2. 検出したArUcoマーカ

 
いかがだったでしょうか。
近年ARマーカの活用が増えているため、今後活用する方などのお役に立つことができれば幸いです。