こんにちは、えんせきです。
4月は展示会だらけで忙しいのとRubyいじってばっかりだったので今日は息抜きに画像処理をやりました。
ArUcoとは?
ArUcoマーカはマーカを検出してカメラとかカメラから見たマーカの位置・姿勢を推定するのに使える。
白と黒のバイナリ形式で正方形、見栄えはどう見てもマーカだけどロバストな検出と簡単に使えて計算が早いのが利点。
ロボットとかでもよく使われている。
C++の例が多いので今日はPythonのOpenCVでやってみた。
OpenCV: ArUco marker detection (aruco module)
OpenCVとOpenCV Contribをインストール(MacOS+python3.6.x+pip)
OpenCVをインストールする
pip install opencv-python
OpenCV Contribをインストールする
pip install opencv-contrib-python
実行確認
>>> import cv2 >>> cv2.__version__ '3.4.0' >>> dir(cv2.aruco) ['Board_create', 'CORNER_REFINE_CONTOUR', 'CORNER_REFINE_NONE', 'CORNER_REFINE_SUBPIX', 'CharucoBoard_create', 'DICT_4X4_100', 'DICT_4X4_1000', 'DICT_4X4_250', 'DICT_4X4_50', 'DICT_5X5_100', 'DICT_5X5_1000', 'DICT_5X5_250', 'DICT_5X5_50', 'DICT_6X6_100', 'DICT_6X6_1000', 'DICT_6X6_250', 'DICT_6X6_50', 'DICT_7X7_100', 'DICT_7X7_1000', 'DICT_7X7_250', 'DICT_7X7_50', 'DICT_ARUCO_ORIGINAL', 'DetectorParameters_create', 'Dictionary_create', 'Dictionary_create_from', 'Dictionary_get', 'GridBoard_create', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'calibrateCameraAruco', 'calibrateCameraArucoExtended', 'calibrateCameraCharuco', 'calibrateCameraCharucoExtended', 'custom_dictionary', 'custom_dictionary_from', 'detectCharucoDiamond', 'detectMarkers', 'drawAxis', 'drawDetectedCornersCharuco', 'drawDetectedDiamonds', 'drawDetectedMarkers', 'drawMarker', 'drawPlanarBoard', 'estimatePoseBoard', 'estimatePoseCharucoBoard', 'estimatePoseSingleMarkers', 'getBoardObjectAndImagePoints', 'getPredefinedDictionary', 'interpolateCornersCharuco', 'refineDetectedMarkers']
コード
import cv2 cap = cv2.VideoCapture(0) dictionary_name = cv2.aruco.DICT_6X6_250 dictionary = cv2.aruco.getPredefinedDictionary(dictionary_name) while True: ret, frame = cap.read() # スクリーンショットを撮りたい関係で1/3サイズに縮小 frame = cv2.resize(frame, (int(frame.shape[1]/3), int(frame.shape[0]/3))) # ArUcoの処理 corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(frame, dictionary) frame = cv2.aruco.drawDetectedMarkers(frame, corners, ids) # 加工済の画像を表示する cv2.imshow('Edited Frame', frame) # キー入力を1ms待って、k が27(ESC)だったらBreakする k = cv2.waitKey(1) if k == 27: break cap.release() cv2.destroyAllWindows()
ここで、マーカ辞書は6x6の250にした。本来であれば辞書から画像を作成して印刷して壁に貼ったりするけど、
今回はディスプレイに表示するだけにした。
0から順番に並べると以下のようになる。
結果
いい感じに検出できた様子