我有三个点对应的视图,我想在第二个和第三个视图计算相机的姿势。因此,我生成包含不同视图中的点的随机数据集(无噪声),其具有相对于第一视图在第二和第三视图处的相机的已知旋转和平移。我首先在第一个视图中生成随机2D点,然后我分配随机(正)深度以获得相应的3D点,最后使用随机生成的旋转和平移将这些3D点投影到第二个和第三个视图中。
首先,我计算三焦张量(参见Hartley& Zisserman,Multiple View Geometry,第15章)。然后,我按照此answer中描述的方法获取第二个和第三个视图的轮转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
(使用matlab表示法):
for ground truth:
[ 1.0768
13.1338
1.6933]
for my algorithm:
[ 1.0768
13.1338
1.6933]
我的第一个问题是: 可能是翻译载体符号不一致的原因是什么?(特别是考虑到结果是正确的事实)。
我的第二个问题是: 上述相关答案第4步中给出的这些公式来自何处?我有Hartley& Co.的书“Multiple View Geometry”。 Zisserman,但在那里找不到所描述的算法。
以下是我在上述链接中使用算法的第4步实现的代码片段(使用特征库,我不想使用OpenCV)来找到正确的旋转解R
和翻译向量t
来自基本矩阵E
,给出3视图同质2D点对应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;
}