OpenCV calibrateCamera 如何在 undistort 后将角点匹配到提供的 objectPoints
Posted
技术标签:
【中文标题】OpenCV calibrateCamera 如何在 undistort 后将角点匹配到提供的 objectPoints【英文标题】:OpenCV calibrateCamera how to match corner points after undistort to objectPoints provided 【发布时间】:2017-10-09 11:36:17 【问题描述】:我正在尝试不扭曲以下 2500X2000 图片 回到原来的状态 我正在使用以下代码
//ptCircleCenter is a array of 25 circle center points detected in the distorted image
//prepare object_points and image_points
vector<vector<Point3f>> object_points;
vector<vector<Point2f>> image_points;
vector<Point3f> object_point;
vector<Point2f> image_point;
for (int i = 0; i <= 4; ++i)
for (int j = 0; j <= 4; ++j)
//object_point corresponds to circle center coordinates in the original picture before distortion
object_point.push_back(Point3f(250 + i * 500, 200 + j * 400, 0));
for (int i = 0; i <= 24; ++i)
image_point.push_back(Point2f(ptCircleCenter[i].x, ptCircleCenter[i].y));
object_points.push_back(object_point);
image_points.push_back(image_point);
//prepare distCoeffs rvecs tvecs
Mat distCoeffs = Mat::zeros(5, 1, CV_64F);
vector<Mat> rvecs;
vector<Mat> tvecs;
//calculate principal point
Point2f tFImageCenter;
tFImageCenter.x = 0.;
tFImageCenter.y = 0.;
for (int i=0;i<5*5;i++)
tFImageCenter.x = tFImageCenter.x+ ptCircleCenter[i].x;
tFImageCenter.y = tFImageCenter.y+ ptCircleCenter[i].y;
tFImageCenter.x = tFImageCenter.x / 25;
tFImageCenter.y = tFImageCenter.y / 25;
//prepare camera matrix
Mat intrinsic = Mat(3, 3, CV_64FC1);
intrinsic.ptr<float>(0)[0] = 1.0f;
intrinsic.ptr<float>(1)[1] = 1.0f;
intrinsic.ptr<float>(0)[2] = tFImageCenter.x;
intrinsic.ptr<float>(1)[2] = tFImageCenter.y;
//solve calibration
calibrateCamera(object_points, image_points, Size(2500,2000), intrinsic, distCoeffs, rvecs, tvecs);
//apply undistortion
Mat imageUndistorted;
undistort(imgray, imageUndistorted, intrinsic, distCoeffs);
string outputName = "../corrected grid.jpg";
imwrite(outputName, imageUndistorted); // A JPG FILE IS BEING SAVED
结果
输出图像是 ,这会扩大网格并丢失网格周围的信息。
我尝试修改 imageSize 参数
calibrateCamera(object_points, image_points, Size(4000,3200), intrinsic, distCoeffs, rvecs, tvecs);
输出图像变为
问题1
那么有没有办法将 undistort 后的角点坐标与提供给 calibrateCamera 的 objectPoints 精确匹配,如 getPerspectiveTransform,它保持大小 网格?
问题2
我也遇到了不终止程序的异常:
Exception thrown at 0x00007FFCF8A07788 in Demo.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000E870EFB810.
当我尝试将标志 cv::CALIB_USE_INTRINSIC_GUESS 添加到 calibrateCamera 时:
calibrateCamera(object_points, image_points, Size(2500,2000), intrinsic, distCoeffs, rvecs, tvecs, cv::CALIB_USE_INTRINSIC_GUESS);
抛出两个异常,第二个在这一行终止程序
Exception thrown at 0x00007FFCF8A07788 in Demo.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000E870EFB810.
Unhandled exception at 0x00007FFCF8A07788 in Demo.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000E870EFB810.
我正在使用带有 x64 调试模式的 VS2015 和 OpenCv 3.1.0。
有人可以帮我解决这两个问题吗?谢谢。
已添加 好的。我解决了第二个异常。我把intrinsic的定义改成了这个,设置cv::CALIB_USE_INTRINSIC_GUESS时没有抛出异常。
Mat intrinsic = Mat::eye(3, 3, CV_64F);
我不知道为什么。第一个例外仍然存在。
实际上这是我校准过程的前半部分。这个SO question 包含整个过程。而undistort中的比例修改还是让我很担心,因为我需要保留undistort之后的扭曲图片的信息,以便在warpPerspective中进一步使用。
添加了 2 个 getOptimalNewCameraMatrix 解决了比例问题。详细解释贴在上面的So question链接中。
【问题讨论】:
【参考方案1】:您正在执行的转换是完全有效的。如果是单图算法提供转换,你提供了什么结果。
如果您想获得更好的结果,请尝试更改对象点定义,因为当内在矩阵设置为 I
时,对象坐标是您的“理想”图像坐标。
如果您有任何疑问或问题,请发表评论 - 我会扩展我的答案。
【讨论】:
生成的内在矩阵是 95642.7 0 1307.13 ,0 87092.2 999.268, 0 0 1。我应该在将内在矩阵传递给 calibrateCamera 并将标志设置为 cv::CALIB_USE_INTRINSIC_GUESS 之前将其设置为恒等吗?但是我应该如何处理异常?谢谢。以上是关于OpenCV calibrateCamera 如何在 undistort 后将角点匹配到提供的 objectPoints的主要内容,如果未能解决你的问题,请参考以下文章
opencv calibrateCamera 函数产生不好的结果
OpenCV每日函数 相机校准calibrateCamera函数
函数 cv2.calibrateCamera PYTHON 中类型 Point3f 的问题
OpenCV calibrateCamera - 断言失败(nimages > 0 && nimages == (int)imagePoints1.total()