matlab - 使用 OpenCV 和 Matlab 的校准图像和三角网格的深度图

标签 matlab opencv mesh raytracing camera-calibration

我想使用从 Matlab 2014b 调用的 OpenCV(使用 OpenCV 绑定(bind))从校准图像和三角网格中提取深度图。我是 Matlab 的普通用户,但我是 OpenCV 的新手。我有以下输入:

im - 场景的未失真 RGB 图像

或 - 相机位置向量

R - 描述相机位姿的旋转矩阵

点 - 表示场景的 nx3 三角形网格顶点列表

faces - mx3 三角形网格面列表

EFL - 以像素为单位的图像有效焦距

我已经编写了一个原生的 Matlab 光线追踪引擎来从这些输入中提取深度图,但这非常慢并且存在高重投影错误(我想将 OpenCV 函数的结果与我自己的结果进行比较以确定这些错误是否存在与我的实现有关或只是相机校准不准确)。

如何使用从 Matlab 调用的 OpenCV 从这些输入中获取深度图?

任何帮助将不胜感激

谢谢

托马斯

最佳答案

建议的策略

您可以将网格中的顶点投影到 2D 像素坐标中(使用校准的相机模型)。然后对于每个面,您可以找到包含在由其投影顶点形成的 2D 三角形中的所有像素中心(格点)。在重叠的情况下,您可能必须跟踪哪个三角形最近。现在您知道每个像素对应于哪张脸了。这应该非常快,除非你的网格比你的图像分辨率高得多。

然后您可以使用相机模型找到对应于每个像素的 3D 射线,并将射线与该像素的已知面相交以计算深度(听起来您已经完成了这部分)。既然您已经了解飞机,这也不应该花太长时间。

关于相机投影的更多信息

OpenCV 有 a good resource关于使用相机模型(下图)。 基本上,您可以将 3D 点 M' 投影到像素坐标 m';这就是将顶点投影到像素位置的方式。换个方向,尺度是不可恢复的——你得到的是射线 M'/s 而不是点 M'。您要查找的深度是 s,它是相机框架中 3D 点的 Z 坐标。如果您的网格位于以相机为中心的框架中(X 向右,Y 向下,Z 向外),R = Identityt = 0。如果不是,[R|t] 将其转换为。

Compact

展开每个因子让我们看到矩阵的构成。

Expanded

您在下面建议的代码使用了 OpenCV 的 projectPoints 函数,该函数实现了上述等式以及一些失真校准(参见 OpenCV 主要引用资料)。您必须填充矩阵并将它们相乘。 projectPoints 的替代示例可用 on GitHub ,我相信在 this SO question 中讨论了同一个例子.

Code suggested by asker

Apparently the following code does the job. I may need some time to pick through it given that my C++ knowledge is practically zero (I realise that it is commented out BTW):

       //CString str;
       //cv::Mat CamMatrix(3, 3, CV_64F);
       //cv::Mat distCoeffs(5, 1, CV_64F);
       //m_CamCalib.GetOpenCVInfo(&CamMatrix, &distCoeffs);
       //vector<Point3d> GCP_Points;
       //vector<Point2d> Image_Points;
       //cv::Mat RVecs(3, 3, CV_64F); // rotation matrix
       //cv::Mat TranRVecs(3, 3, CV_64F); // rotation matrix
       //cv::Mat TVecs(3, 1, CV_64F); // translation vector
       //RVecs.at<double>(0, 0) = m_CamPosMtrx.m_pMtrx[0];
       //RVecs.at<double>(1, 0) = m_CamPosMtrx.m_pMtrx[1];
       //RVecs.at<double>(2, 0) = m_CamPosMtrx.m_pMtrx[2];

       //RVecs.at<double>(0, 1) = m_CamPosMtrx.m_pMtrx[4];
       //RVecs.at<double>(1, 1) = m_CamPosMtrx.m_pMtrx[5];
       //RVecs.at<double>(2, 1) = m_CamPosMtrx.m_pMtrx[6];

       //RVecs.at<double>(0, 2) = m_CamPosMtrx.m_pMtrx[8];
       //RVecs.at<double>(1, 2) = m_CamPosMtrx.m_pMtrx[9];
       //RVecs.at<double>(2, 2) = m_CamPosMtrx.m_pMtrx[10];
       //transpose(RVecs, TranRVecs);
       //TVecs.at<double>(0, 0) = 0;
       //TVecs.at<double>(1, 0) = 0;
       //TVecs.at<double>(2, 0) = 0;
       //GCP_Points.push_back(Point3d((x - m_CamPosMtrx.m_pMtrx[12]), (y - m_CamPosMtrx.m_pMtrx[13]), (z - m_CamPosMtrx.m_pMtrx[14])));
       //Image_Points.push_back(Point2d(0, 0));
       //projectPoints(GCP_Points, TranRVecs, TVecs, CamMatrix, distCoeffs, Image_Points);

/bool CCameraCalibration::GetOpenCVInfo(Mat * cameraMatrix, Mat * distCoeffs)
//{
//            int i,j;
//            Mat projMatrix;
//            CMatrix4x4 m1;
//            if(cameraMatrix->rows==0) cameraMatrix->create(3,3, CV_64F);
//            if(distCoeffs->rows==0) distCoeffs->create(5, 1, CV_64F);
//            for(i=0;i<3;i++)
//            for(j=0;j<3;j++){
//                   cameraMatrix->at<double>(i,j)=m_pCameraMatrix[i][j];
//            }
//            for(i=0;i<5;i++)
//                   distCoeffs->at<double>(i,0)=m_pCoefficients[i];
//     return false;
//}

关于matlab - 使用 OpenCV 和 Matlab 的校准图像和三角网格的深度图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33745446/

相关文章:

Python cv2.imshow() 因中止陷阱而崩溃 : 6

ios - 使用 3D 管道查找附近的三角形?

matlab - 在交互式经纪商上计算 IV60 和 IV90

java - 在哪里可以找到 com.mathworks.jmi 包

opencv - 在 Visual Studio 2012 中安装 OpenCV

opengl - 深度图到网格

c++ - 如何使用 GL_TRIANGLES 生成平面?

java - 如何将java输出作为matlab变量传递?

matlab - Matlab 中的决策树

c++ - 如何使用 C++ 在 opencv 中舍入 float