2016-04-12 34 views
2

私はAugmented Realityアプリケーションを作成するために、 "OpenCV for Unity3d"アセットを使用しています(これはJava用の同じOpenCVパッケージですが、Unity3d用にはC#私の修士論文(コンピュータサイエンス)。Unity3Dで3Dオブジェクトを配置するためのOpenCV rotation(Rodrigues)と翻訳ベクトル

これまでのところ、ORB機能検出器を使用してビデオフレームからオブジェクトを検出することができました。また、OpenCVのSolvePnPメソッド(私はカメラキャリブレーションも行っていました)を使用して3D対2Dの関係を見つけることができます。 その方法から、私は翻訳と回転ベクトルを得ています。この問題は、仮想オブジェクトとして3Dオブジェクトを表示し、各フレームでその位置と回転を更新する必要がある拡張段階で発生します。 OpenCVはRodrigues Rotationマトリックスを返しますが、Unity3dはQuaternionローテーションで動作しますので、オブジェクトの位置と回転を間違って更新しています(RodriguesからQuaternionへの変換フォーラムを実装する方法を理解できません)。

rvecとtvec行き方:

Mat rvec = new Mat(); 
    Mat tvec = new Mat(); 
    Mat rotationMatrix = new Mat(); 

    Calib3d.solvePnP (object_world_corners, scene_flat_corners, CalibrationMatrix, DistortionCoefficientsMatrix, rvec, tvec); 
    Calib3d.Rodrigues (rvec, rotationMatrix); 

仮想物体の位置更新:あなたはUnty3dのシステムにOpenCVの者を変換する際に座標ので、私はZ軸のマイナス符号を持つ

Vector3 objPosition = new Vector3(); 
    objPosition.x = (model.transform.position.x + (float)tvec.get (0, 0)[0]); 
    objPosition.y = (model.transform.position.y + (float)tvec.get (1, 0)[0]); 
    objPosition.z = (model.transform.position.z - (float)tvec.get (2, 0)[0]); 
    model.transform.position = objPosition; 

をZ軸を反転する必要があります(自分でシステム座標をチェックしました)。

Unity3dの座標系(緑は赤がXであるとブルーがZで、Yです):

enter image description here

のOpenCVの座標系:また

enter image description here

私は同じことをしました私は仮想オブジェクトの回転を更新しました。

p.s私は同様の質問を見つけましたが、解決策を明確に投稿していない人がいました。

ありがとうございます!

答えて

3

cv :: solvePnPの直後に回転3x3行列があります。その行列は回転であるため、と直交するは正規化です。したがって、その行列の列は、左から右の順になります。

  1. 右のベクトル(X軸上)。
  2. アップベクトル(Y軸上)。
  3. フォワードベクトル(Z軸上)。

OpenCVは右手座標系を使用します。光軸に沿って見てカメラに座って、X軸は右に、Y軸は下に、Z軸は前方に進む。

ユニティにベクトルF =(fx、fy、fz)とアップベクトルU =(ux、uy、uz)を渡します。これらはそれぞれ3番目と2番目の列です。正規化する必要はありません。彼らは既に正規化されています。ユニティで

、あなたはこのようなあなたの四元数を構築:

Vector3 f; // from OpenCV 
Vector3 u; // from OpenCV 

// notice that Y coordinates here are inverted to pass from OpenCV right-handed coordinates system to Unity left-handed one 
Quaternion rot = Quaternion.LookRotation(new Vector3(f.x, -f.y, f.z), new Vector3(u.x, -u.y, u.z)); 

そして、それはかなりそれです。お役に立てれば!

POSITION関連するコメントのために編集

注:OpenCVの中にZ軸がなく、正確に、一般的に中央に中央付近に画像を通過し、カメラの光軸上にあります。キャリブレーションパラメータには、CxおよびCyパラメータがあります。これらは、Z軸が画像を通過する中心から中心までの画像空間における2Dオフセットである。 3D背景を2D背景に正確にマッピングするには、この変更を考慮する必要があります。

はユニティに適切な位置を取得するには:

あなたは右のその前方軸を中心とした仮想カメラの前に物理的なカメラから取得した画像を入れ
// STEP 1 : fetch position from OpenCV + basic transformation 
Vector3 pos; // from OpenCV 
pos = new Vector3(pos.x, -pos.y, pos.z); // right-handed coordinates system (OpenCV) to left-handed one (Unity) 

// STEP 2 : set virtual camera's frustrum (Unity) to match physical camera's parameters 
Vector2 fparams; // from OpenCV (calibration parameters Fx and Fy = focal lengths in pixels) 
Vector2 resolution; // image resolution from OpenCV 
float vfov = 2.0f * Mathf.Atan(0.5f * resolution.y/fparams.y) * Mathf.Rad2Deg; // virtual camera (pinhole type) vertical field of view 
Camera cam; // TODO get reference one way or another 
cam.fieldOfView = vfov; 
cam.aspect = resolution.x/resolution.y; // you could set a viewport rect with proper aspect as well... I would prefer the viewport approach 

// STEP 3 : shift position to compensate for physical camera's optical axis not going exactly through image center 
Vector2 cparams; // from OpenCV (calibration parameters Cx and Cy = optical center shifts from image center in pixels) 
Vector3 imageCenter = new Vector3(0.5f, 0.5f, pos.z); // in viewport coordinates 
Vector3 opticalCenter = new Vector3(0.5f + cparams.x/resolution.x, 0.5f + cparams.y/resolution.y, pos.z); // in viewport coordinates 
pos += cam.ViewportToWorldPoint(imageCenter) - cam.ViewportToWorldPoint(opticalCenter); // position is set as if physical camera's optical axis went exactly through image center 

(錐台を合わせてスケーリング)、あなたは適切な3D位置がオーバーマップされてい2Dの背景!

+0

今、すべて意味があります:)私の翻訳ベクトルは間違っていると思います。 3Dオブジェクトはシーン内で間違って動いています!私が間違っているのは何ですか? – user43053534

+2

位置については、方向ベクトルの場合と同じようにY座標を反転します。 Z軸は一般に画像中心を通らないカメラの光軸です。キャリブレーションパラメータには、CxおよびCyパラメータがあります。これらは、カメラの光軸(Z軸)が画像内を通過する画像中心からの画像空間における2Dオフセットである。 3DアプリケーションをARアプリケーション用に2Dの背景にマッピングすることは本当に重要です! – RCYR

+0

これを正しく動作させるためには、どのような変更を行う必要がありますか?カメラのキャリブレーションの後、私はカメラの内在的なパラメータを得ました。 virutalオブジェクトを正しく配置するために、それらをどのように使用しなければなりませんか? – user43053534

関連する問題