C++ OpenCV三角点惯用手

C++ OpenCV三角点惯用手,c++,opencv,triangulation,C++,Opencv,Triangulation,我有两个摄像头,紧紧地并排安装在一起,朝着平行的方向看 左摄像机的投影矩阵 右侧摄像机的投影矩阵 当我在对应点的两个向量上执行三角形点时,我得到了三维空间中的点集合。三维空间中的所有点都具有负Z坐标 所以,为了弄清真相 我的假设是OpenCV使用右手坐标系 惯用手提醒: 我假设每个相机的初始方向都指向正Z轴方向 Mat points2D_a = projectionMatrix_a * points3D; Mat points2D_d = projectionMatrix_d * point

我有两个摄像头,紧紧地并排安装在一起,朝着平行的方向看

左摄像机的投影矩阵

右侧摄像机的投影矩阵

当我在对应点的两个向量上执行
三角形点
时,我得到了三维空间中的点集合。三维空间中的所有点都具有负Z坐标

所以,为了弄清真相

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

惯用手提醒:

我假设每个相机的初始方向都指向正Z轴方向

Mat points2D_a = projectionMatrix_a * points3D;
Mat points2D_d = projectionMatrix_d * points3D;
因此,通过使用像我在开始时介绍的投影矩阵,我假设摄像机在空间中的位置如下:

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;

这个假设与我观察到的情况相冲突,当我得到约束点的负Z相关时。我能想到的唯一解释是OpenCV实际上使用左手坐标系。因此,根据我在开头提到的投影矩阵,这就是摄像机在空间中的定位方式:

这表明在这种情况下,我的左摄像头不在左侧。这就是为什么我得到点的负深度

此外,如果我尝试将
三角点
解算pnp
结合起来,我会遇到问题

我使用
triangulatePoints
的输出作为
solvePnP
的输入。我希望得到3D坐标系原点附近的摄像机坐标。我希望计算出的相机位置与开始时使用的投影矩阵相匹配。但这并没有发生。我得到了一些完全疯狂的结果,比基线长度少了10倍多的期望值

例子 这个例子比上面所说的更完整地描述了这个问题

点3d

是生成这些点的代码

打开,设置摄像头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;
我把它们放在向量中:

vector<Point2f> points2Dvector_a, points2Dvector_d;
现在,
三角点3d
开始如下:

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;

它们与
点3d
相同

然后是最后一步

Mat rvec, tvec;
solvePnP(triangulatedPoints3D, points2Dvector_d, cameraMatrix, distCoeffs, rvec, tvec);
产生的
rvec
tvec

我曾希望得到与创建
projectionMatrix\u 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;

Mat-rotation\u d=(Mat\u3,1)OpenCV坐标系是右手坐标系,答案给出了一个关于OpenCV相机系统的说明性示例。我猜混淆是关于
rvec
tvec
,后者没有给出相机的平移,但它指向世界原点。第一个答案基于一个示例进行解释。你可以得到actu通过简单的矩阵乘法,从
solvePnP
的输出中得到一个投影矩阵,细节在第一个答案中。

我可以确认OpenCV使用右手坐标系,我也定期使用
triangulatePoints
solvePnP
。我不确定你的问题是什么,但基于在描述您的问题时,我将从调查您的输入数据开始。需要更多详细信息来准确了解发生了什么(例如,摄像机矩阵、实际代码、输入数据样本等)。谢谢您的回答。我扩展了问题。我可以确认,生成投影矩阵时使用的旋转和平移值不应该反映摄影机的移动,而是反映点的移动。因此,如果摄影机向左移动100个单位,这与点向装备移动100个单位相同但是右边的移动应该用于计算投影矩阵。我有同样的问题…任何人都可以帮助??