欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

利用opencv的鱼眼相机去畸变程序,C++&python

程序员文章站 2022-04-17 18:12:56
...

最近在搞鱼眼相机,这玩意儿不太好弄,因为资料都特别少,而且各个开源代码好像对鱼眼相机的定义都不太一样,也即模型不统一,现在做出了一点阶段性的成果,来总结一下

对于畸变参数,有描述径向的畸变参数k1,k2,k3,k4,也有描述切向的畸变参数p1,p2,这个都是在网上资料比较全的,对于鱼眼相机,据我理解的应该是两种描述方法。

一种就是opencv的通用描述方法,也就是k1,k2,p1,p2,k3,对于畸变情况比较大的相机,如鱼眼,启用k3,正常情况下k3=0
另一种就是cv::fisheye描述方法,畸变参数只有四个,k1,k2,k3,k4,这个就是opencv专门为鱼眼镜头创建的模型,也对应着kalibr中的pinhole-equidistant模型,这两个模型参数是可以通用的,亲测准确。

现在上去畸变的opencv代码


        //图像去畸变部分///////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////
    cv::Size img_sizea;
//    const char *imagename = "/home/taolihao/CLionProjects/undistort_tlh/left-0055.jpg";
//    cv::Mat src = cv::imread(imagename);
//    if(src.empty()) return -1;
    img_sizea.width=1280;
    img_sizea.height=1024;


    cv::Mat distortiona = I.clone();



    cv::Mat camera_matrixa = (cv::Mat_<double>(3, 3) << 541.1788, 0.0, 644.1565, 0, 539.5916, 502.7171, 0, 0, 1);
    cv::Mat distortion_coefficientsa=(cv::Mat_<double >(1,4)<<-0.07071596,-0.0031326,-0.00692476,0.00191935);


    cv::fisheye::undistortImage(I, distortiona, camera_matrixa, distortion_coefficientsa,camera_matrixa,img_sizea);

//    cout<<1<<endl;
//    imshow("img", src);
//    imshow("undistort", distortion);
//    imwrite("undistort.jpg", distortion);

    I=distortiona;


    //////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////////

对以上代码的一些坑,一定要包含头文件
#include <opencv2/calib3d.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/calib3d/calib3d.hpp>
否则出不来cv::fisheye,如果包含了头文件还是出不来,记得装一个opencv3

效果如下图所示

利用opencv的鱼眼相机去畸变程序,C++&python

利用opencv的鱼眼相机去畸变程序,C++&python

可以看到,恢复效果非常的好,就是尺寸有那么些不一样,不过是正常的

下面放python的版本

import cv2
import yaml
from matplotlib.pyplot import imshow
import numpy as np



def undistort():
    skip_lines = 0
    with open('./pinhole-equi-512/camchain-imucam-imucalib.yaml') as infile:
        for i in range(skip_lines):
            _ = infile.readline()
        data = yaml.load(infile)
        
        
    # You should replace these 3 lines with the output in calibration step
    DIM=(1280, 1024)
    #K=np.array(YYY)
    #D=np.array(ZZZ)


    [fu, fv, pu, pv] = data['cam0']['intrinsics']
    #https://medium.com/@kennethjiang/calibrate-fisheye-lens-using-opencv-333b05afa0b0
    K = np.asarray([[fu, 0, pu], [0, fv, pv], [0, 0, 1]]) # K(3,3)
    D = np.asarray(data['cam0']['distortion_coeffs'])#D(4,1)
    
    
    img = cv2.imread("left-0055.jpg")
    h,w = img.shape[:2]
   # map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
    # undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    cv2.fisheye.undistortImage(img,undistorted_img,K,D,K,DIM)    

    cv2.imwrite("out.png", undistorted_img)
    #imshow(undistorted_img, cmap='gray')
    #cv2.imshow("undistorted", undistorted_img)
    #cv2.waitKey(0)
    #cv2.destroyAllWindows()
    
if __name__ == '__main__':
    undistort()    

也是调用同样的一个函数完成去畸变操作,这个版本需要在一个yaml文件里度内参,这个内参可以在代码里直接定义的,很方便,如果需要yaml,可以在我的github里找到

重申
cv::fisheye::undistortimage用的是k1,k2,k3,k4四个参数
cv::undistortimage用的是k1,k2,p1,p2,k3五个参数

kalibr中的pinhole-radtan模型就是cv::undistortimage中的模型