多摄像机标定和去畸变
Table of Contents
进行摄像机标定的目的:求出相机的内、外参数,以及畸变参数。
标定相机后通常是想做两件事:一个是由于每个镜头的畸变程度各不相同,通过相机标定可以校正这种镜头畸变矫正畸变,生成矫正后的图像;另一个是根据获得的图像重构三维场景。
摄像机标定过程,简单的可以简单的描述为通过标定板,如下图,可以得到n个对应的世界坐标三维点Xi和对应的图像坐标二维点xi,这些三维点到二维点的转换都可以通过上面提到的相机内参K,相机外参R和t,以及畸变参数D,经过一系列的矩阵变换得到。
1、kalibr多摄像机标定
kalibr提供两种标定方法,标定板标定和IMU联合标定。IMU联合标定又分了两种,都需要移动摄像机测其加速度和角速度,这里只讨论第一种方法。
kalibr支持小孔摄像机模型 pinhole camera model 代号(pinhole)和全景(鱼眼)摄像机模型 omnidirectional camera model代号 (omni),畸变模型支持三种:
(1) radial-tangential模型代号 (radtan) 畸变参数 (distortion_coeffs: [k1 k2 r1 r2])
(2)equidistant模型代号 (equi)畸变参数(distortion_coeffs: [k1 k2 k3 k4])
(3) fov模型代号 (fov)畸变参数(distortion_coeffs: [w])
1.1 系统安装,环境配置:实测Ubuntu 16.04
github地址https://github.com/ethz-asl/kalibr/wiki/installation
按此教程安装原作者只tested on Ubuntu 14.04 with ROS indigo,在Ubuntu 16.04上测试各种坑:
(1)首先ROS版本不对,Wily (Ubuntu 15.10), Xenial (Ubuntu 16.04) and Jessie (Debian 8)需要用Kinetic版,indigo only for Ubuntu 14.04,解决方法 apt-cache search ros-kinetic 再install
(2)实际上还是第一个问题,在step1中:sudo apt-get install python-setuptools python-rosinstall ipython libeigen3-dev libboost-all-dev doxygen libopencv-dev ros-indigo-vision-opencv ros-indigo-image-transport-plugins ros-indigo-cmake-modules python-software-properties software-properties-common libpoco-dev python-matplotlib python-scipy python-git python-pip ipython libtbb-dev libblas-dev liblapack-dev python-catkin-tools libv4l-dev
其中的indigo换成kinetic,然后第一步搞定。这里ROS是一个机器人操作系统,你没看错,操作系统...具体在本节不详述,先看看详细教程。
(3)每次编译完记得source ~/kalibr_workspace/devel/setup.bash不然can not find kalibr...这不是很大的问题,按照教程编译即可顺利完成。
1.2 多摄像机标定
github地址https://github.com/ethz-asl/kalibr/wiki/multiple-camera-calibration
按此教程测试成功,然而:在使用google上测试集解压时kalibr_bagextractor命令报错
(1)需要将所有import cv去掉改成import cv2,如有import cv2可以不加,可以在kalibr_workspace中grep一下。
(2)/kalibr_workspace/src/Kalibr/aslam_offline_calibration/kalibr/python下kalibr_bagextractor.py中CV_IMWRITE_PNG_COMPRESSION这玩意现在OpenCV中改名了改成IMWRITE_PNG_COMPRESSION,错误解决。
标定结果会有几个配置文件和十几张图,包含需要的内参、外参矩阵,畸变矩阵和采集的角点数据等图表,四相机标定第一张如下:
配置文件各项含义:camera_model:相机模型 distortion_coeffs:畸变矩阵 distortion_model:畸变模型 intrinsics:相机内参矩阵
resolution:输出图像长宽 T_cn_cnm1:相机相对cam0的变换矩阵
样例输出:cam0:
cam_overlaps: [1, 3]
camera_model: pinhole
distortion_coeffs: [-0.0031732362017921597, 0.02653769087310933, -0.03646367945634393,
0.01904340710637716]
distortion_model: equidistant
intrinsics: [461.6668123091529, 460.2863010116818, 356.7581291153528, 230.66746533905612]
resolution: [752, 480]
rostopic: /cam0/image_raw
cam1:
T_cn_cnm1:
- [0.9999980949215028, 0.0012278637514936633, -0.0015174003987799415, -0.11016646555368138]
- [-0.0012266412128679274, 0.9999989225766607, 0.0008063478469194138, -0.0003287356017999524]
- [0.0015183888491896661, -0.0008044850048979049, 0.9999985236484987, -4.578129891464306e-05]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [0, 3]
camera_model: pinhole
distortion_coeffs: [-0.0025811639275481264, 0.022339610762027486, -0.034682018961608684,
0.02150751942731516]
distortion_model: equidistant
intrinsics: [462.5967934237879, 461.34432488344453, 377.6059400211138, 225.96899993566748]
resolution: [752, 480]
rostopic: /cam1/image_raw
cam2:
T_cn_cnm1:
- [-0.5040154774986171, -0.04156359669838476, -0.8626939584066463, -0.04588940199554018]
- [-0.07621073036493432, 0.9970855429235707, -0.0035134982631184926, 0.015105481742387357]
- [0.8603257075195868, 0.06397567914681077, -0.5057141380845706, -0.08234109302475862]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [3]
camera_model: omni
distortion_coeffs: [-0.05373073570641462, 0.1343211417522062, 0.0027962580948237203,
-0.003344532565573822]
distortion_model: radtan
intrinsics: [1.892360109609722, 1205.348263755371, 1209.4771950048394, 373.53109998823794,
239.5654160765348]
resolution: [752, 480]
rostopic: /cam2/image_raw
cam3:
T_cn_cnm1:
- [0.4920203720089843, -0.04234128475839692, 0.869553430867332, 0.059917006159028514]
- [-0.0634685509903097, 0.994414190583533, 0.08433362675283367, 0.0023533419393624642]
- [-0.8682670652301226, -0.0966831586735981, 0.48658469999123966, -0.03541318005875174]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [0, 1, 2]
camera_model: omni
distortion_coeffs: [0.002632387378474235, -0.11994551929048765, 0.0022899997101987887,
-0.0025077150557263088]
distortion_model: radtan
intrinsics: [1.9426332690972294, 1234.7842291797426, 1233.0633157996383, 369.0600525635168,
258.7175859449949]
resolution: [752, 480]
rostopic: /cam3/image_raw
2、OpenCV多摄像机标定
OpenCV 2016开始增加了双目标定,误差比较大,而且需要先单摄像机标定后再用stereoCalibrate函数双目标定。
3、Matlab多摄像机标定
Matlab用的人比较多,工具箱自带功能,效果适中。
4、利用标定矩阵去畸变
利用得到的相机内参和畸变矩阵,输入原图像可以得到对应相机去畸变的图像,OpenCV有三个相关函数,参数略有不同。
(1) fisheye::undistortImage(image, dst,intrinsic_matrix,distortion_coeffs,new_intrinsic_mat);
(2)cvUndistort2(src, dst,intrinsic_matrix,distortion_coeffs); (3)initUndistortRectifyMap()+remap()
其中initUndistortRectifyMap和cvUndistort2原理相同,主要是先存了下仿射变换在内存,再remap下,适合同相机的大量图像去畸变处理,fisheye::undistortImage主要适用鱼眼相机模型。
去畸变前后图像栗子如下: