本記事では、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マーカの活用が増えているため、今後活用する方などのお役に立つことができれば幸いです。