如何正确使用cv :: triangulatePoints()

And*_*uri 31 c++ opencv triangulation

我试图用OpenCV对一些点进行三角测量,我发现了这个cv::triangulatePoints()功能.问题是几乎没有文档或示例.

我有一些疑问.

  1. 它使用什么方法? 我对三角测量进行了一些小的研究,有几种方法(线性,线性LS,本征,迭代LS,迭代本征......)但我找不到它在OpenCV中使用的方法.

  2. 我该怎么用?似乎作为输入它需要投影矩阵和3xN齐次2D点.我将它们定义为std::vector<cv::Point3d> pnts,但作为输出它需要4xN数组,显然我不能创建一个std::vector<cv::Point4d>因为它不存在,所以我应该如何定义输出向量?

对于我尝试的第二个问题:cv::Mat pnts3D(4,N,CV_64F);并且cv::Mat pnts3d;,似乎都不起作用(它抛出异常).

And*_*uri 48

1.- 使用的方法是最小二乘法.有比这更复杂的算法.它仍然是最常见的一种,因为在某些情况下其他方法可能会失败(例如,如果点在平面上或在无限上,则其他方法会失败).

该方法可以发现多视图几何在计算机视觉理查德·哈特利和安德鲁·齐塞尔曼(P312)

2.- 用法:

cv::Mat pnts3D(1,N,CV_64FC4);
cv::Mat cam0pnts(1,N,CV_64FC2);
cv::Mat cam1pnts(1,N,CV_64FC2);
Run Code Online (Sandbox Code Playgroud)

用图像中的点填充2个chanel点矩阵.

cam0并且cam1Mat3x4相机矩阵(内在和外在参数).您可以通过乘以A*RT来构造它们,其中A是内在参数矩阵,RT是旋转平移3x4姿势矩阵.

cv::triangulatePoints(cam0,cam1,cam0pnts,cam1pnts,pnts3D);
Run Code Online (Sandbox Code Playgroud)

注意:定义时pnts3DNEED为4通道1xN cv::Mat,如果没有则抛出异常,但结果为cv::Mat(4,N,cv_64FC1)矩阵.真的很混乱,但这是我没有例外的唯一方法.


更新:从版本3.0或更早版本开始,这不再是真的,pnts3D也可以是类型Mat(4,N,CV_64FC1)或者可以保持完全为空(通常,它是在函数内部创建的).

  • 谢谢,一个很好的起点.男人,OpenCV的文档很糟糕.我的意思是,它比没有文档更好,但仍然...... (7认同)
  • 非常好的答案.OpenCV文档很糟糕.很好地阐述了这些糟糕的文档. (6认同)
  • 这个回复非常有用,谢谢... opencv文档缺少这样的例子 (5认同)
  • 仍然不明白为什么三角剖分方法尚未在OpenCV中很好地实现。 (2认同)

Bál*_*ván 11

@Ander Biguri回答的一小部分内容.你应该让你的形象加分的非在undistort编的图像,并调用undistortPoints()cam0pntscam1pnts,因为cv::triangulatePoints预计在归一化坐标的二维点(独立于相机)和cam0cam1应只[R | T ^ T] matricies你不需要用A来复制它.

  • 我同意BálintKriván,因为Ander Biruis的解决方案是使用扭曲点.将相机矩阵A相乘只会将这些点传输到相机系统中,而不会处理任何失真.在我看来,这可能适用于小的失真,但绝对应该使用不失真的点. (2认同)

Gin*_*lgo 7

感谢安德·比古里!他的回答对我帮助很大。但我总是更喜欢 std::vector 的替代方案,我编辑了他的解决方案:

std::vector<cv::Point2d> cam0pnts;
std::vector<cv::Point2d> cam1pnts;
// You fill them, both with the same size...

// You can pick any of the following 2 (your choice)
// cv::Mat pnts3D(1,cam0pnts.size(),CV_64FC4);
cv::Mat pnts3D(4,cam0pnts.size(),CV_64F);

cv::triangulatePoints(cam0,cam1,cam0pnts,cam1pnts,pnts3D);
Run Code Online (Sandbox Code Playgroud)

所以你只需要在点中执行 emplace_back 即可。N主要优点:在开始填充之前您不需要知道尺寸。不幸的是,没有 cv::Point4f,所以 pnts3D 必须是 cv::Mat...