相机标定是图像处理的基础,虽然相机使用的是小孔成像模型,但是由于小孔的透光非常有限,所以需要使用透镜聚焦足够多的光线。在使用的过程中,需要知道相机的焦距、成像中心以及倾斜因子(matlab的模型有考虑,实际中这个因子很小,也可以不考虑)。为了增加光照使用了透镜,而使用透镜的代价是会产生畸变,现在市面上买到的相机,都存在着或多或少的畸变。畸变的种类比较多,这里介绍常见的两种:径向畸变、切向畸变。相机标定就是求解相机的内参数以及畸变参数的过程。
畸变种类
(1)径向畸变(参考自《学习opencv》412页)
摄像头的透镜在传感器的边缘产生显著的畸变,如下图所示。对于径向畸变,光学中心的畸变为-,随着向边缘移动,畸变会越来越严重。由于畸变比较小,所以可以用泰勒级数的低阶项来近似。
(2)切向畸变。
另外一种需要考虑的相机畸变是切向畸变,切向畸变的主要原因是透镜本身和图像平面不平行,如下左图所示。切向畸变导致的结果是在成像平面上所成的像为下右图所示。
相机的标定
相机的标定主要有两种:传统的摄像头标定方法和摄像头自标定方法,典型的有:(1)Tsai(传统的标定方法);(2)张正友(介于传统和自标定之间)。张正友标定方法由于简单、效果好而得到广泛使用。这里只介绍张正友标定方法。
其中,
q=⎡⎣⎢uvw⎤⎦⎥,M=⎡⎣⎢fx00sfy0cxcy1⎤⎦⎥,Q=⎡⎣⎢XYZ⎤⎦⎥
q
的坐标系是默认的OpenCV的像素坐标系,
Q
的坐标系是标定板坐标系,Z轴为0,原点在标定板的某个内角点上(标定板上角点的坐标均为[*,*,0]的形式),在Open CV 3.0中使用的是(
[i∗Squres_Size,j∗Square_Size,0]
的形式)。其中
fx
和
fy
表示相机
x
轴和
y
轴的焦距,
s
表示成像平面
x
轴和
y
轴的不正交性(OpenCV模型中把该项置为0,Matlab考虑了该项)。
2、基础公式
对于不同位置的棋盘格到相机的成像,可以使用下面的公式进行表示:
sm~=A[R|t]M~
其中,
[R|t]
表示棋盘格坐标系相对于相机坐标系的位姿。把矩阵
R
和
M~
写开,如下式所示:
m~=⎡⎣⎢uv1⎤⎦⎥,M~=⎡⎣⎢⎢⎢XY01⎤⎦⎥⎥⎥,R=[r1r2r3],M~=⎡⎣⎢⎢⎢XY01⎤⎦⎥⎥⎥
进行化简得到:
s⎡⎣⎢uv1⎤⎦⎥=A[r1r2t]⎡⎣⎢XY1⎤⎦⎥
其中
[uv1]
是已知量,
[XY1]
也是已知量,
A
和
[r1r2t]
是未知量。
其中
H=A[r1r2t]
又叫做单应性矩阵,可以使用下面的
3
中所述的方法求解。
3、单应矩阵求解:
这里使用的方法基于最大似然准则:假设提取的
m
存在均值为0,噪声协方差矩阵为的高斯白噪声。
则优化目标为
∑i(mi−m^i)TΛ−1mi(mi−m^i)
其中
mi=1h¯¯¯T3Mi⎡⎣h¯¯¯T1Mih¯¯¯T2Mi⎤⎦
,其中
h¯¯¯i
是矩阵
H
的第
i
列,并且假设
Λmi=σ2I
(
mi
、
Mi
已知)
求解上面的非线性优化问题可以使用LM算法。
(1)初始值求解
令
x=[h¯¯¯1,h¯¯¯2,h¯¯¯3]
,则
sm~=HM~
可以重写为
[M~T0T0TM~T−uM~T−vM~T]x=0
对于
n
个点,对应
n
个方程,
Lx=0
,其中
x
是
1×9
的,
L
是
2n×9
的。
x
的解对应于
L
的最小奇异值的右奇异向量。
Q:为什么用svd求了,还需要用最大似然方法来优化?svd求的
H
是有误差的,需要用优化来精确求解。
4、求解相机内参
(1)利用约束条件求解内参矩阵A
在公式中,由于
r1
和
r2
是单位向量且是正交的,所以存在下面的关系:
hT1A−TA−1h2=0hT1A−TA−1h1=hT2A−TA−1h2
上面的公式写成方程组的形式如下所示:
[vT12(v11−v22)T]b=0
上面的等式是一个最小二乘问题,可以使用SVD求解.由于A有5个参数:
α,β,u0,v0,γ
,一个单应性矩阵对应两个约束,所以求解A需要3个单应性矩阵,也就是最小需要3幅图像(超定方程)。当然,
也可以使用两个单应性矩阵,此时需要令
γ=0
。算出了b之后,可以用下面的公式求
A
。
v0=(B12B13−B11B23)/(B11B22−B212)λ=B33−[B213+v0(B12B13−B11B23)]/B11α=λ/B11−−−−−√β=λB11/(B11B12−B212)−−−−−−−−−−−−−−−−−√γ=−B12α2β/λu0=γv0/β−B13α2/λ
5、求解相机外参
在上面求解了相机的内参之后,可以求出棋盘格的位姿,公式如下:
r1=λA−1h1r2=λA−1h2r3=r1×h2t=λA−1h3
在OpenCV中,上面的公式是用来求解优化参数的初始值的,最终的结果是使用优化的方法得到的。
由于存在误差,还是需要迭代求解以提高精度(问题描述如下):
给定棋盘格的
n
个图像和
m
个角点,并假设图像点被独立同分布的噪声影响。
似然函数如下所示:
∑i=1n∑j=1m=∥mij−m(A,Ri,ti,Mj)∥2
其中旋转矩阵
R
用向量
r
表示(罗巨格公式)
6、相机的畸变参数求解
上面的讨论中一直没有引入相机畸变的问题,这里引入相机的畸变。
记
(u,v)
为理想的像素坐标,
(u˘,v˘)
为实际观测得到的像素坐标(受到畸变)。同样的,有归一化的相机坐标系
(x,y)
和
(x˘,y˘)
对于径向畸变(这是张正友上的模型,泰勒展开):
x˘=x+x[K1(x2+y2)+k2(x2+y2)2]y˘=y+y[K1(x2+y2)+k2(x2+y2)2]
用像素坐标表示则为:
u˘=u+(u−u0)[K1(x2+y2)+k2(x2+y2)2]v˘=v+(v−v0)[K1(x2+y2)+k2(x2+y2)2]
写成如下形式:
[(u−u0)(x2+y2)(v−v0)(x2+y2)(u−u0)(x2+y2)2(v−v0)(x2+y2)][k1k2]=[u˘−uv˘−v]
给定
n
个图像中的
m
个点,可以得到
2mn
个方程,记为
Dk=d
。
则
k=(DTD)−1DTd
。
最小二乘方法求解:
∑i=1n∑j=1m∥mij−m˘(A,k1,k2,Ri,ti,Mj)∥2
如果求解了畸变参数
k1
和
k2
,则可以求解出没有畸变的坐标,从而使用上面的方法求解位姿和内参。
畸变参数
k1
和
k2
初始化可以简单的设为0,也可以使用后续的估计方法。
OpenCV的模型(《学习OpenCV》,这是Brown和Fryer的工作)还包括了切向畸变,并且镜像畸变有三项。因此,opencv中一共有五个参数
[k1,k2,p1,p2,k3]
OpenCV的标定步骤
1、初始化参数求解;
a、求解单应性矩阵;
b、根据理论的第4步求解相机内参的初始值;
c、根据理论的第5步求解相机外参的初始值;
d、畸变参数设置为0。
2、迭代求解总体最小二乘问题,也就是上面6所示的最小二乘问题。
后面会接着介绍最小二乘中的数学相关知识