![]() |
OpenCV 5.0.0
Open Source Computer Vision
|
前のチュートリアル: ChArUcoボードの検出
次のチュートリアル: ArUcoとChArUcoによるキャリブレーション
ChArUcoダイヤモンドマーカー(単にダイヤモンドマーカーとも呼ぶ)は、3x3個の正方形と、白い正方形の中に配置された4個のArUcoマーカーで構成されるチェスボードである。見た目はChArUcoボードに似ているが、概念的には異なるものである。
ChArUcoボードとダイヤモンドマーカーは、いずれもその検出が事前に検出されたArUcoマーカーに基づいている。ChArUcoの場合、使用するマーカーはその識別子を直接参照して選択される。つまり、(ボードに含まれる)マーカーが画像中で見つかれば、自動的にそのボードに属するものとみなされる。さらに、あるマーカーボードが画像中で複数回見つかった場合、システムはどちらをボードに使うべきか判断できないため、曖昧さが生じる。
一方、ダイヤモンドマーカーの検出は識別子に基づかない。代わりに、その検出はマーカー同士の相対位置に基づく。その結果、マーカーの識別子は同一のダイヤモンド内や異なるダイヤモンド間で重複してもよく、曖昧さなく同時に検出できる。ただし、相対位置に基づいてマーカーを見つける処理は複雑であるため、ダイヤモンドマーカーは3x3個の正方形と4個のマーカーというサイズに制限される。
単一のArUcoマーカーと同様に、各ダイヤモンドマーカーは4個のコーナーと1個の識別子で構成される。4個のコーナーはマーカー内の4個のチェスボードコーナーに対応し、識別子は実際には4個の数値の配列であり、これらはダイヤモンド内部の4個のArUcoマーカーの識別子である。
ダイヤモンドマーカーは、マーカーの重複を許可したいシナリオで有用である。例えば、次のような場合である:
detect_diamonds.cppファイルに含まれている。さらに、コーナーはチェスボードのコーナーであるため、正確な姿勢推定に利用できる。
ダイヤモンド機能は<opencv2/objdetect/charuco_detector.hpp>に含まれている
ダイヤモンドマーカーの画像はcv::aruco::CharucoBoard::generateImage()関数を使って簡単に作成できる。例えば次のようにする:
これにより、正方形サイズ200ピクセル、マーカーサイズ120ピクセルのダイヤモンドマーカー画像が作成される。マーカーidは2番目の引数としてcv::Vec4iオブジェクトで与える。ダイヤモンドレイアウトにおけるマーカーidの順序は標準的なChArUcoボードと同じで、すなわち上、左、右、下の順である。
生成される画像は次のようになる:
完全な動作例はsamples/cpp/tutorial_code/objectDetection/内のcreate_diamond.cppに含まれている。
サンプルcreate_diamond.cppは現在、cv::CommandLineParserを介してコマンドラインから入力を受け取る。このファイルの例の引数は次のようになる:
多くの場合と同様に、ダイヤモンドマーカーの検出には事前にArUcoマーカーの検出が必要である。マーカーを検出した後、cv::aruco::CharucoDetector::detectDiamonds()関数を使ってダイヤモンドを検出する:
cv::aruco::CharucoDetector::detectDiamonds()関数は、元画像と、事前に検出されたマーカーのコーナーおよびidを受け取る。markerCornersとmarkerIdsが空の場合、この関数はarucoマーカーとidを検出する。入力画像はChArUcoコーナーのサブピクセル精緻化を行うために必要である。また、正方形サイズとマーカーサイズの比率も受け取る。この比率は、マーカーの相対位置からダイヤモンドを検出することと、ChArUcoコーナーを補間することの両方に必要である。
この関数は検出されたダイヤモンドを2つの引数で返す。1つ目の引数diamondCornersは、検出された各ダイヤモンドの4つのコーナーすべてを含む配列である。その形式はcv::aruco::ArucoDetector::detectMarkers()関数で検出されるコーナーと同様であり、各ダイヤモンドについてコーナーはArUcoマーカーと同じ順序、すなわち左上のコーナーから始まる時計回りの順序で表現される。2つ目の戻り値の引数diamondIdsは、diamondCorners内の返されたダイヤモンドコーナーのすべてのidを含む。各idは実際には4個の整数の配列であり、cv::Vec4iで表現できる。
検出されたダイヤモンドはcv::aruco::drawDetectedDiamonds()関数を使って可視化できる。この関数は単に画像とダイヤモンドのコーナーおよびidを受け取る:
結果はcv::aruco::drawDetectedMarkers()が生成するものと同じだが、ダイヤモンドの4つのidが表示される点が異なる:
完全な動作例はsamples/cpp/tutorial_code/objectDetection/内のdetect_diamonds.cppに含まれている。
サンプルdetect_diamonds.cppは現在、cv::CommandLineParserを介してコマンドラインから入力を受け取る。このファイルの例の引数は次のようになる:
ChArUcoダイヤモンドは4つのコーナーで表現されるため、その姿勢は単一のArUcoマーカーの場合と同じ方法で、すなわち cv::solvePnP() 関数を用いて推定できる。例えば次のとおり:
この関数は各ダイヤモンドマーカーの回転ベクトルと並進ベクトルを取得し、rvecsとtvecsに格納する。ダイヤモンドのコーナーはチェスボードの正方形のコーナーであるため、姿勢推定にはマーカー長ではなく正方形の長さを与える必要があることに注意する。カメラキャリブレーションの引数も必要である。
最後に、drawFrameAxes()を使って軸を描画し、推定された姿勢が正しいか確認できる:
ダイヤモンド姿勢の座標系は、単純なArUcoマーカーの姿勢推定と同様に、マーカーの中心に位置し、Z軸が外向きを指す。
サンプル動画:
ChArUcoダイヤモンドの姿勢はChArUcoボードとしても推定できる:
完全な動作例はsamples/cpp/tutorial_code/objectDetection/内のdetect_diamonds.cppに含まれている。
サンプルdetect_diamonds.cppは現在、cv::CommandLineParserを介してコマンドラインから入力を受け取る。このファイルの例の引数は次のようになる: