我在天花板上有一个鱼眼相机,我想在地板上定位一些点。我将参考系统(现实世界)的原点放在相机下方,我想知道每个物体的位置(以厘米为单位)。这张图片显示了这一点:
首先,我完成了相机校准,并获得了 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
其余点也显示错误太大...我使用了更多点,但结果没有改善。我不知道我哪里出错了,谁能帮帮我?
提前致谢。