有很多关于从已知内部校准的立体视图中进行3D重建的帖子,其中一些是优秀的。我阅读了很多这样的帖子,并根据所读内容尝试使用以下流程/算法计算自己的3D场景重建。我将列出方法,然后在底部提出具体问题。
0. 校准您的相机:
- 这意味着检索相机标定矩阵K1和K2,分别对应相机1和相机2。这些是3x3的矩阵,封装了每个相机的内部参数:焦距,主点偏移/图像中心。这些参数不会改变,只需要在每个相机上执行一次,除非你进行缩放或更改录制分辨率。
- 请离线进行此操作。不要争论。
- 我正在使用OpenCV的
CalibrateCamera()
和棋盘格例程,但这个功能也包含在Matlab相机标定工具箱中。OpenCV例程似乎很好用。
1. 基础矩阵F:
- 现在你的相机已经设置成立体摄影系统。使用两幅图像/视图之间的点对应关系确定该配置的基础矩阵(3x3)。
- 如何获取对应关系取决于场景本身,您可以自行决定。
- 我正在使用OpenCV的
findFundamentalMat()
来获取F,它提供了多种方法(8点算法、RANSAC、LMEDS)。 - 您可以通过将结果矩阵插入基础矩阵的定义方程
x'Fx = 0
进行测试,其中x'和x是齐次坐标(x, y, 1)
中的原始图像点对应关系(x, y)
,其中三个向量之一被转置以使乘法有意义。每个对应关系越接近零,F遵从其关系就越好。这相当于检查导出的F实际上将一个图像平面映射到另一个图像平面的效果有多好。使用8点算法,我得到了约2px的平均偏差。
2. 本质矩阵E:
- 直接从F和校准矩阵计算本质矩阵。
- E = K2TFK1
3. E的内部约束:
- E应遵守某些限制。特别地,如果通过SVD分解为
USV.t
,则其奇异值应为a,a,0
。S的前两个对角元素应相等,第三个为零。 - 我惊讶地看到这里说,如果测试发现这不是真的,你可以选择从先前的分解中制造一个新的本质矩阵,如下所示:
E_new = U * diag(1,1,0) * V.t
,这当然保证了遵守限制。你实际上已经人为地设置了S=(100,010,000)。
4. 完整的相机投影矩阵:
- 有两个相机投影矩阵P1和P2。它们都是3x4的,遵守
x = PX
的关系。此外,P = K[R|t]
,因此K_inv.P = [R|t]
(其中已经去除了相机标定)。 - 第一个矩阵P1(不包括标定矩阵K)可以设置为
[I|0]
,然后P2(不包括K)为R|t
- 从E的分解中计算出两个相机之间的旋转和平移R、t。有两种计算R的可能方法(
U*W*V.t
和U*W.t*V.t
),以及计算t的两种方法(±U的第三列),这意味着有四种Rt
的组合,只有一种是有效的。 - 计算所有四种组合,并选择几何上对应于重建点在两个相机前方的情况。我通过执行计算并计算结果的P2=[R|t],以及在归一化坐标下三维位置的几个对应关系来确保它们具有正深度(z-coord)来实现这一点。
5. 三维三角测量
- 最后,将恢复的3x4投影矩阵与其各自的标定矩阵相结合:P'1 = K1P1和P'2 = K2P2。
- 然后根据每个2D点对应的三维空间坐标进行三角测量,我使用这里的LinearLS方法。
问题:
- 这种方法是否存在任何遗漏或错误?
- 我的F矩阵显然很准确(与典型坐标值相比,映射中的偏差为0.22%),但是在使用归一化图像对应关系测试E与
x'Ex = 0
时,该映射中的典型误差大于归一化坐标本身的100%。测试E与xEx = 0
有效吗?如果有效,那么错误跳跃来自哪里? - 使用RANSAC进行基础矩阵估计的误差比8点算法要严重得多,在x和x'之间的映射中±50px。这让我非常担心。
- “强制内部约束”对我来说仍然非常奇怪-如何从原始分解的一部分中制造出一个新的本质矩阵是有效的呢?
- 有没有更有效的方法来确定使用哪个R和t组合,而不是计算P并三角化一些归一化坐标?
- 我的最终重新投影误差在720p图像中达到数百像素。我可能正在查看校准,确定P矩阵或三角测量方面的问题吗?