从基础矩阵中提取平移和旋转信息

17
我正在尝试从计算的基本矩阵中获取平移和旋转向量。我使用OpenCV,通用方法来源于维基百科。我的代码如下:

我正在尝试从计算的基本矩阵中获取平移和旋转向量。我使用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

还有另一张图片,显示了第一张图片中点的极线。 图像 http://imageshack.us/a/img546/189/bildschirmfoto20130110uy.png


2
decomp.vt 是 V 的转置,而不是 V。如果你说 U * W.t() * V,你会得到什么? - yiding
我的相机矩阵可能是错误的吗?这个公式来自维基百科。我已经将我的当前矩阵添加到第一篇帖子中了。 - Teris
我对这个算法的细节不太确定,除了从维基百科上了解到的。你是否使用这些矩阵旋转图像,看看它与原始图像对齐得如何? - yiding
不,我没有。我怎么做呢? - Teris
我尝试的是根据计算出的值在两个图像上重新投影一个立方体。我相信每个顶点的极线应该匹配。但不幸的是它们并不匹配。稍后我会发布我使用的代码。 - Teris
显示剩余2条评论
2个回答

10

3
谢谢。这正是我所需要的。我还可以推荐新书《通过实际计算机视觉项目掌握 OpenCV》的非常简单易懂的资源,网址为https://github.com/MasteringOpenCV/code。 - Teris
1
你能提供一个链接,解释如何确定哪个R是正确的吗? - Antonio Sesto
1
链接现在是:http://igt.ip.uca.fr/~ab/Classes/DIKU-3DCV2/Handouts/Lecture16.pdf - Gabriel Devillers
1
链接又挂了。 - schrödinbug
1
@RoyAmoyal 已修复,感谢您告诉我。 - Gabriel Devillers
显示剩余3条评论

0
8点算法是计算基础矩阵的最简单方法,但如果小心处理,你可以很好地执行它。获得良好结果的关键是在构建解方程之前对输入数据进行适当的归一化处理。许多算法都可以做到这一点。 像素点坐标必须转换为相机坐标,在这一行中完成:
然而,这个假设并不准确。如果已知相机校准矩阵K,则可以应用逆变换将点x转换为以归一化坐标表示的点。
在8PA的情况下,对点进行简单的变换可以改善结果的稳定性。建议的归一化是对每个图像进行平移和缩放,使参考点的质心位于坐标原点,并且点到原点的RMS距离等于√2。请注意,在反归一化之前建议强制执行奇异条件。

参考资料:如果你还感兴趣的话,可以查看这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接