ステレオカメラを使用して特定のオブジェクトまでの距離を計算する方法はありますか? 視差または角度を使用して距離を取得するための方程式または何かはありますか?
3 に答える
注:ここで説明されていることはすべて、カメラのキャリブレーションとステレオビジョンに関する章のLearningOpenCVブックに記載されています。以下の手順をよりよく理解するには、これらの章を読む必要があります。
すべてのカメラの内因性と外因性を自分で測定する必要がない1つのアプローチは、openCVのキャリブレーション機能を使用することです。カメラの内因性(レンズの歪み/スキューなど)はcv :: calibrateCameraで計算でき、外因性(左右のカメラの関係)はcv::stereoCalibrateで計算できます。これらの関数は、ピクセル座標でいくつかのポイントを取り、それらを実際のオブジェクト座標にマッピングしようとします。CVには、そのようなポイントを取得し、白黒のチェス盤を印刷し、cv :: findChessboardCorners / cv::cornerSubPix関数を使用してそれらを抽出するための優れた方法があります。チェス盤の約10〜15の画像ペアで十分です。
キャリブレーション関数によって計算された行列はディスクに保存できるため、アプリケーションを起動するたびにこのプロセスを繰り返す必要はありません。ここでは、後でcv :: remapを使用して画像に適用できる修正マップ(cv :: stereoRectify / cv :: initUnConstraintRectifyMap)を作成できるいくつかのきちんとしたマトリックスを取得します。また、視差から深さまでのマトリックスであるQと呼ばれるきちんとしたマトリックスも得られます。
画像を修正する理由は、画像のペアのプロセスが完了すると(キャリブレーションが正しいと仮定して)、一方の画像のすべてのピクセル/オブジェクトがもう一方の画像の同じ行に表示されるためです。
画像で探している機能の種類に応じて、ここから進むことができるいくつかの方法があります。1つの方法は、ステレオブロックマッチングやセミグローバルブロックマッチングなどのCVステレオ対応関数を使用することです。これにより、Qマトリックス(cv :: reprojectImageTo3D)を使用して3Dポイントに変換できる画像全体の視差マップが得られます。
これの欠点は、画像に多くのテクスチャ情報がない限り、CVは密な視差マップを作成するのがあまり得意ではないことです(特定のピクセルの正しい視差を見つけることができなかった場所にギャップが生じます) 、したがって、別のアプローチは、自分で一致させたいポイントを見つけることです。左の画像でx=40、y = 110、右の画像でx = 22にフィーチャ/オブジェクトが見つかったとします(画像は修正されているため、同じy値を持つ必要があります)。視差はd=40-22=18として計算されます。
この場合(40,110,18)のcv :: Point3f(x、y、d)を作成します。同じ方法で他の興味深いポイントを見つけてから、すべてのポイントをcv :: PerspectiveTransformに送信します(変換行列としてQ行列を使用します。基本的に、この関数はcv :: reprojectImageTo3Dですが、スパース視差マップの場合)。出力は次のポイントになります。左のカメラを中央にしたXYZ座標系。
私はまだそれに取り組んでいるので、まだソースコード全体を投稿することはできません. しかし、概念的な解決策を提供します。
入力として次のデータが必要です (両方のカメラ用)。
- カメラ位置
- カメラの注視点 (カメラが見ているポイント)
- カメラの解像度 (水平および垂直)
- カメラの視野角 (水平および垂直)
カメラを一枚の紙の上に置き、2本の線を引き、これらの線の間の角度を測定することにより、最後の1つを自分で測定できます.
カメラはどのような方法でも整列する必要はありません。両方のカメラでオブジェクトを見ることができればよいだけです。
次に、各カメラからオブジェクトへのベクトルを計算します。各カメラからのオブジェクトの (X,Y) ピクセル座標があり、ベクトル (X,Y,Z) を計算する必要があります。オブジェクトがカメラの真ん中に見える単純なケースでは、解決策は単純に (camera.PointOfInterest - camera.Position) になることに注意してください。
両方のベクトルがターゲットを指すようになると、これらのベクトルによって定義される線が理想的な世界で 1 点で交差するはずです。現実の世界では、測定誤差が小さく、カメラの解像度が限られているため、そうではありません。したがって、以下のリンクを使用して、2 つの線の間の距離ベクトルを計算します。
そのリンクでは: P0 は最初のカム位置、Q0 は 2 番目のカム位置、u と v はカメラ位置から始まり、ターゲットを指すベクトルです。
あなたは実際の距離には興味がありません。彼らは計算したいのです。ベクトル Wc が必要です。オブジェクトが Wc の中央にあると仮定できます。3D 空間でオブジェクトの位置を取得したら、任意の距離も取得できます。
ソースコード全体をすぐに投稿します。
人間の顔を検出するためのソース コードがあり、深度だけでなく、左カメラ (または右カメラ、思い出せませんでした) が原点である現実世界の座標も返します。これは、「OpenCV の学習」のソース コードを基に作成されており、いくつかの Web サイトを参照して動作させます。結果は一般的に非常に正確です。