1. 摄像机的标定
摄像机标定的过程就是从1张或者多张图片中求解相机的内外参数的过程。
根据上一节的知识,针孔摄像机模型的世界坐标系到成像平面的映射关系为
p = K [ R , T ] P p = K[R,T]P p=K[R,T]P
其中 P P P是世界坐标系的坐标, p p p是成像坐标系的坐标。令 M = K [ R , T ] = [ m 1 , m 2 , m 3 ] T M = K[R, T] = [m_1, m_2, m_3]^T M=K[R,T]=[m1,m2,m3]T,得到
p i = [ u i v i ] = [ m 1 P i m 3 P i m 2 P i m 3 P i ] p_i = \begin{bmatrix} u_i \\ v_i \end{bmatrix} = \begin{bmatrix} \frac{m_1P_i}{m_3P_i} \\ \frac{m_2P_i}{m_3P_i} \end{bmatrix} pi=[uivi]=[m3Pim1Pim3Pim2Pi]
通常,我们可以采用这种标准化的格子来进行标定。例如下图的装置,假定三个面的交点就是世界坐标系原点,每个格子的宽度我们是知道的,所以某个点在世界坐标系的坐标值我们可以立即得到。相应地,这个点在成像平面的像素位置我们也知道。如图所示,世界坐标中的点 P i P_i Pi就被映射到了 p i p_i pi. 我们可以采集 n n n个点。
我们将映射关系重写为
u i ( m 3 P i ) = m 1 P i → m 1 P i − u i ( m 3 P i ) = 0 v i ( m 3 P i ) = m 2 P i → m 2 P i − v i ( m 3 P i ) = 0 u_i(m_3P_i) = m_1P_i \to m_1 P_i - u_i (m_3P_i) = 0 \\ v_i(m_3P_i) = m_2P_i \to m_2P_i - v_i (m_3P_i) = 0 ui(m3Pi)=m1Pi→m1Pi−ui(m3Pi)=0vi(m3Pi)=m2Pi→m2Pi−vi(m3Pi)=0
所以,一对 p i , P i p_i, P_i pi,Pi可以贡献2个方程。根据第一节的学习,我们知道 M M M是有11个自由度(5内参+6外参),所以至少需要6对点才能求解。但是我们采点的过程中,难免有噪声,因此一般是尽可能多采,然后解一个超定方程。
对于线性齐次超定方程 A x = 0 Ax=0 Ax=0, 最小二乘解的目标函数是 min ∣ ∣ y − A x ∣ ∣ = min ∣ ∣ A x ∣ ∣ \min ||y - Ax|| = \min ||Ax|| min∣∣y−Ax∣∣=min∣∣Ax∣∣. 如果我们限定 ∣ ∣ x ∣ ∣ = 1 , ||x||=1, ∣∣x∣∣=1,那么可以通过SVD求得。
对A进行SVD得到 A = U Σ V T A = U \Sigma V^T A=UΣVT.我们要最小化 ∣ ∣ A x ∣ ∣ ||Ax|| ∣∣Ax∣∣, 就可以取 A A A最小的奇异值对应的奇异向量(也就是 V V V的最后一列)。因为 A v i = σ v i u i Av_i = \sigma_{v_i} u_i Avi=σviui , 所以 ∣ ∣ A v i ∣ ∣ = σ v i ||Av_i|| = \sigma_{v_i} ∣∣Avi∣∣=σvi(因为 U U U是酉矩阵, ∣ ∣ u i ∣ ∣ = 1 ||u_i|| = 1 ∣∣ui∣∣=1),所以我们就应该取最小的奇异值对应的奇异向量作为解。
我们先写这个方程的形式。我们把 M M M拉成列向量:
m : = [ m 1 T m 2 T m 3 T ] ∈ R 12 m:= \begin{bmatrix} m_1^T \\ m_2^T \\ m_3^T \end{bmatrix} \in \mathbb{R}^{12} m:= m1Tm2Tm3T ∈R12
别忘了 m i m_i mi是行向量
我们要将上面的方程写成 P m = 0 Pm = 0 Pm=0的形式,现在我们来找这个 P P P.
如果我们找了 n n n对点,我们可以列出 2 n 2n 2n个方程如下:
− u 1 ( m 3 P 1 ) + m 1 P 1 = 0 − v 1 ( m 3 P 1 ) + m 2 P 1 = 0 . . . − u n ( m 3 P n ) + m 1 P n = 0 − v n ( m 3 P n ) + m 2 P n = 0 -u_1(m_3P_1) + m_1P_1 = 0 \\ -v_1(m_3P_1) + m_2P_1 = 0 \\ ... \\ -u_n(m_3P_n) + m_1P_n = 0 \\ -v_n(m_3P_n) + m_2P_n = 0 −u1(m3P1)+m1P1=0−v1(m3P1)+m2P1=0...−un(m3Pn)+m1Pn=0−vn(m3Pn)+m2Pn=0
对于其中一对点的两个方程,两边取转置,我们可以得到
P i T m 1 T + 0 T m 2 T − u i P i T m 3 T = 0 0 T m 1 T + P i T m 2 T − v i P i T m 3 T = 0 P_i^Tm_1^T + 0^Tm_2^T - u_iP_i^Tm_3^T = 0 \\ 0^Tm_1^T + P_i^Tm_2^T - v_iP_i^Tm_3^T = 0 PiTm1T+0Tm2T−uiPiTm3T=00Tm1T+PiTm2T−viPiTm3T=0
所以,我们令
P = [ P 1 T 0 T − u 1 P 1 T 0 T P 1 T − v 1 P 1 T . . . P n T 0 T − u n P n T 0 T P n T − v n P n T ] P = \begin{bmatrix} P_1^T \quad 0^T \quad -u_1P_1^T \\ 0^T \quad P_1^T \quad -v_1P_1^T \\ ...\\ P_n^T \quad 0^T \quad -u_nP_n^T \\ 0^T \quad P_n^T \quad -v_nP_n^T \end{bmatrix} P= P1T0T−u1P1T0TP1T−v1P1T...PnT0T−unPnT0TPnT−vnPnT
有 P m = 0 Pm = 0 Pm=0.
所以,求解的步骤就是:我们对 P P P进行SVD,然后求出最小奇异值对应的右奇异向量( V V V的最后一列), 这个向量就是解出的 m ^ \hat{m} m^. 然后我们将 m ^ \hat{m} m^重新整理,得到 3 × 4 3\times 4 3×4的矩阵 M ^ \hat{M} M^.
**但是!**我们通过这种SVD的方式,限定了 ∣ ∣ m ∣ ∣ = 1 ||m||=1 ∣∣m∣∣=1. 所以,真正的矩阵 M M M是和求解出的 M ^ \hat{M} M^差一个比例系数 ρ \rho ρ.
好,为了避免混乱,我们重新整理一下我们现在得到的结果:
-
世界坐标到像素坐标的映射为 p = M P = K [ R , T ] P p = MP = K[R, T]P p=MP=K[R,T]P
-
内参矩阵为( θ \theta θ是传感器横纵边的夹角,与工艺有关,理想情况 θ \theta θ是直角,推导在后文补充)
[ α − α cot θ u 0 0 β / sin θ v 0 0 0 1 ] \begin{bmatrix} \alpha & -\alpha \cot \theta & u_0 \\ 0 & \beta / \sin \theta & v_0 \\ 0& 0& 1 \end{bmatrix} α00−αcotθβ/sinθ0u0v01 -
外参矩阵,写成如下形式:
R = [ r 1 T r 2 T r 3 T ] , T = [ t 1 t 2 t 3 ] R = \begin{bmatrix} r_1^T \\ r_2^T \\ r_3^T \end{bmatrix}, T = \begin{bmatrix} t_1 \\ t_2 \\ t_3 \end{bmatrix} R= r1Tr2Tr3T ,T= t1t2t3
其中 r i ∈ R 3 r_i \in \mathbb{R}^3 ri∈R3是 R R R的行向量(它是列向量,所以转置是行), t i ∈ R t_i \in \mathbb{R} ti∈R. -
我们把 M M M乘开,得到:
M = [ α r 1 T − α cot θ r 2 T + u 0 r 3 T α t 1 − α cot θ t 2 + u 0 t 3 β sin θ r 2 T + v 0 r 3 T β sin θ t 2 + v 0 t 3 r 3 T t 3 ] = ρ M ^ M = \begin{bmatrix} \alpha r_1^T - \alpha \cot \theta r_2^T + u_0 r_3^T & \alpha t_1 - \alpha \cot \theta t_2 + u_0 t_3 \\ \frac{\beta}{\sin \theta}r_2^T + v_0 r_3^T & \frac{\beta}{\sin \theta}t_2 + v_0 t_3 \\ r_3^T & t_3 \end{bmatrix} = \rho \hat{M} M= αr1T−αcotθr2T+u0r3Tsinθβr2T+v0r3Tr3Tαt1−αcotθt2+u0t3sinθβt2+v0t3t3 =ρM^ -
我们现在已知的是 M ^ \hat{M} M^,可以将其进一步写成 M ^ = [ A , b ] \hat{M} = [A, b] M^=[A,b], 这里面的元素都是已知的。我们未知的是 K , R , T , ρ K, R, T, \rho K,R,T,ρ.
-
别忘了旋转矩阵的性质: r 1 , r 2 , r 3 r_1, r_2, r_3 r1,r2,r3相互正交,且模为1.
2.1 ρ , u 0 , v 0 \rho, u_0, v_0 ρ,u0,v0的获取
我们继续推导:
ρ M ^ = ρ [ A , b ] = [ . . . ] \rho \hat{M} = \rho [A, b] = [...] ρM^=ρ[A,b]=[...]
所以
ρ A = ρ [ a 1 T a 2 T a 3 T ] = [ α r 1 T − α cot θ r 2 T + u 0 r 3 T β sin θ r 2 T + v 0 r 3 T r 3 T ] = K R \rho A = \rho \begin{bmatrix} a_1^T \\ a_2^T \\ a_3^T \end{bmatrix} = \begin{bmatrix} \alpha r_1^T - \alpha \cot \theta r_2^T + u_0 r_3^T\\ \frac{\beta}{\sin \theta}r_2^T + v_0 r_3^T \\ r_3^T \end{bmatrix} = KR ρA=ρ a1Ta2Ta3T = αr1T−αcotθr2T+u0r3Tsinθβr2T+v0r3Tr3T =KR
根据最后一行,立即得到
ρ a 3 T = r 3 T \rho a_3^T = r_3^T ρa3T=r3T
两边取模:
∣ ρ ∣ ∣ a 3 ∣ = 1 → ρ = ± 1 ∣ a 3 ∣ |\rho||a_3| = 1 \to \rho = \pm \frac{1}{|a_3|} ∣ρ∣∣a3∣=1→ρ=±∣a3∣1
因此 ρ \rho ρ就确定了。
然后,我们再考察最后一行点乘中间一行:
( ρ a 3 T ) ⋅ ( ρ a 2 T ) = ρ 2 ( a 2 ⋅ a 3 ) = β sin θ ( r 2 ⋅ r 3 ) + v 0 ∣ r 3 ∣ ( 正交性,模为 1 ) = v 0 (\rho a_3^T) \cdot (\rho a_2^T) = \rho^2(a_2 \cdot a_3) \\ = \frac{\beta}{\sin \theta}(r_2 \cdot r_3) + v_0 |r_3| \\ (正交性,模为1) = v_0 (ρa3T)⋅(ρa2T)=ρ2(a2⋅a3)=sinθβ(r2⋅r3)+v0∣r3∣(正交性,模为1)=v0
所以 v 0 v_0 v0确定了为 v 0 = ρ 2 ( a 2 ⋅ a 3 ) v_0 = \rho^2(a_2 \cdot a_3) v0=ρ2(a2⋅a3)
同理,我们考察最后一行点乘第一行,**确定 u 0 u_0 u0**为 u 0 = ρ 2 ( a 1 ⋅ a 3 ) u_0 = \rho^2 (a_1 \cdot a_3) u0=ρ2(a1⋅a3).
我们用了点乘,也可以用叉乘。
根据正交向量之间叉乘的关系,我们分别让最后一行叉乘第一行和第二行:
ρ 2 ( a 1 × a 3 ) = α r 2 − α cot θ r 1 ρ 2 ( a 2 × a 3 ) = β sin θ r 1 \rho^2(a_1 \times a_3) = \alpha r_2 - \alpha \cot \theta r_1 \\ \rho^2(a_2 \times a_3) = \frac{\beta}{\sin \theta}r_1 ρ2(a1×a3)=αr2−αcotθr1ρ2(a2×a3)=sinθβr1
两边取模:
ρ 2 ∣ ( a 1 × a 3 ) ∣ = ∣ α r 2 − α cot θ r 1 ∣ ρ 2 ∣ ( a 2 × a 3 ) ∣ = ∣ β ∣ sin θ \rho^2|(a_1 \times a_3)| = |\alpha r_2 - \alpha \cot \theta r_1| \\ \rho^2|(a_2 \times a_3)| = \frac{|\beta|}{\sin \theta} ρ2∣(a1×a3)∣=∣αr2−αcotθr1∣ρ2∣(a2×a3)∣=sinθ∣β∣
而
∣ α r 2 − α cot θ r 1 ∣ 2 = ( ⋅ ) T ( ⋅ ) = α 2 + α 2 cot 2 θ ( 1 + cot 2 θ = 1 / sin 2 θ ) = ( α sin θ ) 2 |\alpha r_2 - \alpha \cot \theta r_1|^2 = (\cdot)^T(\cdot) = \alpha^2 + \alpha^2 \cot^2 \theta \\ (1 + \cot^2 \theta = 1 / \sin^2 \theta) = (\frac{\alpha}{\sin \theta})^2 ∣αr2−αcotθr1∣2=(⋅)T(⋅)=α2+α2cot2θ(1+cot2θ=1/sin2θ)=(sinθα)2
由于 θ \theta θ是一个0~90度之间的值,所以
ρ 2 ∣ ( a 1 × a 3 ) ∣ = ∣ α ∣ sin θ ρ 2 ∣ ( a 2 × a 3 ) ∣ = ∣ β ∣ sin θ \rho^2|(a_1 \times a_3)| = \frac{|\alpha|}{\sin \theta} \\ \rho^2|(a_2 \times a_3)| = \frac{|\beta|}{\sin \theta} ρ2∣(a1×a3)∣=sinθ∣α∣ρ2∣(a2×a3)∣=sinθ∣β∣
考察
ρ 2 ( a 1 × a 3 ) ⋅ ρ 2 ( a 2 × a 3 ) = − α β cos θ sin 2 θ ρ 2 ∣ ( a 1 × a 3 ) ∣ ⋅ ρ 2 ∣ ( a 2 × a 3 ) ∣ = ∣ α ∣ ∣ β ∣ sin 2 θ \rho^2(a_1 \times a_3) \cdot \rho^2(a_2 \times a_3) = - \alpha \beta \frac{\cos \theta}{\sin^2 \theta} \\ \rho^2|(a_1 \times a_3)| \cdot\rho^2|(a_2 \times a_3)| = \frac{|\alpha||\beta|}{\sin^2 \theta} ρ2(a1×a3)⋅ρ2(a2×a3)=−αβsin2θcosθρ2∣(a1×a3)∣⋅ρ2∣(a2×a3)∣=sin2θ∣α∣∣β∣
两式相除( α , β > 0 \alpha, \beta > 0 α,β>0,可以消去绝对值),得到
cos θ = − ( a 1 × a 3 ) ⋅ ( a 2 × a 3 ) ∣ ( a 1 × a 3 ) ∣ ⋅ ∣ ( a 1 × a 3 ) ∣ \cos \theta = -\frac{(a_1 \times a_3)\cdot (a_2 \times a_3)}{|(a_1 \times a_3)| \cdot |(a_1 \times a_3)| } cosθ=−∣(a1×a3)∣⋅∣(a1×a3)∣(a1×a3)⋅(a2×a3)
这样 θ \theta θ也被确定了, 就可以立即得到
α = ρ 2 ∣ ( a 1 × a 3 ) ∣ sin θ β = ρ 2 ∣ ( a 2 × a 3 ) ∣ sin θ \alpha = \rho^2|(a_1 \times a_3)| \sin \theta \\ \beta = \rho^2|(a_2 \times a_3)| \sin \theta α=ρ2∣(a1×a3)∣sinθβ=ρ2∣(a2×a3)∣sinθ
这样 α , β \alpha, \beta α,β也被确定了.
再返回去看之前叉乘的结果,根据 ρ 2 ( a 2 × a 3 ) = β sin θ r 1 \rho^2(a_2 \times a_3) = \frac{\beta}{\sin \theta}r_1 ρ2(a2×a3)=sinθβr1, 由于 r 1 r_1 r1是一个单位向量,指示着向量 a 2 × a 3 a_2 \times a_3 a2×a3的方向,所以我们对 a 2 × a 3 a_2 \times a_3 a2×a3单位化就能得到其方向上的单位向量:
r 1 = a 2 × a 3 ∣ a 2 × a 3 ∣ r_1 = \frac{a_2 \times a_3}{|a_2 \times a_3|} r1=∣a2×a3∣a2×a3
此外,根据 ρ a 3 T = r 3 T \rho a_3^T = r_3^T ρa3T=r3T,代入 ρ \rho ρ立即得到 r 3 = ± a 3 ∣ a 3 ∣ r_3 = \pm \frac{a_3}{|a_3|} r3=±∣a3∣a3. 根据正交关系,立即得到 r 2 = r 1 × r 3 r_2 = r_1 \times r_3 r2=r1×r3.
这样 r 2 , r 1 , r 3 r_2 , r_1, r_3 r2,r1,r3也被确定了. 因此我们得到了 R R R. 根据
ρ M ^ = ρ [ A , b ] = K [ R , T ] → ρ b = K T T = ρ K − 1 b \rho \hat{M} =\rho[A, b] = K[R, T] \\ \to \rho b = KT \\ T = \rho K^{-1}b ρM^=ρ[A,b]=K[R,T]→ρb=KTT=ρK−1b
这样 T T T也被确定了,至此我们得到了所有的参数,总结如下:
2. 畸变与畸变下的标定
之前说过桶型和枕型畸变。我们首先对畸变进行建模。
对于桶型畸变,越靠外侧的点越会被拉伸到原点
理想情况下到成像平面的点坐标为 p = M P p=MP p=MP, 但需要对 x , y x, y x,y轴乘缩放因子,因此是
p = [ 1 / λ 0 0 0 1 / λ 0 0 0 1 ] M P p = \begin{bmatrix} 1/\lambda & 0 & 0 \\ 0 & 1/\lambda & 0 \\ 0 & 0 & 1 \end{bmatrix} MP p= 1/λ0001/λ0001 MP
我们用多项式定义 λ = 1 + ∑ p = 1 3 k p d 2 p \lambda = 1 + \sum_{p=1}^3k_p d^{2p} λ=1+∑p=13kpd2p
所以 k p = 0 k_p=0 kp=0时表示无畸变,称为畸变因子。 d = x 2 + y 2 d=x^2+y^2 d=x2+y2表示到原点的距离。
相反地,对于枕型畸变,越靠外侧的点越会被拉远到原点,所以 λ = 1 − ∑ p = 1 3 k p d 2 p \lambda = 1 - \sum_{p=1}^3k_p d^{2p} λ=1−∑p=13kpd2p
因此,令
Q = [ 1 / λ 0 0 0 1 / λ 0 0 0 1 ] M = [ q 1 q 2 q 3 ] M Q= \begin{bmatrix} 1/\lambda & 0 & 0 \\ 0 & 1/\lambda & 0 \\ 0 & 0 & 1 \end{bmatrix} M =\begin{bmatrix} q_1 \\ q_2 \\ q_3 \end{bmatrix} M Q= 1/λ0001/λ0001 M= q1q2q3 M
按照上一节的方式,我们也可以写出
− u 1 ( q 3 P 1 ) + q 1 P 1 = 0 − v 1 ( q 3 P 1 ) + q 2 P 1 = 0 . . . -u_1(q_3P_1) + q_1P_1 = 0 \\ -v_1(q_3P_1) + q_2P_1 = 0 \\ ... −u1(q3P1)+q1P1=0−v1(q3P1)+q2P1=0...
但是! q q q里面含有未知量(畸变因子),所以上述方程不再是线性方程,需要通过牛顿法或者L-M方法迭代求解。
然而,我们还可以更进一步。根据 q 1 = 1 λ m 1 , q 2 = 1 λ m 2 , q 3 = m 3 q_1 = \frac{1}{\lambda}m_1, q_2 = \frac{1}{\lambda}m_2, q_3 = m_3 q1=λ1m1,q2=λ1m2,q3=m3, 则
p i = [ q 1 P i q 3 P i q 2 P i q 3 P i ] = 1 λ [ m 1 P i m 3 P i m 2 P i m 3 P i ] p_i = \begin{bmatrix} \frac{q_1P_i}{q_3P_i} \\ \frac{q_2P_i}{q_3P_i} \end{bmatrix} = \frac{1}{\lambda} \begin{bmatrix} \frac{m_1P_i}{m_3P_i} \\ \frac{m_2P_i}{m_3P_i} \end{bmatrix} pi=[q3Piq1Piq3Piq2Pi]=λ1[m3Pim1Pim3Pim2Pi]
我们消去 λ \lambda λ:
u i v i = m 1 P i m 2 P i \frac{u_i}{v_i} = \frac{m_1P_i}{m_2P_i} viui=m2Pim1Pi
得到 u i m 2 P i − v i m 1 P i = 0 u_im_2P_i- v_im_1P_i=0 uim2Pi−vim1Pi=0, 这又是一个线性方程组,可以按照同样的方法求出 m 1 , m 2 m_1, m_2 m1,m2,这样就减少了牛顿法或L-M方法所需要迭代的参数量。
3. 2D平面和3D空间的变换
如果两个点A,B经过某种变换后,各自变成A’, B’, 但AB的距离和A’B’的距离一样,称这个变换是等距变换,具有下面的形式:
[ x ′ y ′ 1 ] = [ σ cos θ − sin θ x 0 σ sin θ cos θ y 0 0 0 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} \sigma \cos \theta & - \sin \theta & x_0 \\ \sigma \sin \theta & \cos \theta & y_0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} x′y′1 = σcosθσsinθ0−sinθcosθ0x0y01 xy1
其中, σ = 1 \sigma=1 σ=1时称为保向变换,即单纯的旋转/平移操作,而 σ = − 1 \sigma=-1 σ=−1是镜像变换,如下图:
更广义地,仿射变换如下:
[ x ′ y ′ 1 ] = [ A 3 × 3 t 3 × 1 0 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} A_{3\times 3} & t_{3\times 1} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} x′y′1 =[A3×30t3×11] xy1
不变量:平行性不变,面积的比值不变,平行线段长度的比值不变。
类似地,在3D空间中,定义仿射变换
[ x ′ y ′ z ′ 1 ] = [ A 3 × 3 t 3 × 1 0 1 ] [ x y z 1 ] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} A_{3\times 3} & t_{3\times 1} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} x′y′z′1 =[A3×30t3×11] xyz1
不变量:保持无穷远平面不变(无穷远点变换到无穷远点)、保持直线与直线、直线与平面、平面与平面的平行性不变
如果左下角不再是0,而是一个向量 v v v,则称为透视变换:
[ x ′ y ′ z ′ 1 ] = [ A 3 × 3 t 3 × 1 v 3 × 1 T 1 ] [ x y z 1 ] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} A_{3\times 3} & t_{3\times 1} \\ v_{3\times1}^T & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} x′y′z′1 =[A3×3v3×1Tt3×11] xyz1
不变量:点变换到点,线变换到线,保持点的共线(面)性、线的共面性.