视觉标定(一) 单目视觉标定
一、相机模型
常见的单目相机主要有两种模型:即pinhole(针孔相机)与fisheye(鱼眼相机)模型,之前我已经介绍过视觉坐标系转换原理,不管单目相机模型是什么,其内参模型是一样的,将之前的结果拿过来,如下图所示:
坐标系
1.1 pinhole模型
pinhole
pinhole相机即小孔成像原理,主要存在两种不同类型的畸变,一种是透镜形状引起的径向畸变,另一种是相机组装过程中透镜与成像平面不能严格平行引起的切向畸变。
径向畸变如下所示,其中是理想坐标,是真实观测到的坐标,且。
切向畸变:
综合上述两种畸变,得到相机的畸变模型
1.2 fisheye模型
fisheye
鱼眼相机大致分为四种模型,分别为:等距投影模型、等立体角投影模型、正交投影模型和体视投影模型。实际上,鱼眼相机不可能按照某一个模型进行设计,为了方便标定,一般综合上述四种模型进行表示,我们将四种模型进行加权,并进行泰勒级数展开,取前五项:
畸变模型为:
一般普通pinhole相机只标定即可,fisheye相机标定。
二、基本原理
2.1 单应性矩阵
单目内参与畸变矫正采用的是张正友标定法,是张正友教授1998年提出的单棋盘格摄像机标定方法。我们将坐标系转换方程改写为:
将世界坐标系固定在棋盘格上,即令,则可以得到:
将记为单应性矩阵,即:
是齐次矩阵,有8个未知量,需要8个方程才能求解,每个点对提供两个方程,因此至少需要4个点对,才能计算单应性矩阵。
2.2 内参的计算
旋转矩阵是酉矩阵,故有以下性质:
将带入可得:
由上式可知,一个单应性矩阵可以提供两个方程,内参矩阵至少包含4个参数,至少需要2个单应性矩阵,因此至少需要两张棋盘格图片进行标定,改变相机与标定板之间的相对位置得到至少3个不同的图片。记,通过cholesky分解,得到相机的内参矩阵。
上面的推导是基于理想情况下求解,实际中存在高斯噪声,使用最大似然估计进行优化。假设我们采集了n副棋盘格图像,每幅图像由m个角点,设第i幅图像上的角点在图像上的投影点为:
通过角点的概率密度函数构造似然函数:
将似然函数最大化,即上式最小,我们选择LM(Levenberg-Marquardt)算法进行非线性优化,迭代求解。
2.3 畸变计算
按照第一节的畸变模型公式进行计算,将其带入到上述优化函数,进行LM迭代优化,即可将内参与畸变一起计算完成。
三、标定操作
视觉标定可以使用matlab、opencv等开源工具进行标定,操作也很简单,读者感兴趣可以查阅相关资料。在此,我介绍一种更优秀的标定工具kalibr,其不仅可以标定单目相机,也可以对双目立体相机,vio系统进行标定,并且有bag解压压缩功能,极力推荐!地址:https://github.com/ethz-asl/kalibr.git。
3.1 标定板
常见的标定板有:aprilgrid、checkerboard、circlegrid,我们选用aprilgrid,如下所示:
aprilgrid
apriltag的yaml文件参数为:
代码语言:javascript复制 target_type: 'aprilgrid' #gridtype
tagCols: 6 #number of apriltags
tagRows: 6 #number of apriltags
tagSize: 0.12 #size of apriltag, edge to edge [m]
tagSpacing: 0.3 #ratio of space between tags to tagSize
#example: tagSize=2m, spacing=0.5m --> tagSpacing=0.25[-]
3.2 标定
我们在标定板前不断晃动相机,录制视频,我这里使用的是双目vio系统,里面有两个cam与一个imu的topic,我们先只使用cam0进行单目标定。
rosbag_info
通过命令行对相机进行标定,--target即标定文件参数,--bag即bag文件,--models即内参畸变模型,--topics即播放bag中对应的topic:
代码语言:javascript复制kalibr_calibrate_cameras --target 2april_6x6.yaml --bag w.bag --models pinhole-equi --topics /cam0/image_raw
kalibr使用的是python与C 混合编程,基于ros环境运行,基本算法原理就是第二小节讲述的张正友标定法,采用LM进行迭代优化,即BA(Bundle Adjustment)优化,BA优化原理我们以后进行介绍,限于篇幅原因,这里不给出代码核心细节了,感兴趣的读者可以从kalibr_calibrate_cameras.python中仔细阅读源码。标定完成后会生成一个pdf总结文档以及对应的内参畸变yaml文件,其中pdf文档首页如下所示:
error
我们可以看到绝大部分对应的角点的重投影误差都在0.5以下,一般平均投影误差低于0.5个像素即可认为标定结果可以接受,否则,要重新进行标定。我们标定结果可以接受,对应的yaml文件结果为:
代码语言:javascript复制cam0:
cam_overlaps: []
camera_model: pinhole
distortion_coeffs: [-0.0012401362900342373, -0.03069966600965989, 0.046607156271033026,
-0.018194192150805963]
distortion_model: equidistant
intrinsics: [290.69996211319705, 290.8786390133949, 311.99329708834927, 208.3866583107687]
resolution: [640, 400]
rostopic: /cam0/image_raw
至此,我们已经获得单目相机内参标定结果,下一期我们来讲述双目立体视觉相机的内外参标定。
SLAM标定系列文章
1. IMU标定(三)确定误差的标定 2. IMU标定(二)随机误差的标定
3. IMU标定
Python高性能系列文章
- Python高性能计算之列表
- Python高性能计算之字典
- Python高性能计算之堆
- Python嵌套函数 闭包
- Python高性能计算之修饰符
6.如何写出高性能的Python之修饰符functools.wraps