点対応のある 3 つのビューがあり、2 番目と 3 番目のビューでカメラのポーズを計算したいと考えています。したがって、最初のビューに対する 2 番目と 3 番目のビューでのカメラの既知の回転と平行移動を使用して、さまざまなビューのポイントを含むランダム データセット (ノイズなし) を生成します。まず最初のビューでランダムな 2D ポイントを生成し、次にランダムな (正の) 深度を割り当てて対応する 3D ポイントを取得し、最後にランダムに生成された回転と平行移動を使用して、これらの 3D ポイントを 2 番目と 3 番目のビューに投影します。
最初に、3 焦点テンソルを計算します (Hartley & Zisserman、Multiple View Geometry Chapter 15 を参照)。次に、この回答で説明されているアプローチに従って、 2 番目と 3 番目のビューの回転R_i
と平行移動を取得しt_i
ます。
計算では常に正しい回転が得られますが、残念ながら、並進ベクトルの符号は常に正しいとは限りません。t2
とt3
正しいスケールを持っていますが、ランダムに生成された新しいデータセットを使用すると、グラウンドトゥルースの翻訳に対して符号が反転することがあります (!)。
グラウンド トゥルース:
R2 = [0.9942 -0.0998 0.0393
0.1069 0.9541 -0.2798
-0.0096 0.2823 0.9593]
t2 = [0.4267
0.3747
0.3544]
R3 = [0.9764 -0.0626 0.2069
0.1358 0.9222 -0.3622
-0.1681 0.3817 0.9089]
t3 = [0.3963
0.0285
0.2093]
私のアルゴリズムの出力(翻訳は最大スケールで決定されます):
R2 = [0.994229 -0.0998196 0.0393062
0.106851 0.954105 -0.279761
-0.00957664 0.282346 0.959265]
t2 = [-0.637428
-0.559842
-0.529398]
R3 = [0.976367 -0.0625748 0.206861
0.135829 0.92217 -0.362151
-0.168099 0.38169 0.908876]
t3 = [-0.591991
-0.0426261
-0.312637]
グラウンド トゥルースと と の私の出力を比較するとt2
、t3
それらがスケールアップして同一であることがわかります (この例では、符号によって反転されていますt2./t3
)。アルゴリズムの利回り:
for ground truth:
[ 1.0768
13.1338
1.6933]
for my algorithm:
[ 1.0768
13.1338
1.6933]
私の最初の質問は、翻訳ベクトルの符号の不一致の原因は何でしょうか? (特に、そうでなければ結果が正しいという事実を考えると)。
私の2番目の質問は、上記のリンクされた回答のステップ4で与えられたこれらの式はどこから来たのですか? Hartley & Zisserman による「Multiple View Geometry」という本を持っていますが、記載されているアルゴリズムが見つかりませんでした。
上記のリンクのアルゴリズムのステップ 4 の実装のコード スニペットを次に示します ( Eigenライブラリを使用しR
ます。OpenCV は使用したくありません) 。 -一様な 2D 点対応を表示、、および:t
E
p1
p2
p3
getPoseFromEssentialMat(Matrix3d E)
{
Matrix3d W, U, V;
W << 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0;
// calculate the SVD of the essential matrix
JacobiSVD<MatrixXd> svdE(E, ComputeThinU | ComputeThinV);
// if det(U) < 0 -> U = -U, if det(V) < 0 -> V = -V
U = svdE.matrixU();
if (U.determinant() < 0.0)
{
U *= -1.0;
}
V = svdE.matrixV();
if (V.determinant() < 0.0)
{
V *= -1.0;
}
R = U * W * V.transpose();
t = U.col(2);
findCorrectSolution(R, t, W, U, V);
}
findCorrectSolution(Matrix3d& R, Vector3d& t, Matrix3d W, Matrix3d U, Matrix3d V)
{
MatrixXd P(3, 4); // P = [R | t]
P.block(0, 0, 3, 3) = R;
P.col(3) = t;
Vector3d Rtpt = R.transpose() * t;
Matrix3d M = crossProductMatrix(Rtpt);
Vector3d X_1 = M * K_inv_ * p1; // point in 1. view
Vector3d X_i = M * R.transpose() * K_inv_ * pi; // point in i. view
if (X_1(2) * X_i(2) < 0.0) // depth components
{
R = U * W.transpose() * V.transpose();
Rtpt = R.transpose() * t;
M = crossProductMatrix(Rtpt);
X_1 = M * K_inv_ * p1;
}
if (X_1(2) < 0.0) // depth of 1. 3D point
{
t = -t;
}