我有两个摄像头,它们被刚性地并排固定在一起,朝向平行方向。
当我对应点的两个向量执行triangulatePoints
时,我得到了3D空间中的点集。所有3D空间中的点都具有负Z坐标。
所以,要找出问题的根源...
我的假设是OpenCV使用右手坐标系。
我假设每个相机的初始方向都指向正Z轴方向。
因此,通过使用像我在开头介绍的那样的投影矩阵,我会假设相机在空间中的位置如下:
这个假设与我观察到的当我得到三角化点的负Z坐标相矛盾。我能想到的唯一解释是OpenCV实际上使用左手坐标系。因此,根据我在开头所述的投影矩阵,摄像机在空间中的位置如下:
这表明在这种情况下,我的左侧相机不在左侧。这就是为什么我得到负点深度的原因。
此外,如果我尝试将triangulatePoints
与solvePnP
结合使用,就会遇到问题。
我使用triangulatePoints
的输出作为solvePnP
的输入。我期望获得靠近三维坐标系原点的相机坐标。我期望计算出的相机位置与最初使用的投影矩阵相匹配。但是这并没有发生。我得到了一些完全荒谬的结果,距离基线长度超过10倍的预期值。
示例
这个示例更完整地表示了上述问题。
这里是生成这些点的代码。
继续前进,设置相机A和相机D...
Mat cameraMatrix = (Mat_<double>(3, 3) <<
716.731, 0, 660.749,
0, 716.731, 360.754,
0, 0, 1);
Mat distCoeffs = (Mat_<double>(5, 1) << 0, 0, 0, 0, 0);
Mat rotation_a = Mat::eye(3, 3, CV_64F); // no rotation
Mat translation_a = (Mat_<double>(3, 1) << 0, 0, 0); // no translation
Mat rt_a;
hconcat(rotation_a, translation_a, rt_a);
Mat projectionMatrix_a = cameraMatrix * rt_a;
Mat rotation_d = (Mat_<double>(3, 1) << 0, CV_PI / 6.0, 0); // 30° rotation about Y axis
Rodrigues(rotation_d, rotation_d); // convert to 3x3 matrix
Mat translation_d = (Mat_<double>(3, 1) << 100, 0, 0);
Mat rt_d;
hconcat(rotation_d, translation_d, rt_d);
Mat projectionMatrix_d = cameraMatrix * rt_d;
当被投影A和D观察时,points3D
的像素坐标是什么?
Mat points2D_a = projectionMatrix_a * points3D;
Mat points2D_d = projectionMatrix_d * points3D;
我把它们放进向量中:
vector<Point2f> points2Dvector_a, points2Dvector_d;
接着,我再次生成3D点。
Mat points3DHomogeneous;
triangulatePoints(projectionMatrix_a, projectionMatrix_d, points2Dvector_a, points2Dvector_d, points3DHomogeneous);
Mat triangulatedPoints3D;
transpose(points3DHomogeneous, triangulatedPoints3D);
convertPointsFromHomogeneous(triangulatedPoints3D, triangulatedPoints3D);
现在,
triangulatedPoints3D
的初始状态如下:
它们与points3D
完全相同。
然后是最后一步。
Mat rvec, tvec;
solvePnP(triangulatedPoints3D, points2Dvector_d, cameraMatrix, distCoeffs, rvec, tvec);
最终的rvec
和tvec
:
projectionMatrix_d
所使用的变换,即 (100, 0, 0) 的平移和围绕 Y 轴旋转 30°。如果在创建投影矩阵时使用了反向变换,就像这样:
Mat rotation_d = (Mat_<double>(3, 1) << 0, CV_PI / 6.0, 0); // 30° rotation about Y axis
Rodrigues(-rotation_d, rotation_d); // NEGATIVE ROTATION
Mat translation_d = (Mat_<double>(3, 1) << 100, 0, 0);
Mat rt_d;
hconcat(rotation_d, -translation_d, rt_d); // NEGATIVE TRANSLATION
Mat projectionMatrix_d = cameraMatrix * rt_d;
然后我得到 rvec
和 tvec
:
这样就更有意义了。但是我改变了起始转换,使得旋转为负数 CV_PI / 6.0
-> -CV_PI / 6.0
,得到的 rvec
和 tvec
分别为:
我想找到一个解释,为什么会发生这种情况。为什么我从 solvePnP
得到如此奇怪的结果。
triangulatePoints
和solvePnP
。我不确定你的问题是什么,但根据你问题的描述,我建议你先调查一下你的输入数据。为了确切地找出问题所在,需要更多的细节信息(例如相机矩阵、实际代码、输入数据样本等)。 - BConic