OpenCV calibrateCamera如何在unistort到objectPoints提供后匹配角点

时间:2017-10-09 11:36:17

标签: c++ opencv camera-calibration

我试图取消以下2500X2000图片的失真 enter image description here 到原来的状态 enter image description here 我使用以下代码

//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

结果

输出图像是 enter image description here ,它会扩大网格并丢失网格周围的信息。

我尝试修改imageSize参数

calibrateCamera(object_points, image_points, Size(4000,3200), intrinsic, distCoeffs, rvecs, tvecs);

输出图像变为 enter image description here

问题1

那么有没有办法将unsistort后角点的坐标与提供给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.

我使用VS2015和OpenCv 3.1.0以及x64调试模式。

有人可以帮我解决这两个问题吗?感谢。

好。我解决了第二个例外。我将 intrinsic 的定义更改为this,并且在设置cv :: CALIB_USE_INTRINSIC_GUESS时没有抛出异常。

Mat intrinsic = Mat::eye(3, 3, CV_64F);

我不知道为什么。第一个例外仍然存在。

实际上这是我校准过程的前半部分。这SO question 包含完整的过程。 undistort 中的缩放修改仍然让我感到困惑,因为我需要在 undistort 之后保留扭曲图片的信息,以便在 warpPerspective 中进一步使用。

已添加2 使用 getOptimalNewCameraMatrix 解决了比例问题。详细解释发布在上面的问题链接。

1 个答案:

答案 0 :(得分:0)

您正在执行的转化完全有效。如果单图像算法提供转换,您提供的结果。

如果您想获得更好的效果,请尝试更改对象点定义,因为当内在矩阵设置为I时,对象坐标是您理想的&#34;图像坐标。

如果您有任何疑问或疑问,请发表评论 - 我会扩大答案。