OpenCV:鱼眼相机去畸变=图像去畸变+点去畸变

官网:https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html

鱼眼相机去畸变,即图像矫正,分为整幅图像去畸变和点去畸变.

1.去畸变函数

先来看一下鱼眼相机的去畸变函数.
已知鱼眼相机的内参矩阵和畸变系数


image.png

step1.先估计新的相机内参矩阵
这个新的相机内参矩阵是去畸变后的,图像矫正后的.
Estimates new camera matrix for undistortion or rectification.


image.png

image.png

P New camera matrix (3x3) or new projection matrix (3x4)
balance Sets the new focal length in range between the min focal length and the max focal
length. Balance is in range of [0, 1].

step2. initUndistortRectifyMap()
这个函数的作用是初始化畸变矫正矩阵,
将KDRP转换为map1和map2.
之后就可以通过remap函数计算无畸变图像了.


image.png

image.png

这里有个问题,为什么要把KDRP转换为map1,map2之后在使用remap矫正?
https://docs.opencv.org/master/d4/d94/tutorial_camera_calibration.html
这里有个解释.
之所以扩展undistort函数为initUndistortRectifyMap,是为了提高算法运行速度.

image.png

step3.remap()图像矫正函数

// 图像去畸变
cv::Mat cam_im = imread("1.png");
cv::Mat correct_image;
 cv::remap(cam_im, correct_image, map1, map2, cv::INTER_LINEAR);

(4)undistortImage()函数
这个函数是fisheye::initUndistortRectifyMap和remap函数的合并
Knew是畸变图像的相机内参矩阵,默认是单位阵.

image.png

image.png

(5)undistortPoints是点去畸变函数


image.png

程序

//已知相机内参和畸变系数
//step1.估计新矩阵
cv::Mat newCamMat;
// 估计新的相机内参矩阵,无畸变后的
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(
    camera_intrinsic_matrix, distort_coeff_matrix, img_size,
    cv::Matx33d::eye(), newCamMat, 1);
//step2.计算map1,map2
cv::Mat map1, map2;
cv::fisheye::initUndistortRectifyMap(
        camera_intrinsic_matrix, 
        distort_coeff_matrix, 
    cv::Matx33d::eye(), newCamMat, img_size,
    CV_16SC2, map1, map2);

// step3.remap图像去畸变
cv::Mat cam_im = imread("1.png");
cv::Mat correct_image;
cv::remap(cam_im, correct_image, map1, map2, cv::INTER_LINEAR);

//step4. undistortImage图像去畸变
cv::Mat undistort_im;
cv::fisheye::undistortImage(
    cam_im,undistort_im,
    camera_intrinsic_matrix,
    distort_coeff_matrix,
    newCamMat,
    cam_im.size());
//step5.比较一下这两个图像是否一直
cv::Mat substrct_im;
cv::subtract(undistort_im,correct_image,substrct_im);
cv::imwrite("substrct_im.jpg",substrct_im);

//step6.undistortPoints图像点去畸变
std::vector<cv::Point2f> src_pts{ cv::Point2f(500,500)};
std::vector<cv::Point2f> dst_pts;
cv::fisheye::undistortPoints(
    src_pts,dst_pts,
       camera_intrinsic_matrix,
    distort_coeff_matrix,
    cv::noArray(),
    newCamMat);
cout<<"dst_pts= "<<dst_pts[0]<<endl;

相减结果

说明这两个函数结果一致.

image.png

去畸变点的坐标为(725,514)和去畸变图像中一致.

参考:

  1. https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html
  2. https://blog.csdn.net/baidu_38172402/article/details/89597692
  3. https://blog.csdn.net/jonathanzh/article/details/104418758
  4. https://docs.opencv.org/master/d4/d94/tutorial_camera_calibration.html

推荐阅读更多精彩内容