void cv::triangulatePoints(
InputArray projMatr1, // 左相机投影矩阵 3×4
InputArray projMatr2, // 右相机投影矩阵 3×4
InputArray projPoints1, // 左相机图像点 (2×N)
InputArray projPoints2, // 右相机图像点 (2×N)
OutputArray points4D // 输出的齐次坐标 (4×N)
);
该函数的输入要求:
-
投影矩阵
projMatr1
和projMatr2
必须是 3×4 的K * [R | T]
矩阵。 -
输入点
projPoints1
和projPoints2
必须是 2×N 形状的 归一化相机坐标 (Normalized Image Coordinates)。 -
输出点
points4D
是 齐次坐标 ,即X, Y, Z, W
,需要手动转换为非齐次坐标: X′=X/W,Y′=Y/W,Z′=Z/WX' = X / W, \quad Y' = Y / W, \quad Z' = Z / WX′=X/W,Y′=Y/W,Z′=Z/W常见错误
错误原因:未正确处理
undistortPoints()
的结果当我们使用
cv::undistortPoints()
进行畸变矫正后,它返回的点坐标是 归一化相机坐标 (单位焦距f=1
的坐标系),而不是像素坐标。因此: -
如果
triangulatePoints()
的投影矩阵 包含了相机内参K
,则输入的点必须是 像素坐标 (未除去K
)。 -
如果输入的是 归一化坐标 (已除
K
),那么投影矩阵就不应该包含K
。
正确方法 1:使用归一化坐标// 1. 去畸变,得到归一化坐标
cv::undistortPoints(projPoints_left, projPoints_left, K_left, dist_left);
cv::undistortPoints(projPoints_right, projPoints_right, K_right, dist_right);// 2. 只使用 [R | T] 作为投影矩阵
cv::Mat P1 = RT_left;
cv::Mat P2 = RT_right;// 3. 三角化
cv::triangulatePoints(P1, P2, projPoints_left, projPoints_right, Final_points3D);正确方法 2:保持像素坐标
如果希望直接在像素坐标下进行三角化,可以在
cv::undistortPoints()
中传入 新的投影矩阵P=K
,让输出点保持在像素坐标系:// 1. 去畸变,但保持像素坐标 cv::undistortPoints(projPoints_left, projPoints_left, K_left, dist_left, cv::noArray(), K_left); cv::undistortPoints(projPoints_right, projPoints_right, K_right, dist_right, cv::noArray(), K_right); // 2. 计算投影矩阵 (带K) cv::Mat P1 = K_left * RT_left; cv::Mat P2 = K_right * RT_right; // 3. 三角化 cv::triangulatePoints(P1, P2, projPoints_left, projPoints_right, Final_points3D);