相机成像原理
小孔成像与像素坐标
小孔成像原理如下图所示(焦点就是等价的小孔):
我们通常的相机,都是在上图像平面的位置放一块感光板来接收图像,接收到的图像,有一个像素坐标系
在上图中,任意一个像素点的坐标可以表示为
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi)。
图像坐标系与相机坐标系
图像坐标系是以图像中心为原点的坐标系,由像素坐标平移得到:
在图中,假设图像中心的像素坐标是
(
u
0
,
v
0
)
(u_0,v_0)
(u0,v0),相机中感光板每个像素的物理尺寸是
d
x
×
d
y
dx \times dy
dx×dy,那么,图像坐标系的坐标
(
x
,
y
)
(x,y)
(x,y)与像素坐标系的坐标
(
u
,
v
)
(u,v)
(u,v)之间的关系可以表示为:
{
x
=
d
x
(
u
−
u
0
)
=
u
⋅
d
x
−
u
0
⋅
d
x
y
=
d
y
(
v
−
v
0
)
=
v
⋅
d
y
−
v
0
⋅
d
y
\left\{ \begin{array}{c} x=dx(u- u_0)=u\cdot dx- u_0\cdot dx\\ y=dy(v- v_0)=v\cdot dy-v_0\cdot dy \\ \end{array} \right.
{x=dx(u−u0)=u⋅dx−u0⋅dxy=dy(v−v0)=v⋅dy−v0⋅dy
改写为矩阵式:
[
x
y
]
=
[
d
x
0
0
d
y
]
⋅
[
u
v
]
+
[
−
u
0
⋅
d
x
−
v
0
⋅
d
y
]
\begin{bmatrix} x\\ y\\ \end{bmatrix}= \begin{bmatrix} dx & 0\\ 0 & dy \\ \end{bmatrix}\cdot \begin{bmatrix} u\\ v\\ \end{bmatrix}+\begin{bmatrix} -u_0\cdot dx\\ -v_0\cdot dy\\ \end{bmatrix}
[xy]=[dx00dy]⋅[uv]+[−u0⋅dx−v0⋅dy]
齐次坐标表达:
[
x
y
1
]
=
[
d
x
0
−
u
0
⋅
d
x
0
d
y
−
v
0
⋅
d
y
0
0
1
]
⋅
[
u
v
1
]
\begin{bmatrix} x\\ y\\ 1\\ \end{bmatrix}= \begin{bmatrix} dx & 0 &-u_0\cdot dx\\ 0 & dy & -v_0\cdot dy\\ 0 & 0&1\\ \end{bmatrix}\cdot \begin{bmatrix} u\\ v\\ 1\\ \end{bmatrix}
⎣⎡xy1⎦⎤=⎣⎡dx000dy0−u0⋅dx−v0⋅dy1⎦⎤⋅⎣⎡uv1⎦⎤
相机坐标系是以相机镜头的焦点为原点的坐标系:
其中焦点到像平面的距离,我们称为像距。对于许多单镜片相机来说,实际上镜片的焦距是固定的,我们只是在调整像距距离,使得物体成像清晰。
作为软件工程师,很多时候我们往往不需要知道像距好焦距的区别,或者说混为一谈,我们只要从小孔成像的角度去分析就可以了,把成像平面对称一下:
然后,我们就把对称过去的虚拟平面到相机坐标的距离称为焦距
f
f
f,(实际上这个距离是物距,为了和其他地方统一,我们后面都称其为焦距):
由相似三角形原理可得:
O c O i O c D = O c C D A = P C B A = O c C O c A \frac{O_cO_i}{O_cD}=\frac{O_cC}{DA}=\frac{PC}{BA}=\frac{O_cC}{O_cA} OcDOcOi=DAOcC=BAPC=OcAOcC
把 O c O i = f O_cO_i=f OcOi=f带入,可得实际坐标 ( X c , Y c ) (X_c,Y_c) (Xc,Yc)和图像坐标 ( x , y ) (x,y) (x,y)的关系:
f Z c = x X c = y Y c \frac{f}{Z_c}=\frac{x}{X_c}=\frac{y}{Y_c} Zcf=Xcx=Ycy ,即: X c = x ⋅ Z c f X_c=x\cdot \frac{Z_c}{f} Xc=x⋅fZc, Y c = y ⋅ Z c f Y_c=y\cdot \frac{Z_c}{f} Yc=y⋅fZc
写成矩阵式如下:
[
X
c
Y
c
Z
c
1
]
=
[
Z
c
f
0
0
0
Z
c
f
0
0
0
Z
c
0
0
1
]
⋅
[
x
y
1
]
\begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1\\ \end{bmatrix}= \begin{bmatrix} \frac{Z_c}{f} & 0 & 0 \\ 0 & \frac{Z_c}{f} & 0\\ 0 & 0&Z_c\\ 0 & 0&1\\ \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ 1\\ \end{bmatrix}
⎣⎢⎢⎡XcYcZc1⎦⎥⎥⎤=⎣⎢⎢⎡fZc0000fZc0000Zc1⎦⎥⎥⎤⋅⎣⎡xy1⎦⎤
到此为止,我们只是有了一个成像平面,但是这个平面怎么放,什么角度,什么位置,我们都不知道,像许多工业相机可能会固定安装在特定位置和特定角度:
也就是世界坐标和相机坐标还不一样,我们的相机在现实世界中可以平移,也可以旋转一个角度:
相机坐标与世界坐标的平移变换矩阵为:
T
=
[
1
0
0
t
x
0
1
0
t
y
0
0
1
t
z
0
0
0
1
]
T= \begin{bmatrix} 1& 0& 0& t_x\\ 0& 1&0& t_y\\ 0& 0& 1& t_z\\ 0& 0& 0& 1\\ \end{bmatrix}
T=⎣⎢⎢⎡100001000010txtytz1⎦⎥⎥⎤
绕
x
、
y
、
z
x、y、z
x、y、z轴的旋转变换矩阵分别为:
R
x
=
[
1
0
0
0
0
c
o
s
α
s
i
n
α
0
0
−
s
i
n
α
c
o
s
α
0
0
0
0
1
]
R_x= \begin{bmatrix} 1& 0& 0& 0\\ 0& cos\alpha& sin\alpha& 0\\ 0& -sin\alpha& cos\alpha& 0\\ 0& 0& 0& 1\\ \end{bmatrix}
Rx=⎣⎢⎢⎡10000cosα−sinα00sinαcosα00001⎦⎥⎥⎤
R
y
=
[
c
o
s
β
0
−
s
i
n
β
0
0
1
0
0
s
i
n
β
0
c
o
s
β
0
0
0
0
1
]
R_y= \begin{bmatrix} cos\beta&0& -sin\beta& 0\\ 0&1& 0& 0\\ sin\beta&0& cos\beta& 0\\ 0& 0& 0& 1\\ \end{bmatrix}
Ry=⎣⎢⎢⎡cosβ0sinβ00100−sinβ0cosβ00001⎦⎥⎥⎤
R
y
=
[
c
o
s
γ
s
i
n
γ
0
0
−
s
i
n
γ
c
o
s
γ
0
0
0
0
1
0
0
0
0
1
]
R_y= \begin{bmatrix} cos\gamma& sin\gamma& 0&0 \\ -sin\gamma&cos\gamma& 0&0 \\ 0&0& 1& 0\\ 0& 0& 0& 1\\ \end{bmatrix}
Ry=⎣⎢⎢⎡cosγ−sinγ00sinγcosγ0000100001⎦⎥⎥⎤
可得相机坐标与世界坐标的变换矩阵为
[
R
x
y
z
T
x
y
z
0
1
]
\begin{bmatrix} R_{xyz}& T_{xyz}\\ 0&1\\ \end{bmatrix}
[Rxyz0Txyz1]
其中:
R
x
y
z
=
R
x
⋅
R
y
⋅
R
z
R_{xyz}=R_x\cdot R_y\cdot R_z
Rxyz=Rx⋅Ry⋅Rz
T
x
y
z
=
[
t
x
t
y
t
z
]
T_{xyz}= \begin{bmatrix} t_x\\ t_y\\ t_z\end{bmatrix}
Txyz=⎣⎡txtytz⎦⎤
所以坐标变换关系即:
[ X w Y w Z w 1 ] = [ R x y z T x y z 0 1 ] ⋅ [ X c Y c Z c 1 ] \begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1\\ \end{bmatrix}= \begin{bmatrix} R_{xyz}& T_{xyz}\\ 0&1\\ \end{bmatrix} \cdot \begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1\\ \end{bmatrix} ⎣⎢⎢⎡XwYwZw1⎦⎥⎥⎤=[Rxyz0Txyz1]⋅⎣⎢⎢⎡XcYcZc1⎦⎥⎥⎤
相机的内参和外参
通过前面几个步骤,我们可以知道,要把像素坐标变换到世界坐标,需要经历如下步骤:
像素坐标 ( u , v ) → (u,v) \to (u,v)→图像坐标 ( x , y ) → (x,y) \to (x,y)→相机坐标 ( X c , Y c , Z c ) → (X_c,Y_c,Z_c) \to (Xc,Yc,Zc)→世界坐标 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)
所谓的内参,指的就是像素坐标
→
\to
→相机坐标的变换参数,
而所谓的外参,即相机坐标
→
\to
→世界坐标的变换参数
外参矩阵与内参矩阵
整体变换的矩阵式如下:
[
X
w
Y
w
Z
w
1
]
=
[
R
x
y
z
T
x
y
z
0
1
]
[
Z
c
f
0
0
0
Z
c
f
0
0
0
Z
c
0
0
1
]
[
d
x
0
−
u
0
⋅
d
x
0
d
y
−
v
0
⋅
d
y
0
0
1
]
⋅
[
u
v
1
]
\begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1\\ \end{bmatrix}= \begin{bmatrix} R_{xyz}& T_{xyz}\\ 0&1\\ \end{bmatrix} \begin{bmatrix} \frac{Z_c}{f} & 0 & 0 \\ 0 & \frac{Z_c}{f} & 0\\ 0 & 0&Z_c\\ 0 & 0&1\\ \end{bmatrix} \begin{bmatrix} dx & 0 &-u_0\cdot dx\\ 0 & dy & -v_0\cdot dy\\ 0 & 0&1\\ \end{bmatrix} \cdot \begin{bmatrix} u\\ v\\ 1\\ \end{bmatrix}
⎣⎢⎢⎡XwYwZw1⎦⎥⎥⎤=[Rxyz0Txyz1]⎣⎢⎢⎡fZc0000fZc0000Zc1⎦⎥⎥⎤⎣⎡dx000dy0−u0⋅dx−v0⋅dy1⎦⎤⋅⎣⎡uv1⎦⎤
化简可得外参矩阵与内参矩阵:
[
X
w
Y
w
Z
w
1
]
=
[
R
x
y
z
T
x
y
z
0
1
]
[
Z
c
f
⋅
d
x
0
−
Z
c
u
0
f
⋅
d
x
0
Z
c
f
⋅
d
y
−
Z
c
v
0
f
⋅
d
y
0
0
Z
c
0
0
1
]
⋅
[
u
v
1
]
\begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1\\ \end{bmatrix}= \begin{bmatrix} R_{xyz}& T_{xyz}\\ 0&1\\ \end{bmatrix} \begin{bmatrix} \frac{Z_c}{f}\cdot dx & 0 & - \frac{Z_cu_0}{f}\cdot dx \\ 0 & \frac{Z_c}{f} \cdot dy& - \frac{Z_cv_0}{f}\cdot dy\\ 0 & 0&Z_c\\ 0 & 0&1\\ \end{bmatrix} \cdot \begin{bmatrix} u\\ v\\ 1\\ \end{bmatrix}
⎣⎢⎢⎡XwYwZw1⎦⎥⎥⎤=[Rxyz0Txyz1]⎣⎢⎢⎡fZc⋅dx0000fZc⋅dy00−fZcu0⋅dx−fZcv0⋅dyZc1⎦⎥⎥⎤⋅⎣⎡uv1⎦⎤
公式中有一个
Z
c
Zc
Zc,它表示物体离光学中心的距离。也就是说在标定的时候,如果物体在距离相机的不同位置,那么我们就必须在不同的位置对相机做标定。
齐次坐标与向量的区别
我们在图形学或者很多其他领域内,都会见到齐次坐标的身影,我们会用齐次坐标来表示点,由或者表示向量:
P
=
[
x
y
1
]
,
P
⃗
=
[
x
y
0
]
P=\begin{bmatrix} x\\ y\\ 1\\ \end{bmatrix} ,\vec P=\begin{bmatrix} x\\ y\\ 0\\ \end{bmatrix}
P=⎣⎡xy1⎦⎤,P=⎣⎡xy0⎦⎤
我们会发现,对于向量,底下是用0,对于点,底下是用1,为什么这么规定呢?原因其实很简单,我们对一个向量进行平移,其大小和方向都不会改变,而对于一个点来说,其位置就改变了。假设有如下平移矩阵A,分别对点和向量进行运算,我们很容易从结果看出,点发生了变化,而向量不变:
[
x
+
t
x
y
+
t
y
1
]
=
[
1
0
t
x
0
1
t
y
0
0
1
]
⋅
[
x
y
1
]
=
A
⋅
P
\begin{bmatrix} x+t_x\\ y+t_y\\ 1\\ \end{bmatrix}=\begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0&1\\ \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ 1\\ \end{bmatrix}=A\cdot P
⎣⎡x+txy+ty1⎦⎤=⎣⎡100010txty1⎦⎤⋅⎣⎡xy1⎦⎤=A⋅P
[
x
y
0
]
=
[
1
0
t
x
0
1
t
y
0
0
1
]
⋅
[
x
y
0
]
=
A
⋅
P
⃗
\begin{bmatrix} x\\ y\\ 0\\ \end{bmatrix}=\begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0&1\\ \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ 0\\ \end{bmatrix}=A\cdot \vec P
⎣⎡xy0⎦⎤=⎣⎡100010txty1⎦⎤⋅⎣⎡xy0⎦⎤=A⋅P
图像畸变与矫正
造成图像畸变的原因有很多,总结起来可以分为两类:径向畸变和切向畸变。
径向畸变及其矫正
对于透镜而言,以透镜的中心作为原点,往外是透镜的半径的方向,当光线越靠近中心的位置,畸变越小,沿着半径方向远离中心的时候,畸变越大。我们可以用正常同心圆来看他们的变形情况
实际上,也就是两种情况,随着离中心越远距离d越大或者越小
我们可以在线性函数的基础上,通过添加二次项来逼近变形曲线:
即公式如下所示:
x
2
=
x
(
1
+
k
1
m
+
k
2
m
2
+
k
3
m
3
)
x_2=x(1+k_1m+k_2m^2+k_3m^3)
x2=x(1+k1m+k2m2+k3m3)
y
2
=
y
(
1
+
k
1
m
+
k
2
m
2
+
k
3
m
3
)
y_2=y(1+k_1m+k_2m^2+k_3m^3)
y2=y(1+k1m+k2m2+k3m3)
其中 ( x , y ) (x,y) (x,y)是畸变的坐标, ( x 2 , y 2 ) (x_2,y_2) (x2,y2)是矫正后像素点的坐标,且 m = r 2 = x 2 + y 2 m=r^2=x^2+y^2 m=r2=x2+y2
我们也可以改写为增量式,把增加量单独分离出来:
x
2
=
x
+
x
d
r
x_2=x+x_{dr}
x2=x+xdr
y
2
=
y
+
y
d
r
y_2=y+y_{dr}
y2=y+ydr
其中,增量为:
x
d
r
=
x
(
k
1
m
+
k
2
m
2
+
k
3
m
3
)
x_{dr}=x(k_1m+k_2m^2+k_3m^3)
xdr=x(k1m+k2m2+k3m3)
y
d
r
=
y
(
k
1
m
+
k
2
m
2
+
k
3
m
3
)
y_{dr}=y(k_1m+k_2m^2+k_3m^3)
ydr=y(k1m+k2m2+k3m3)
切向畸变及其矫正
咋一看,你会说,那个无夹角切向畸变不是在直径方向有变化么,怎么就切向了,不应该是径向畸变么,实际上我们这里讲的切向,不是指图像的切向,是指呈像的感光元件和透镜存在一个夹角,这个在下面区别中有介绍,这边作为结论记住就可以了。
旋转=放缩+剪切
我们先来看旋转矩阵,并把它分解为放缩+剪切形式:
[
s
i
n
θ
c
o
s
θ
−
c
o
s
θ
s
i
n
θ
]
=
[
s
i
n
θ
0
0
s
i
n
θ
]
+
[
0
c
o
s
θ
−
c
o
s
θ
0
]
\begin{bmatrix} sin\theta & cos\theta \\ -cos\theta & sin\theta \\ \end{bmatrix}=\begin{bmatrix} sin\theta & 0 \\ 0 & sin\theta \\ \end{bmatrix}+\begin{bmatrix} 0& cos\theta \\ -cos\theta & 0 \\ \end{bmatrix}
[sinθ−cosθcosθsinθ]=[sinθ00sinθ]+[0−cosθcosθ0]
对一个点进行旋转:
[
s
i
n
θ
c
o
s
θ
−
c
o
s
θ
s
i
n
θ
]
⋅
[
x
y
]
=
[
s
i
n
θ
⋅
x
s
i
n
θ
⋅
y
]
+
[
c
o
s
θ
⋅
y
−
c
o
s
θ
⋅
x
]
\begin{bmatrix} sin\theta & cos\theta \\ -cos\theta & sin\theta \\ \end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ \end{bmatrix}=\begin{bmatrix} sin\theta \cdot x \\ sin\theta \cdot y \\ \end{bmatrix}+\begin{bmatrix} cos\theta \cdot y\\ -cos\theta \cdot x\\ \end{bmatrix}
[sinθ−cosθcosθsinθ]⋅[xy]=[sinθ⋅xsinθ⋅y]+[cosθ⋅y−cosθ⋅x]
可得剪切矫正量:
d
x
=
c
o
s
θ
⋅
y
=
a
1
⋅
y
d
y
=
−
c
o
s
θ
⋅
x
=
a
2
⋅
x
dx=cos\theta \cdot y=a_1\cdot y\\ dy=-cos\theta \cdot x=a_2 \cdot x
dx=cosθ⋅y=a1⋅ydy=−cosθ⋅x=a2⋅x
矫正公式:
x
2
=
x
(
1
+
2
p
1
y
+
p
2
(
m
/
x
+
2
x
)
)
x_2=x(1+2p_1y+p_2(m/x+2x))
x2=x(1+2p1y+p2(m/x+2x))
y
2
=
y
(
1
+
2
p
2
x
+
p
1
(
m
/
y
+
2
y
)
)
y_2=y(1+2p_2x+p_1(m/y+2y))
y2=y(1+2p2x+p1(m/y+2y))
其中 ( x , y ) (x,y) (x,y)是畸变的坐标, ( x 2 , y 2 ) (x_2,y_2) (x2,y2)是矫正后像素点的坐标,且 m = r 2 = x 2 + y 2 m=r^2=x^2+y^2 m=r2=x2+y2
我们也可以改写为增量式,把增加量单独分离出来:
x
2
=
x
+
x
d
q
x_2=x+x_{dq}
x2=x+xdq
y
2
=
y
+
y
d
q
y_2=y+y_{dq}
y2=y+ydq
其中,增量为:
x
d
q
=
2
(
p
1
x
y
+
p
2
(
m
/
2
+
x
2
)
)
x_{dq}=2(p_1xy+p_2(m/2+x^2))
xdq=2(p1xy+p2(m/2+x2))
y
d
q
=
2
(
p
2
x
y
+
p
1
(
m
/
2
+
y
2
)
)
y_{dq}=2(p_2xy+p_1(m/2+y^2))
ydq=2(p2xy+p1(m/2+y2))
径向畸变与切向畸变的区别
对于一个相机来说,如果两个方向的变化比例是相等的,则发生径向畸变,若是两个方向变化比例不等,则发生的是切向畸变。我们现在的相机基本上都是径向畸变,切向畸变并不明显。
对于一个透镜而言,一般来说透镜本身四周的曲率都是相等的,也就是两个方向比例变化会相等。但我们还需要考虑呈像板,如果呈像板和透镜是平行的,自然所呈的像也是两个方向变化比例相等(同心圆形),即只发生径向畸变。若是呈像板和透镜不平行,两个方向就会出现比例不一致的情况(椭圆形),并且此时可能还会有一个偏角,即只发生切向畸变。
切向畸变好径向畸变只会发生其中一个,不可能同时发生,所以畸变矫正公式可以写成如下形式:
x 2 = x + x d q + x d r x_2=x+x_{dq}+x_{dr} x2=x+xdq+xdr
y 2 = y + y d q + y d r y_2=y+y_{dq}+y_{dr} y2=y+ydq+ydr