![]() |
OpenCV 5.0.0
Open Source Computer Vision
|
前のチュートリアル: ArUcoとChArUcoによるキャリブレーション
次のチュートリアル: バーコード認識
これは、arucoモジュールを使いたい人にとって役立つであろう質問をまとめたものである。
この場合、必要なのは単独のArUcoマーカーだけである。識別したい各物体に、異なるidを持つ1つまたは複数のマーカーを配置すればよい。
arucoモジュールはオリジナルのArUcoライブラリに基づいている。検出処理の詳細な説明は次の文献にある。
S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014. "Automatic generation and detection of highly reliable fiducial markers under occlusion". Pattern Recogn. 47, 6 (June 2014), 2280-2292. DOI=10.1016/j.patcog.2014.01.005
マーカーが正しく検出されない要因は多数考えられる。おそらく cv::aruco::DetectorParameters オブジェクトのいくつかのパラメータを調整する必要がある。まず最初にできるのは、cv::aruco::ArucoDetector::detectMarkers() 関数によってマーカーが棄却候補 (rejected candidates) として返されていないか確認することである。その結果に応じて、さまざまなパラメータを変更してみるとよい。
ArUcoボードを使っている場合は、cv::aruco::ArucoDetector::refineDetectedMarkers() 関数を試すこともできる。大きなマーカー (400x400ピクセル以上) を使っている場合は、cv::aruco::DetectorParameters::adaptiveThreshWinSizeMax の値を大きくしてみるとよい。また、マーカー周囲の ArUcoマーカー周りの狭い境界 (マーカー周長の5%以下。cv::aruco::DetectorParameters::minMarkerDistanceRate で調整) も避けること。
マーカーのボードを使うと、単一のマーカーではなく一群のマーカーからカメラ姿勢を求めることができる。これにより、姿勢を求めるには1つのマーカーがあればよいため、ボードの部分的なオクルージョン (隠れ) にも対応できる。
さらに、ほとんどの場合、姿勢推定により多くのコーナーを使用するため、単一マーカーを使う場合よりも精度が高くなる。
主な欠点は、ボードが単一マーカーほど汎用的でない点である。
ChArUcoボードはチェスボードとArUcoボードを組み合わせたものである。これにより、ChArUcoボードが提供するコーナーは、ArUcoボード (や単一マーカー) が提供するものよりも精度が高い。
主な欠点は、ChArUcoボードがArUcoボードほど汎用的でない点である。例えば、ChArUcoボードは特定のマーカーレイアウトを持つ平面ボードであるのに対し、ArUcoボードは3次元であっても任意のレイアウトを持てる。さらに、ChArUcoボード内のマーカーは通常より小さく、検出が難しい。
いいえ。ChArUcoボードの主な目的は、姿勢推定やカメラキャリブレーションのために高精度なコーナーを提供することである。
いいえ。ArUcoボード内のマーカーコーナーは、その3次元座標系内のどこにでも配置できる。
はい。ChArUcoボード内のすべてのマーカーは同一平面上にある必要があり、そのレイアウトはチェスボードの形状によって固定される。
cv::aruco::Board オブジェクトと cv::aruco::GridBoard オブジェクトの違いは何か?cv::aruco::GridBoard クラスは、cv::aruco::Board クラスを継承する特定種類のボードである。cv::aruco::GridBoard オブジェクトは、マーカーが同一平面上にグリッド状に配置されたボードである。
Diamondマーカーは3x3マスのChArUcoボードに非常によく似ている。ただし、ChArUcoボードとは異なり、diamondの検出はマーカーの相対位置に基づく。これは、diamond内の任意の (またはすべての) マーカーに概念的な意味を持たせたい場合に有用である。例えば、マーカーの1つを使ってdiamondのスケールを表す用途が挙げられる。
はい。単一マーカーの検出はarucoモジュールにおける基本的なツールである。これは cv::aruco::DetectorParameters::detectMarkers() 関数を使って行われる。その他の機能は、この関数から得られる検出済みマーカーのリストを受け取る。
はい。arucoモジュールは、ArUcoボードとChArUcoボードの両方を使ってカメラをキャリブレーションする機能を提供する。
精度が高いため、ChArUcoボードを使ったキャリブレーションを強く推奨する。
一般には、定義済み辞書の1つを使う方が簡単である。ただし、(マーカー数やビット数の点で) より大きな辞書が必要な場合は、独自の辞書を生成すべきである。識別ステップでより良い誤り訂正を実現するためにマーカー間距離を最大化したい場合も、辞書生成は有用である。
辞書の生成はアプリケーションの開始時に一度だけ行うべきであり、数秒かかる。検出ループの反復ごとに辞書を生成しているなら、それは誤った使い方である。
さらに、辞書を cv::aruco::Dictionary::writeDictionary() でファイルに保存し、実行のたびに cv::aruco::Dictionary::readDictionary() で読み込むことを推奨する。そうすれば辞書を生成する必要がなくなる。
使える。事前定義辞書の一つが cv::aruco::DICT_ARUCO_ORIGINAL であり、これはオリジナルArUcoライブラリのマーカーを同じ識別子で検出する。
直接は使えない。ArUcoファイルの情報をarucoモジュールのBoard形式に合わせて変換する必要がある。
おそらく可能だが、元のライブラリの辞書をarucoモジュールの形式に移植する必要がある。
事前定義辞書のいずれかを使っているなら必要ない。そうでない場合は、ファイルに保存することを推奨する。
cv::aruco::GridBoard または cv::aruco::CharucoBoard を使っている場合は、cv::aruco::GridBoard::GridBoard() コンストラクタや cv::aruco::CharucoBoard コンストラクタに渡したボードの計測値を保存するだけでよい。ボードのマーカーIDを手動で変更した場合や、異なる種類のボードを使う場合は、ボードオブジェクトをファイルに保存すべきである。
cv::aruco::Dictionary には cv::aruco::Dictionary::writeDictionary() と cv::aruco::Dictionary::readDictionary() を使える。ボードクラスのデータメンバはpublicであり、容易に保存できる。
そのためには、OpenGLのような外部のレンダリングエンジンライブラリを使う必要がある。arucoモジュールが提供するのは、拡張現実効果の生成に必要なカメラ姿勢、すなわち回転ベクトルと並進ベクトルを取得する機能のみである。ただし、回転ベクトルと並進ベクトルをOpenCV形式から、使用する3Dレンダリングライブラリが受け付ける形式へ変換する必要がある。オリジナルのArUcoライブラリには、OpenGLとOgre3Dでそれを行う方法の例が含まれている。
オリジナルのArUcoライブラリを引用できる:
S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014. "Automatic generation and detection of highly reliable fiducial markers under occlusion". Pattern Recogn. 47, 6 (June 2014), 2280-2292. DOI=10.1016/j.patcog.2014.01.005
4つの同一平面上の点のみを使った姿勢推定には曖昧さがあることに注意することが重要である。一般に、カメラがマーカーに近ければ曖昧さは解決できる。しかし、マーカーが小さくなるとコーナー推定の誤差が大きくなり、曖昧さが問題となる。使用するマーカーのサイズを大きくしてみるとよい。また、衝突を避けるために非対称な (aruco_dict_utils.cpp) マーカーを試すこともできる。複数のマーカー (ArUco/ChArUco/Diamonds ボード) を使い、cv::SOLVEPNP_IPPE_SQUARE オプション付きの solvePnP() で姿勢推定を行うこと。詳しくは この issue を参照。