c++ - 图像点(像素)到真实世界坐标(米)

标签 c++ opencv camera-calibration pose-estimation

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

Reference system - Real world

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

Undistorted image after calibration

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

例如,原点位于 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);

现在我有了相机矩阵、旋转矩阵和平移 vector ,所以通过使用 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))错误:3.69 厘米
  • 点 1 --> (-68.28, -112.82)(应该是 (-80, -132))错误:17.49 厘米
  • 点 2 --> (84.48, 137.61)(应该是 (120, 188))错误:49.62 厘米

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

提前致谢。

最佳答案

solvePNP 的角度来看,您可能两次有效地消除了图像失真。这是由于传入了畸变系数以及已经从未畸变图像中导出的点对应。

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

关于c++ - 图像点(像素)到真实世界坐标(米),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37706914/

相关文章:

c++ - 执行 InFile 数组的程序

c++ - 使用 boost :thread 的可运行类

c++ - 强大的相机校准

opencv - 相机校准在长焦距镜头的大图像上遇到高误差

c++ - 如何将 C/C++ python 模块与 PVTS 项目/VS 2013 解决方案集成

c++ - std::unordered_set迭代器遍历的复杂度

c++ - 使用 OpenCV 和 C++ 执行图像过滤,错误 : "Sizes of input arguments do not match"

java - 最大矩形的 findContour 和霍夫变换的角点检测都不适合我

opencv - OpenCV文档检测FIX

python - Python OpenCV相机校准cv::imshow错误