web-dev-qa-db-ja.com

基本マトリックスから平行移動と回転を抽出します

計算された基本行列から平行移動と回転のベクトルを取得しようとしています。私はOpenCVを使用していますが、一般的なアプローチはウィキペディアからのものです。私のコードは次のようなものです:

//Compute Essential Matrix
Mat A = cameraMatrix(); //Computed using chessboard
Mat F = fundamentalMatrix(); //Computed using matching keypoints
Mat E = A.t() * F * A;

//Perfrom SVD on E
SVD decomp = SVD(E);

//U
Mat U = decomp.u;

//S
Mat S(3, 3, CV_64F, Scalar(0));
S.at<double>(0, 0) = decomp.w.at<double>(0, 0);
S.at<double>(1, 1) = decomp.w.at<double>(0, 1);
S.at<double>(2, 2) = decomp.w.at<double>(0, 2);

//V
Mat V = decomp.vt; //Needs to be decomp.vt.t(); (transpose once more)

//W
Mat W(3, 3, CV_64F, Scalar(0));
W.at<double>(0, 1) = -1;
W.at<double>(1, 0) = 1;
W.at<double>(2, 2) = 1;

cout << "computed rotation: " << endl;
cout << U * W.t() * V.t() << endl;
cout << "real rotation:" << endl;
Mat rot;
Rodrigues(images[1].rvec - images[0].rvec, rot); //Difference between known rotations
cout << rot << endl;

最後に、推定された回転を、すべての画像にあるチェス盤を使用して計算した回転と比較しようとします(チェス盤なしで外部パラメーターを取得する予定です)。たとえば、私はこれを取得します:

computed rotation:
[0.8543027125286542, -0.382437675069228, 0.352006107978011;
  0.3969758209413922, 0.9172325022900715, 0.03308676972148356;
  0.3355250705298953, -0.1114717965690797, -0.9354127247453767]

real rotation:
[0.9998572365450219, 0.01122579241510944, 0.01262886032882241;
  -0.0114034800333517, 0.9998357441946927, 0.01408706050863871;
  -0.01246864754818991, -0.01422906234781374, 0.9998210172891051]

明らかに問題があるようですが、それが何であるか理解できません。

編集:これは私が転置されていないvtで得た結果です(明らかに別のシーンから):

computed rotation: 
[0.8720599858028177, -0.1867080200550876, 0.4523842353671251;
 0.141182538980452, 0.9810442195058469, 0.1327393312518831;
-0.4685924368239661, -0.05188790438313154, 0.8818893204535954]
real rotation
[0.8670861432556456, -0.427294988334106, 0.2560871201732064;
 0.4024551137989086, 0.9038194629873437, 0.1453969040329854;
-0.2935838918455123, -0.02300806966752995, 0.9556563855167906]

これが私の計算されたカメラ行列です、エラーはかなり低かった(約0.17 ...)。

[1699.001342509651, 0, 834.2587265398068;
  0, 1696.645251354618, 607.1292618175946;
  0, 0, 1]

キューブを再投影しようとしたときに得られる結果は次のとおりです...カメラ0、キューブは軸に沿って配置され、回転と平行移動は(0、0、0)です。 画像http://imageshack.us/a/img802/5292/bildschirmfoto20130110u.png

もう1つは、最初の画像のポイントのエピラインです。 画像http://imageshack.us/a/img546/189/bildschirmfoto20130110uy.png

16
Teris

このリンクを見てください:

http://isit.u-clermont1.fr/~ab/Classes/DIKU-3DCV2/Handouts/Lecture16.pdf

2ページを参照してください。Rには2つの可能性があります。1つ目はU[〜#〜] w [〜#〜]VTで、2つ目はU[〜#〜] wt [〜#〜]VT。あなたは2番目を使用しました。最初に試してください。

10
user1993497

8点アルゴリズムは、基本行列を計算する最も簡単な方法ですが、注意を払えば、うまく実行できます。良好な結果を得るには、解く方程式を作成する前に、入力データを適切に注意深く正規化することが重要です。多くのアルゴリズムがそれを行うことができます。ピクセルのポイント座標をカメラ座標に変更する必要があります。これは次の行で行います。

Mat E = A.t() * F * A;

ただし、この仮定は正確ではありません。カメラキャリブレーションマトリックスKがわかっている場合は、ポイントxに逆数を適用して、正規化された座標で表されたポイントを取得できます。

X_{norm}= K.inv()*X_{pix}ここで、X_{pix}(2)、zは1に等しい。

8PAの場合、ポイントの単純な変換が改善され、結果の安定性が向上します。推奨される正規化は、参照点の重心が座標の原点にあり、原点からの点のRMS距離が\sqrt{2}に等しくなるように、各画像の平行移動とスケーリングです。非正規化の前に特異点条件を適用することをお勧めします。

参照:次の場合に確認してください: まだ興味があります

0
MichalSzczep