针孔相机和鱼眼相机的去畸变模型是不一样的。
针孔相机的畸变参数有12个,k1~k6是径向畸变参数,p1 p2是切向畸变,s1s4;而鱼眼相机是等距模型,畸变参数只有4个k1k4。
针孔相机
畸变分为径向畸变和切向畸变。
把相机平面坐标系下的点表示为极坐标(r,θ),则径向畸变表示径r变化δr,而切向变换表示角度θ变化δθ。
径向畸变是透镜改变了光线传播,使得光不再直线传播导致的;切向变换是由于透镜安装与成像平面不平行导致的。(SLAM 14讲)
此图是OpenCV官方文档示例https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html,很清晰。
桶形畸变和枕形畸变
假设只有k1,如果k1大于0,则x’’ = x’(1+k1r2),x’‘>x’,去畸变后的图像会变大,为帧形畸变;反之为桶形畸变。
针孔相机去畸变函数
cv2.undistort(image, K, distCoeffs)
distCoeffs格式为
也就是说,如果只传入4个参数,则是k1,k2,p1,p2,后面的参数都是0.
鱼眼相机
官方文档公式推导https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html
鱼眼相机去畸变函数
distCoeffs为k1,k2,k3,k4
image_undis = cv2.fisheye.undistortImage(image, K, distCoeffs, None,
np.copy(K))
附
- 图片去畸变
def undistort_images(image_dir,
output_dir,
K,
distCoeffs,
is_equidistant: bool = False):
for img in tqdm(sorted(os.listdir(image_dir))):
image = cv2.imread(f'{image_dir}/{img}')
if is_equidistant:
image_undis = cv2.fisheye.undistortImage(image, K, distCoeffs, None,
np.copy(K))
else:
image_undis = cv2.undistort(image, K, distCoeffs)
cv2.imwrite(f'{output_dir}/{img}', image_undis)
- 参考链接
针对OpenCV官方文档的翻译:https://blog.csdn.net/Thomson617/article/details/103987952
https://github.com/nerfstudio-project/nerfstudio/issues/868