OpenCV ArUco マーカー
このチュートリアルでは、OpenCV の cv2.aruco.detectMarkers()
関数を使用して ArUco マーカーを検出する方法について説明します。
OpenCV を使用した ArUco マーカー検出
ArUco マーカーは、姿勢推定、カメラ キャリブレーション、ロボット ナビゲーション、および拡張現実アプリケーション用のバイナリ イメージです。 コンピューター ビジョン アプリケーションでは、ポーズの推定は非常に重要で困難ですが、ArUco マーカーを使用すると簡単に行うことができます。
ArUco マーカーは、黒の境界線を持つ 2 進数の正方形の画像で、内側の本体はマーカーに応じて変化する白色です。 たとえば、ArUco マーカーを以下に示します。
上記のArUcoマーカーは、ウェブサイト(https://chev.me/arucogen/)を使用して生成されます。 この ウェブサイト(https://chev.me/arucogen/) を使用して ArUco マーカーを生成するには、辞書、マーカー ID、およびマーカー サイズを選択する必要があります。
ArUco maker は、ArUco 辞書、マーカー サイズ、およびマーカー ID で構成されます。 たとえば、4x4_100
ディクショナリは、4x4
マーカー サイズの 100
マーカーで構成され、マーカーが 25 ビットで構成され、各マーカーが一意の ID を持つことを意味します。
ArUco マーカーの定義済みディクショナリを使用する場合、マーカー ID は 0 から始まり、ディクショナリでサポートされているマーカーの最大数で終了します。 検出プロセスは、ArUco メーカーの 4つのコーナーとマーカー ID を返します。
最初のステップでは、アルゴリズムは与えられた画像を分析して正方形の画像を見つけます。 アルゴリズムは、指定された画像に存在するすべての形状のカウンターを取得します。これにより、形状の角に関する情報が得られ、正方形ではない形状は破棄されます。
2 番目のステップでは、アルゴリズムは残りの形状の内部コード化を分析します。 マーカー ビットはしきい値処理を使用して計算され、白と黒のビットが分離されます。
アルゴリズムは、ビットが ArUco 辞書のいずれかに属しているかどうかをチェックします。 ビットが特定の ArUco 辞書に属している場合、マーカーの ID が返されます。
OpenCV の detectMarkers()
関数を使用して、ArUco マーカーを検出できます。 detectMarkers()
関数の最初の引数は、ArUco マーカーを含む入力画像です。
detectMarkers()
関数の 2 番目の引数は、ArUco マーカーを見つけるために検索する辞書です。 3 番目の引数は検出パラメータです。cv2.aruco.DetectorParameters_create()
関数を使用して、ArUco マーカーを検出するためのデフォルト パラメータを作成できます。
detectMarkers()
関数は、マーカー コーナー、マーカー ID、拒否されたマーカーの 3つの出力引数を返します。 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()
関数の最初の引数は、線を描画したい画像です。
2 番目と 3 番目の引数は線の端点で、4 番目の引数は RGB 3 成分形式の線の色です。 5 番目の引数は線の幅です。
cv2.circle()
関数の最初の引数は円を描画したい入力画像、2 番目の引数は円の中心、3 番目の引数は円の半径、4 番目の引数は 円の色であり、5 番目の引数は円を塗りつぶすために使用されます。
cv2.putText()
関数の最初の引数は、テキストを配置したい入力画像です。
2 番目の引数はテキスト、3 番目の引数はテキストを配置するポイント、4 番目の引数はフォント スタイル、5 番目の引数はフォント スケール、6 番目の引数はテキストの色、 7 番目の引数は、テキストの行幅です。 マーカーの作成と検出には、同じ辞書を使用する必要があります。