OpenCV的calibrateCamera后提供给undistort objectPoints

问题描述:

我想undistort以下2500X2000图片 enter image description here 到原来的状态 enter image description here 我用下面的代码OpenCV的calibrateCamera后提供给undistort objectPoints

//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 ,其中enl触发电网并丢失电网周围的信息。

我试图修改IMAGESIZE参数

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

和输出图像变得 enter image description here

问题1

那么,有没有办法角点坐标后完全匹配对提供给calibrateCamera的objectPoint提供不偏不倚,如getPerspectiveTransform,它保持网格的大小 ?

问题2

而且我现在遇到的异常不终止程序:

Exception thrown at 0x00007FFCF8A07788 in Demo.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000E870EFB810. 

当我tryied到CALIB_USE_INTRINSIC_GUESS添加标志CV ::到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调试模式。

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

加入 好的。我解决了第二个例外。我将固有的的定义更改为此,并且在设置cv :: CALIB_USE_INTRINSIC_GUESS时不会引发异常。

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

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

实际上这是我校准过程的前半部分。这SO question 包含完整的过程。并且undistort中的刻度修改仍然让我想起,因为我需要保留undistort之后的扭曲图片的信息,以供warp预览中的进一步使用。

新增2 规模问题的解决,是getOptimalNewCameraMatrix。详细的解释发布到上述所以问题链接。

您正在执行的转换是完全有效的。在单幅图像算法提供转换的情况下,您提供了哪些结果。

如果您希望获得更好的结果,请尝试更改对象点定义,因为当内部矩阵设置为I时,对象坐标是您的“理想”图像坐标。

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

+0

产生的固有矩阵是{95642.7 0 1307.13,087092.2 999.268,0 0 1}。在将其传递给calibrateCamera并将标志设置为cv :: CALIB_USE_INTRINSIC_GUESS之前,我应该将内部矩阵设置为标识吗?但我应该如何处理例外?谢谢。 – ricecakebear