建议的策略
您可以将网格中的顶点投影到 2D 像素坐标中(使用校准的相机模型)。然后对于每个面,您可以找到由其投影顶点形成的 2D 三角形中包含的所有像素中心(晶格点)。在重叠的情况下,您可能必须跟踪哪个三角形最近。现在您知道哪个面对应于每个像素。这应该非常快,除非您的网格比您的图像分辨率高得多。
然后您可以使用相机模型找到与每个像素对应的 3D 射线,并将射线与该像素的已知面相交以计算深度(听起来您已经完成了这部分)。既然您知道飞机,这也不应该花太长时间。
有关相机投影的更多信息
OpenCV 有 a good resource 使用相机模型(下)。
基本上,您可以将3D点M'投影到像素坐标m';这就是您将顶点投影到像素位置的方式。往另一个方向发展,规模是不可恢复的——你得到的是射线M'/s,而不是点M'。您正在寻找的深度是s,它是相机帧中3D 点的Z 坐标。如果您的网格位于以相机为中心的框架中(X 向右,Y 向下,Z 向外),R = Identity 和 t = 0。如果不是,[R|t] 将其转换为。
扩展每个因素可以让我们看到矩阵的构成。
您在下面建议的代码使用 OpenCV 的 projectPoints 函数,该函数实现了上述等式以及一些失真校准(请参阅主要 OpenCV 参考)。您必须填充矩阵并将它们相乘。 projectPoints 的另一个示例是可用的on GitHub,我相信在this SO question 中讨论了这个相同的示例。
提问者建议的代码
显然,以下代码可以完成这项工作。我可能需要一些时间
鉴于我的 C++ 知识几乎为零(我
意识到它被注释掉了顺便说一句):
//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;
//}