python opencv undistortPoints 和 triangulatePoints 给出奇怪的结果

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

我有两个摄像头设置,我使用 opencv 三角测量来获取从两个摄像头看到的物体的 3d 坐标,但我得到了一些奇怪的结果。

以下是我采取的步骤:

  1. 首先,我对两个相机都使用 cv2.calibrateCamera 来获取固有矩阵和畸变系数:
_, left_camera_intrinsic_matrix, left_camera_distortion_coefficients, _, _ = cv2.calibrateCamera(
obj_points_left, img_points_left, left_shape, None, None)

_, right_camera_intrinsic_matrix, right_camera_distortion_coefficients, _, _ = cv2.calibrateCamera(
obj_points_right, img_points_right, right_shape, None, None)
  1. 接下来,我使用 cv2.stereoCalibrate 找到左摄像头相对于右摄像头的旋转和位置
_, _, _, _, _, rot, trans, _, _ = cv2.stereoCalibrate(obj_points, img_points_left,
                                                      img_points_right, left_camera_intrinsic_matrix,
                                                      left_camera_distortion_coefficients,
                                                      right_camera_intrinsic_matrix,
                                                      right_camera_distortion_coefficients,
                                                      left_shape)
left_camera_rotation, _ = cv2.Rodrigues(rot)
left_camera_position = trans
  1. 我用 cv2.stereoRectify 得到校正投影矩阵
right_camera_position = (0, 0, 0)
right_camera_rotation = (0, 0, 0)

right_projection_matrix, _ = cv2.Rodrigues(right_camera_rotation)
right_projection_matrix = np.hstack(
    (right_projection_matrix, np.array(right_camera_position).reshape(-1, 1)))

left_projection_matrix = np.hstack((rot, left_camera_position.reshape(-1, 1)))

_, _, rectified_right_prj_mtx, rectified_left_prj_mtx, _, _, _ = \
    cv2.stereoRectify(right_camera_intrinsic_matrix, right_camera_distortion_coefficients,
                      left_camera_intrinsic_matrix,
                      left_camera_distortion_coefficients, left_shape, rot,
                      left_camera_position)
  1. 最后,对于每一帧视频,我使用 cv2.undistortPoints 和 cv2.triangulatePoints 来获取 3d 坐标
right = cv2.undistortPoints(right_points, right_camera_intrinsic_matrix,
                            right_camera_distortion_coefficients, rectified_right_prj_mtx)
left = cv2.undistortPoints(left_points, left_camera_intrinsic_matrix,
                           left_camera_distortion_coefficients, rectified_left_prj_mtx)

# find 3d points through triangulation
homogeneous_points = \
    cv2.triangulatePoints(right_projection_matrix, left_projection_matrix, right, left)
points_3d = cv2.convertPointsFromHomogeneous(homogeneous_points.T)

这几乎可以正常工作,但有一些问题。

这是一个 GIF 示例,其中我将棋盘 (6x4) 移向右侧相机然后返回。 example GIF

所以我的问题是:

  • 为什么棋盘看起来是弯曲的(我的相机有一些失真,但 cv2.undistortPoints 不应该解决这个问题吗?)?
  • 是什么导致棋盘的表观尺寸发生变化?透视畸变不会造成这么大的变化吧?
  • 我的步骤有什么根本性的缺陷吗?

一些补充说明:

  • 我为 cv2.calibrateCamera 的两个相机使用单独的图像(每个相机在不同的角度和距离下大约 60 张)。对于 cv2.stereoCalibrate,我也使用了大约 60 张图片,尽管我发现只有几张效果一样好
  • 对于这个例子,相机处于 50 度角,但我也以许多其他方式尝试过,并且棋盘的弯曲和明显的尺寸变化总是发生(除非我将棋盘平行于其中一个相机移动,然后尺寸变化非常小,虽然板仍然是弯曲的)
  • 相机是相同的并且捕获相同的分辨率

到目前为止我已经尝试过(这些没有帮助,有些变得更糟):

  • 使用 cv.2stereoRectifyUncalibrated 而不是 cv2.stereoRectify
  • 使用不同的图像进行校准
  • 不失真图像并且不使用 cv2.undistortPoints
python opencv computer-vision triangulation
1个回答
0
投票

已解决
所以我在上面的代码中有很多错误。正如用户 Micka 所说,stereoRectify 有点错误,实际上不需要。

为了以后帮助像我这样的初学者,我将我的工作代码合并到一个文件中并放在 github 上。像这样的一些示例代码可能会为我节省 40 个小时的调试和困惑,所以我真的希望它能帮助将来的人。

github 上的 opencv-triangulation-example

© www.soinside.com 2019 - 2024. All rights reserved.