我想使用从Matlab 2014b调用的OpenCV(使用OpenCV绑定)从校准图像和三角形网格中提取深度图。我是Matlab的常用用户,但我是OpenCV的新用户。我有以下输入:
im - 场景的未失真RGB图像
或 - 相机位置矢量
R - 描述相机姿势的旋转矩阵
points - 表示场景的nx3三角形网格顶点列表
faces - mx3三角形网格面列表
EFL - 以像素为单位的图像有效焦距
我编写了一个原生的Matlab光线跟踪引擎来从这些输入中提取深度图,但这很慢并且遭受高重投影错误(我想将OpenCV函数的结果与我自己的结果进行比较以确定是否存在这些错误与我的实现有关或只是相机校准不准确)。
如何使用从Matlab调用的OpenCV从这些输入中获取深度图?
非常感谢任何帮助
谢谢
托马斯
答案 0 :(得分:1)
提议的策略
您可以将网格中的顶点投影到2D像素坐标(使用校准的相机模型)。然后,对于每个面,您可以找到由其投影顶点形成的2D三角形中包含的所有像素中心(晶格点)。在重叠的情况下,您可能必须跟踪哪个三角形最近。现在您知道哪个面对应于每个像素。这应该非常快,除非您的网格分辨率比图像高得多。
然后,您可以使用相机模型找到与每个像素对应的3D光线,并将光线与该像素的已知面相交以计算深度(听起来就像您已经完成此部分一样)。这不应该花太长时间,因为你知道这架飞机。
有关相机投影的更多信息
OpenCV使用相机型号a good resource(下图)。
基本上,您可以将3D点M'
投影到像素坐标m'
;这是将顶点投影到像素位置的方法。走向另一个方向,比例是不可恢复的 - 你获得了光线M'/s
而不是点M'
。您正在寻找的深度是s
,它是相机框架中3D点的Z
坐标。如果您的网格是以相机为中心的框架(X右,Y下,Z out),R = Identity
和t = 0
。如果不是,[R|t]
会将其转换为。
扩展每个因素让我们看到矩阵的构成。
您在下面建议的代码使用OpenCV的projectPoints
函数,该函数实现上述等式加上一些失真校准(参见主OpenCV参考)。你必须填充矩阵并将它们相乘。 projectPoints
的替代示例可用on GitHub,我相信this SO question中讨论了相同的示例。
提问者建议的代码
显然,下面的代码完成了这项工作。我可能需要一些时间 鉴于我的C ++知识几乎为零(我 意识到它被注释掉了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;
//}