Camera Calibration
Camera Calibration Algorithm
- 前言
首先要了解知道什么是相机的针孔模型,可参考文章小孔相机参数学习笔记。
先介绍相机标定。所谓相机标定,就是通过实验等方法将相机模型中的未知数给解算出来。例如小孔模型我们一般需要节算出内参矩阵 fx,fy,cx,cy 以及畸变参数。
为什么要标定出这些参数呢?
一个是因为每个镜头的畸变程度各不相同,通过相机标定可以校正这种镜头畸变矫正畸变,生成矫正后的图像;另一个是根据获得的图像重构三维场景,例如__ PNP __算法(openCV中solvePNP函数),就是通过相机的内参以及畸变解算出目标在相机下的位置,以及双目 3D 相机也需要相机模型参数进行计算等。
有很多标定方法,比如传统相机标定法、主动视觉相机标定方法、相机自标定法等。现在用的最多的是相机的自标定法,它的基础即张正友标定法。
“张正友标定法” 是张正友博士在 1999 年发表在国际顶级会议 ICCV 上的论文《Flexible Camera Calibration By Viewing a Plane From Unknown Orientations》中,提出的一种利用平面棋盘格进行相机标定的实用方法。该方法既克服了摄影标定法需要的高精度三维标定物的缺点,又解决了之前自标定法鲁棒性差的难题。
标定过程仅需使用一个打印出来的棋盘格,并从不同方向拍摄几组图片即可,任何人都可以自己制作标定图案,不仅实用灵活方便,而且精度很高,鲁棒性好。因此很快被全世界广泛采用。
- 张正友标定法计算流程
首先我们看一下张正友标定法使用 OpenCV 的计算流程:
- 准备标定图片,原理上三张就够,一般在多个角度采集 20 张左右。
- 提取标定板的关键点,并计算出标定板上关键点的实际相对位置,一般将标定板当做 XY 平面,Z 为 0,标定板第一个点为坐标原点。
- 相机标定,通过张正友标定法计算出内参外参以及畸变。
- 对标定结果进行评价,一般通过重投影的误差进行评价。
- 查看标定效果,利用标定结果对棋盘图进行矫正
从上边的过程可以看出,其实只有第三步是真正的解算过程,大致的方法如下:
首先用于标定的棋盘格是三维场景中的一个平面Π,其在成像平面的像是另一个平面𝜋,知道了两个平面的对应点的坐标,就可以求解得到两个平面的单应矩阵𝐻。其中,标定的棋盘格是特制的,其角点的坐标是已知的;图像中的角点,可以通过角点提取算法得到,这样就可以得到棋盘平面Π和图像平面𝜋的单应矩阵𝐻,即:
其中p是像素点坐标,P是标定板上的棋盘格坐标,K 是相机内参,为了不失一般性,可以在相机的内参矩阵上添加一个扭曲参数γ。即:
这里假设H为单应矩阵,通常用于表示两个平面之间的投影变换,即p=HP。这样就可以得到下面的等式:
我们通过对应的点对解得H后(即p=HP),则可以通过上面的等式得到相机的内参数K,以及外参旋转矩阵R和平移向量t。
下面具体推导具体的解法:
设棋盘格所在的平面为世界坐标系中Z=0 的平面,这样棋盘格的任一角点P的世界坐标为 (X,Y,0),根据小孔相机模型(小孔成像中s表示镜头到被成像物体的距离,镜头当作一个点处理;f为相机的焦距,即镜头到感光元件的距离。那么根据相似三角形,即有p/f=P/s,也即sp=fP。这里f焦距即内参,是矩阵K的一部分,就有了下面的式子。):
另外这里需要在列向量(X Y 0)(Z为0)上增加一维“1”,以添加[R t]坐标系转换矩阵中t平移的部分。这里肯定单靠旋转不足以变换坐标系的,需要平移向量t的信息。那么等号左侧列向量(u v)也需要加“1”变成(u v 1),这样左边是一个3X1的列向量,右边是K-3X3乘[R t]-3X4再乘(X Y 0 1)-4X1,即可得到3X1列向量。
再根据单应性原则:
根据上面两式则有:
将旋转矩阵R的各个列向量和平移向量t使用H的列向量表示:
又因为,R是旋转矩阵,则其是正交矩阵,也就是其任意两个列向量的内积为 0,列向量的模为 1,则有:
即:
\(\begin{aligned}&r_{1}^{T}r_{2}=0\&\\&|r_{1}|=|r_2|=1\end{aligned}\)那么对于一幅棋盘标定版的图像(一个单应矩阵)可以获得两个对内参数的约束等式。(H由对应点可得,求K即可。)
我们令:
矩阵B是一个对称矩阵,其未知量只有 6 个,将 6 个未知量写为向量的形式:
则有:
其中:
则约束等式有:
写成矩阵的形式有:
假如有n幅图像,则:
其中,V是一个 2n×6 的矩阵,b是一个 6 维向量,所以
- 当n≥3,可以得到b的唯一解;
- 当n=2,则可以假设扭曲参数γ=0 作为额外的约束条件
- 当n=1,则值能计算两个相机的内参数
对于方程Vb=0 可以使用 SVD 求得其最小二乘解。对V𝑇V进行 SVD 分解,其最小特征值对应的特征向量就是Vb=0 的最小二乘解,从而求得矩阵B。由于这里得到的B的估计值是在相差一个常量因子下得到的,所以有:
所以则有:
\(\begin{cases}c_x=\gamma c_y/\beta-B_{13}\alpha^2/\lambda\\c_y=(B_{12}B_{11}-B_{11}B_{23})/(B_{11}B_{22}-B_{12}^2)\\\alpha=\sqrt{\lambda B_{11}/B_{11}}\\\beta=\sqrt{\lambda B_{11}/B_{11}B_{22}-B_{12}^2)}\\\gamma=-B_{12}\alpha^2/\lambda\\\lambda=B_{33}-[B_{13}^2+c_3(B_{12}B_{13}-B_{11}B_{23})]/B_{11}\end{cases}\)
其中 $fx = α_(1/γ),fy = β_(1/γ) $。
为了进一步增加标定结果的可靠性,可以使用最大似然估计来优化上面估计得到的结果。
假设同一相机从n个不同的角度的得到了n幅标定板的图像,每幅图像上有m个像点。Mi𝑗表示第i幅图像上第j个像点对应的标定板上的三维点,则:
m̂ (K,Ri,ti,Mij) 表示Mij的像点。其中,Ri,ti表示第i幅图像对应相机的旋转矩阵和平移向量,K是相机的内参数。则像点mij的概率密度函数是:
构造似然函数:
为了能够让L取得最大值,需要最小化下面的值
\(\sum\limits_{i=1}^{n}\|\hat{m}(K,R_i,t_i,M_{ij})-m_{ij}\|^2\)
问题变成了一个非线性优化问题,利用上面得到的解作为初始值,迭代得到最优解。这个过程就是在减少重投影误差的过程。
至此,通过张正友标定法,我们获得了相机的内参以及外参,但是畸变没有获得。张正友标定法只关注了影响较大的径向畸变。畸变的解算有点类似内参解算,暂时先不列举。
- 总结
张正友标定法的思路并不是很难,主要是解算的数学原理较复杂,需要有比较打的耐心看下去,我现在也只能看懂,让自己完全推导一遍还是挺难的。张正友标定法更重要的是将标定这项工作简洁化,不在需要精密高额的设备,而只需要通过打印标定板就可以获得比较好的效果。
在实际的标定项目中,还是需要注意很多的事情,以下是我在标定时用的一些小 trick 或者一些注意点:
- 比如某个点识别错了,要通过重投影误差将其剔除,然后重新计算标定结果。
- 增加图片的数目,标定板在图片中的各个角落都要有着各个角度的分布。
- 对于畸变不大的图片,opencv 中圆形标定板的效果要比棋盘格的效果要好,opencv4 棋盘格识别精度有较大提升,但还是建议用圆形。