作为我硕士论文的一部分,我正在探索运动中的结构。在阅读了H&Z book的部分内容、遵循在线教程并阅读了许多 SO 帖子之后,我得到了一些有用的结果,但我也遇到了一些问题。我正在使用 OpenCVSharp 包装器。所有图像均使用同一台相机拍摄。
我现在拥有的:
首先,我计算初始 3d 点坐标。我通过以下步骤做到这一点:
- 计算 Farneback 的密集光流。
- 使用 Cv2.FindFundamentalMat 和 RANSAC 查找基本矩阵
使用相机内在函数获取基本矩阵(此时我使用预先确定的内在函数)并将其分解:
Mat essential = camera_matrix.T() * fundamentalMatrix * camera_matrix; SVD decomp = new SVD(essential, OpenCvSharp.SVDFlag.ModifyA); Mat diag = new Mat(3, 3, MatType.CV_64FC1, new double[] { 1.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D }); Mat Er = decomp.U * diag * decomp.Vt; SVD svd = new SVD(Er, OpenCvSharp.SVDFlag.ModifyA); Mat W = new Mat(3, 3, MatType.CV_64FC1, new double[] { 0.0D, -1.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); Mat Winv = new Mat(3, 3, MatType.CV_64FC1, new double[] { 0.0D, 1.0D, 0.0D, -1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); Mat R1 = svd.U * W * svd.Vt; Mat T1 = svd.U.Col[2]; Mat R2 = svd.U * Winv * svd.Vt; Mat T2 = -svd.U.Col[2]; Mat[] Ps = new Mat[4]; for (int i = 0; i < 4; i++) Ps[i] = new Mat(3, 4, MatType.CV_64FC1); Cv2.HConcat(R1, T1, Ps[0]); Cv2.HConcat(R1, T2, Ps[1]); Cv2.HConcat(R2, T1, Ps[2]); Cv2.HConcat(R2, T2, Ps[3]);
然后,我通过对点进行三角测量,然后将它们乘以投影矩阵(我尝试了 Cv2.TriangulatePoints 和 H&Z 版本,结果相似)并检查正 Z 值(从同质值):
P * point3D
- 在这一点上,我应该有或多或少正确的 3D 点。3D 可视化看起来非常正确。
然后我通过再次使用密集光流和已知的先前投影矩阵计算每个新帧的 SolvePNP,我计算下一个 3D 点并将它们添加到模型中。同样,3D 可视化看起来或多或少是正确的(此时没有捆绑调整)。
由于我需要为每个新帧使用 SolvePNP,因此我首先通过使用基本矩阵为前 2 个图像计算的那个来检查它。从理论上讲,投影矩阵应该与使用初始算法计算的矩阵相同或几乎相同 - 我使用第二张图像中的初始 3D 点和相应的 2D 点。但不一样。
这是通过分解基本矩阵计算得出的:
0,955678480016302 -0,0278536127242155 0,293091827064387 -0,148461857222772
-0,0710609269521247 0,944258717203142 0,321443338158658 -0,166586733489084
0,285707870900394 0,328023857736121 -0,900428432059693 0,974786098164824
这是我从 SolvePnPRansac 得到的:
0,998124823499476 -0,0269266503551759 -0,0549708305812315 -0,0483615883381834
0,0522887223187244 0,8419572918112 0,537004476968512 -2,0699592377647
0,0318233598542908 -0,538871853288516 0,841786433426546 28,7686946357429
它们都看起来像正确的投影矩阵,但它们是不同的。
对于那些阅读整篇文章的耐心的人,我有 3 个问题:
1. Why are these matrices different? I know the reconstruction is up to scale, but since I have an arbitrary scale assigned in the first place the SolvePNP should keep that scale.
2. I noticed one strange thing - the translation in the first matrix seems to be exactly the same no matter what images I use.
3. Is the overal algorithm correct, or am I doing something wrong? Do I miss some important step?
如果需要更多代码,请告诉我,我将编辑问题。
谢谢你!