我在天花板上有一个鱼眼摄像头,我想在地板上找到一些点。我将参考系统(真实世界)的原点放在相机下方,我想知道每个物体的位置,以厘米为单位。此图为本:图像点(像素)到现实世界坐标(米)
首先,我也做了相机校准和我已经获得的下一个结果与1.11的RMS:
Undistorted image after calibration
作为校准的结果我获得了内部参数(相机矩阵),所以我使用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);
现在我有相机矩阵,旋转矩阵和翻译中矢量,所以通过使用作为this参考我能够计算任何点,如果我有它的位置像素。这是代码:
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))ERROR:3.69厘米
- 点1 - >(-68.28,-112.82)(它应该是(-80,-132))ERROR:17.49厘米
- 点2 - - >(84.48,1 37.61)(它应该是(120,188))错误:49.62厘米
点的其余部分也显示错误太大了......我用更多的积分,但结果并不完善。我不知道我错了哪里,有谁能帮助我?
在此先感谢。
有可能校准没有问题,而且你有效地将图像无畸变了两次(请参阅我的答案以获得解释)。 – rob3c