c++ - subdiv2d - triangulatepoints函数



OpenCV triangulatePoints用手 (1)

OpenCV坐标系是右撇子, here的答案给出了一个关于OpenCV摄像系统的说明性例子。 我猜混淆是关于rvectvec ,后者不给相机的翻译,但它指向世界起源。 here的第一个答案基于一个例子here解释它。 您可以通过简单的矩阵乘法从solvePnP的输出中获取实际投影矩阵,详细信息在第一个答案中。

我有两个严格并排连接的摄像机。

摄像头的投影矩阵

适用于相机的投影矩阵

当我对相应点的两个向量执行triangulatePoints时,我得到了3D空间中的点集合。 3D空间中的所有点都具有负Z坐标

所以,要深究这个......

我的假设是OpenCV使用右手坐标系。

用户提醒:

我假设每个摄像机的初始方向指向正Z轴方向

因此,通过使用像我在开头提出的那些投影矩阵,我会假设相机在这样的空间中定位:

这个假设与我在得到的负点Z corrdinates的交叉点时所观察到的相冲突。 我能想到的唯一解释是OpenCV实际上使用左手坐标系。 因此,对于我在开头所述的投影矩阵,这就是摄像机在太空中的定位方式:

这表明我的左相机在这种情况下不在左侧 。 这就是为什么我得分为负的深度。

而且,如果我尝试将triangulatePointssolvePnP结合起来,我会遇到问题。

我使用triangulatePoints的输出作为solvePnP的输入。 我希望相机坐标靠近3D坐标系的原点。 我希望计算出的相机位置与开头使用的投影矩阵相匹配。 但这不会发生。 我得到了一些完全狂野的结果,错过了预期值超过基线长度的10倍。

该示例比上述内容更完整地表示问题。

points3D

Here是生成这些点的代码。

移动,设置摄像机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;

当投影AD观察时, points3D的像素坐标是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);

结果rvectvec

我曾希望得到更类似于在创建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;

然后我得到了rvectvec

这更有意义。 但后来我更改了起始转换,使得旋转为负CV_PI / 6.0 - > -CV_PI / 6.0 ,得到的rvectvec为:

我想找到解释为什么会发生这种情况的原因。 为什么我从solvePnP得到如此奇怪的结果。





triangulation