我有三个点对应的视图,我想计算相机在第二个和第三个视图的姿势。因此,我生成了一个随机数据集(无噪声),其中包含不同视图中的点,其中相机在第二和第三视图相对于第一视图的旋转和平移已知。我首先在第一个视图中生成随机 2D 点,然后分配随机(正)深度以获得相应的 3D 点,最后使用随机生成的旋转和平移将这些 3D 点投影到第二个和第三个视图中。
首先,我计算三焦张量(参见 Hartley & Zisserman,Multiple View Geometry 第 15 章)。然后我按照这个答案中描述的方法来获得第二个和第三个视图的旋转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]
比较基本事实和我的 and 的输出t2
,我们看到它们在尺度上是相同的(在这个例子中,用符号反转),即从基本事实和我的翻译向量(使用 matlab 表示法)t3
按元素划分t2./t3
算法产量:
for ground truth:
[ 1.0768
13.1338
1.6933]
for my algorithm:
[ 1.0768
13.1338
1.6933]
我的第一个问题是:翻译向量符号不一致的原因可能是什么?(特别是考虑到结果是正确的事实)。
我的第二个问题是:上述链接答案第 4 步中给出的这些公式来自哪里?我有 Hartley & Zisserman 的“Multiple View Geometry”一书,但在那里找不到描述的算法。
这是我在上述链接中实现算法第 4 步的代码片段(使用 Eigen 库,我不想使用 OpenCV),用于从基本矩阵中找到旋转R
和平移向量的正确解决方案,给定 3 -view 齐次二维点对应, , 和: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;
}