最近在搞鱼眼相机,这玩意儿不太好弄,因为资料都特别少,而且各个开源代码好像对鱼眼相机的定义都不太一样,也即模型不统一,现在做出了一点阶段性的成果,来总结一下
对于畸变参数,有描述径向的畸变参数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_(3, 3) << 541.1788, 0.0, 644.1565, 0, 539.5916, 502.7171, 0, 0, 1);
cv::Mat distortion_coefficientsa=(cv::Mat_(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<
对以上代码的一些坑,一定要包含头文件
#include
#include
#include
否则出不来cv::fisheye,如果包含了头文件还是出不来,记得装一个opencv3
效果如下图所示
可以看到,恢复效果非常的好,就是尺寸有那么些不一样,不过是正常的
下面放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中的模型