OpenCV 的基本矩阵不好

问题描述 投票:0回答:0

概览

我正在编写一个简单的 Python 程序来计算一对任意位置的立体图像到选定目标的距离。两张图像都是从具有已知内在函数 K 的单个相机拍摄的,尽管相机位置和姿势是任意的,但我始终知道位置之间的基线距离。

我相信我在从 OpenCV 获取良好的基本矩阵时遇到了问题,我无法弄清楚是这种情况还是我只是错误地解释了结果。这是一个示例图像对:Stereo image pair (left camera on left, right camera on right(如果有人可以将图像内联,将不胜感激:P)。

我的图像目前来自 iPhone 12 相机,几乎可以肯定它会自动不失真。无论如何,我仍然校准了相机,但在我的脚本中的任何时候都没有取消任何东西。 (我应该吗?)

方法

我目前计算几何的流程如下:

  1. 进行关键点检测匹配,得到对应图像点的两个列表
  2. 使用OpenCV的5点算法cv2.findEssentialMat()计算基本矩阵
    E
    。我在这里使用 RANSAC 进行异常值过滤。
  3. 使用 OpenCV 的 cv2.recoverPose()E 恢复旋转矩阵 R 和平移单位向量
    t
    。在这里,我还将 t 乘以基线距离以获得真实世界的比例。

问题

由此产生的计算旋转和平移与预期结果不匹配。我将首先断言我的关键点检测和匹配非常好,几乎可以肯定不是我问题的罪魁祸首。左图是正面拍摄的,右图是在向右 7 米处拍摄的,然后向场景倾斜,所以我希望从左相机到右相机的平移为 t = [7, 0, 0]。相反,我从 cv2.recoverPose() 得到

t
= [-6.597, 0.256, 2.324]。我可能错误地解释了这个结果的坐标系吗?这会不会是从右相机到左相机的平移?或者
cv2.recoverPose()
会聚在错误的解决方案上(不太可能)?

可视化图像上的外线也引起了关注: Images with epilines。我读到找到基本矩阵的 8 点算法对噪声很敏感,所以我决定使用

F = Kinv.T @ E @ Kinv
反向求解基本矩阵,其中 Kinv 是内在矩阵 K 的逆。查看生成的相应外延线,在 BOTH 图像中,“其他”相机似乎位于成像相机的左侧。这显然没有道理。此外,更改算法或 RANSAC 参数有时会极大地改变生成的图像: 性能不佳是否是系统噪音造成的?很容易获得非常好的单应性 (Same stereo images with different RANSAC parameterscv2.findHomography()),如下所示: 并且我策划了这对图像以获得最佳性能(通过成像墙)。系统中的少量视差会不会增加噪音?对于单应性,噪声明显被过滤掉了,我正在通过 5 点算法为这些图像传递近 1500 对匹配点。

归根结底,我需要在视角之间获得准确的

R

t,在我看来,首先需要一个更好的 left image warped onto rightE 矩阵才能做到这一点。任何建议将不胜感激,在此先感谢您!

代码 注意:假设pts0pts1适当地填充了良好的对应关系(分别为左和右)。

# matched points in each image pts0 = np.int32(<left image points here>) pts1 = np.int32(<corresponding right image points here>) E, mask = cv2.findEssentialMat(pts0, pts1, K, cv2.RANSAC, prob=.99999, threshold=.1) F = Kinv.T @ E @ Kinv # solve for fundamental matrix # recover pose to verify calculated transform to actual camera placement _, R, t, _ = cv2.recoverPose(E, pts0, pts1, K, mask=mask) t *= scale # convert to real-world scale pts0 = pts0[mask.ravel() == 1] pts1 = pts1[mask.ravel() == 1] """ followed tutorial at <https://docs.opencv.org/4.x/da/de9/tutorial_py_epipolar_geometry.html> for displaying epilines """ llines = cv2.computeCorrespondEpilines(pts1.reshape(-1, 1, 2), 2, F) llines = llines.reshape(-1, 3) out02, _ = drawlines(left_img, right_img, llines, pts0, pts1) rlines = cv2.computeCorrespondEpilines(pts0.reshape(-1, 1, 2), 1, F) rlines = rlines.reshape(-1, 3) out01, _ = drawlines(right_img, left_img, rlines, pts1, pts0) cv2.imshow('epilines', np.hstack((out02, out01))) cv2.waitKey(0) cv2.destroyAllWindows()


python opencv computer-vision 3d-reconstruction projective-geometry
© www.soinside.com 2019 - 2024. All rights reserved.