3

我在天花板上有一个鱼眼相机,我想在地板上定位一些点。我将参考系统(现实世界)的原点放在相机下方,我想知道每个物体的位置(以厘米为单位)。这张图片显示了这一点:

参考系统 - 真实世界

首先,我完成了相机校准,并获得了 RMS 为 1.11 的下一个结果:

校准后未失真的图像

作为校准的结果,我获得了内在参数(相机矩阵),所以我使用 cv::solvePnP 来获得旋转和平移向量。为了应用这个,我在未失真的图像中标记了一些点(以像素为单位),并根据我的参考系统在现实世界中测量了它们。

例如,原点位于 1024x768 图像的中心,因此:

  • 点 0:ImagePoint(512, 384) [像素] --> ObjectPoint(0,0) [厘米]

下一个代码显示了这一点:

std::vector<cv::Point2f> imagePointsPix;
std::vector<cv::Point3f> objectPointsCm;
imagePointsPix.push_back(cv::Point2f(512.,384.));
imagePointsPix.push_back(cv::Point2f(404.,512.));    
imagePointsPix.push_back(cv::Point2f(666.,211.));
imagePointsPix.push_back(cv::Point2f(519.,66.));

objectPointsCm.push_back(cv::Point3f(0., 0., 0.));
objectPointsCm.push_back(cv::Point3f(-80.,-132.,0.));
objectPointsCm.push_back(cv::Point3f(120.,188.,0.));
objectPointsCm.push_back(cv::Point3f(-40.,268.,0.));

cv::Mat rvec(1,3,cv::DataType<double>::type);
cv::Mat tvec(1,3,cv::DataType<double>::type);
cv::Mat rotationMatrix(3,3,cv::DataType<double>::type);

cv::solvePnP(objectPointsCm, imagePointsPix, cameraMatrix, distCoeffs, rvec, tvec, 0, SOLVEPNP_ITERATIVE);
cv::Rodrigues(rvec,rotationMatrix);

现在我有了相机矩阵、旋转矩阵和平移向量,所以通过使用作为参考,如果我有它的像素位置,我可以计算任何点。这是代码:

cv::Mat uvPoint = cv::Mat::ones(3,1,cv::DataType<double>::type); //u,v,1
uvPoint.at<double>(0,0) = 512.; //img point for which we want its real coordinates
uvPoint.at<double>(1,0) = 384.;
cv::Mat tempMat, tempMat2;
double s;
tempMat = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;
tempMat2 = rotationMatrix.inv() * tvec;
s = 0 + tempMat2.at<double>(2,0); //before 0 it was 285, which represents the height Zconst
s /= tempMat.at<double>(2,0);
std::cout << "P = " << rotationMatrix.inv() * (s * cameraMatrix.inv() * uvPoint - tvec) << std::endl;

对于用于获取参数的相同点,我得到了这个结果:

  • 点 0 --> (0.213, 3.391) (应该是 (0,0))错误: 3.69 cm
  • 点 1 --> (-68.28, -112.82) (应该是 (-80, -132))错误: 17.49 cm
  • 点 2 --> (84.48, 137.61) (应该是 (120, 188))错误: 49.62 cm

其余点也显示错误太大...我使用了更多点,但结果没有改善。我不知道我哪里出错了,谁能帮帮我?

提前致谢。

4

2 回答 2

1

从 的角度来看,您似乎可以有效地使图像不失真两次solvePNP。这是由于传递了失真系数以及已经从未失真图像导出的点对应关系。

尝试将实际相机矩阵从校准传递到solvePNP而不是单位矩阵,但仍为失真系数传递 NULL 以避免双重失真。

于 2017-01-30T18:39:18.913 回答
0

最后我发现错误是由失真系数引起的,即我的校准。我将 cameraMatrix 设置为 Identity 矩阵 (eye(3)) 并将 distCoefficients 设置为 NULL,以便 solvePNP 假设我有一个完美的相机。使用这种方法,我得到的错误要低得多。我将不得不进行更好的校准。

于 2016-08-31T09:59:07.797 回答