一、数学基础
1.1 反对称矩阵的性质
我们令 A = [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] A=\left[ {\begin{matrix} 0&{ - {a_3}}&{{a_2}}\\ {{a_3}}&0&{ - {a_1}}\\ { - {a_2}}&{{a_1}}&0 \end{matrix}} \right] A=⎣⎡0a3−a2−a30a1a2−a10⎦⎤,该矩阵是一个反对称矩阵,即 A T = − A A^T=-A AT=−A;
利用
det
(
λ
E
−
A
)
=
0
\det(\lambda E-A)=0
det(λE−A)=0来反对称矩阵A的特征值,化简得:
λ
(
λ
2
+
m
)
=
0
,
m
=
a
1
2
+
a
2
2
+
a
3
2
(1)
\lambda(\lambda^2+m)=0, \;\;\;\;\;m=a_1^2+a_2^2+a_3^2\tag{1}
λ(λ2+m)=0,m=a12+a22+a32(1)
从特征多项式我们可以看出,这个
3
×
3
3\times3
3×3的矩阵的秩为2,有一个特征值为0,另外两个特征值相等且为虚数。
下面我们对反对称矩阵进行分解:
首先我们对于对称矩阵来说,如果矩阵 A A A是一个对称矩阵(在复数域上被称为Hermite矩阵),即 A T = A A^T=A AT=A,则存在一个正交矩阵 U ( U U T = U T U = I ) U(UU^T=U^TU=I) U(UUT=UTU=I),使得 A = U D U T A=UDU^T A=UDUT, D D D为对角矩阵,另外 A A A不同特征值对应的特征向量正交;
返回到反对称矩阵上,若
S
S
S为反对称矩阵(在复数域上被称为反Hermite矩阵),存在正交矩阵
U
U
U,使得:
S
=
U
B
U
T
,
B
=
κ
⋅
d
i
a
g
(
z
1
,
z
2
,
.
.
.
,
z
m
,
0
,
0
,
.
.
.
,
0
)
(2)
S=UBU^T , \space \space \space \space \space B=\kappa \cdot diag(z_1,z_2,...,z_m,0,0,...,0)\tag{2}
S=UBUT, B=κ⋅diag(z1,z2,...,zm,0,0,...,0)(2)
其中
κ
\kappa
κ为常数对角矩阵
κ
=
d
i
a
g
(
κ
1
,
κ
2
,
.
.
.
,
κ
m
,
0
,
0
,
.
.
.
,
0
)
\kappa = diag(\kappa_1,\kappa_2,...,\kappa_m,0,0,...,0)
κ=diag(κ1,κ2,...,κm,0,0,...,0),
z
i
=
[
0
1
−
1
0
]
,
(
i
=
1
,
2
,
.
.
.
,
m
)
z_i=\begin{bmatrix} 0 &1\\-1&0 \end{bmatrix},(i=1,2,...,m)
zi=[0−110],(i=1,2,...,m)。
我们主要分析
3
×
3
3\times3
3×3的矩阵,令
S
S
S为
3
×
3
3\times3
3×3的反对称矩阵,另外令:
W
=
[
0
−
1
0
1
0
0
0
0
1
]
,
Z
=
[
0
1
0
−
1
0
0
0
0
0
]
(3)
W=\begin{bmatrix} 0 &-1&0\\ \\1&0&0\\\\0&0&1 \end{bmatrix},\space Z=\begin{bmatrix} 0 &1&0\\ \\-1&0&0\\\\0&0&0 \end{bmatrix}\tag{3}
W=⎣⎢⎢⎢⎢⎡010−100001⎦⎥⎥⎥⎥⎤, Z=⎣⎢⎢⎢⎢⎡0−10100000⎦⎥⎥⎥⎥⎤(3)
根据上述性质,能够推出
S
S
S和
Z
Z
Z合同,即:
S
=
κ
⋅
U
Z
U
T
(4)
S=\kappa \cdot UZU^T \tag{4}
S=κ⋅UZUT(4)
为了在奇异值分解中构造奇异值 1,1,0,所以构造了正交矩阵
W
W
W,满足
Z
=
−
d
i
a
g
(
1
,
1
,
0
)
W
=
d
i
a
g
(
1
,
1
,
0
)
W
T
Z=-diag(1,1,0)W =diag(1,1,0)W^T
Z=−diag(1,1,0)W=diag(1,1,0)WT,所以有:
S
=
−
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
⋅
U
T
或
者
S
=
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
T
⋅
U
T
(5)
\begin{aligned} S = -\kappa \cdot U\cdot diag(1,1,0)W\cdot U^T \\ ~\\或者 \quad S = \kappa \cdot U\cdot diag(1,1,0)W^T\cdot U^T \end{aligned}\tag{5}
S=−κ⋅U⋅diag(1,1,0)W⋅UT 或者S=κ⋅U⋅diag(1,1,0)WT⋅UT(5)
参考文献: Multiple View Geometry in Computer Vision Second Edition. P258-259
接下来我们介绍奇异值分解;
1.2 奇异值分解
奇异值分解简单介绍,具体参考:奇异值分解(SVD)----作者:漫漫成长
对于一个矩阵
A
m
×
n
A_{m\times n}
Am×n,
r
a
n
k
(
A
)
=
r
(
r
⩽
n
,
m
)
rank(A)=r\space ({r\leqslant n,m})
rank(A)=r (r⩽n,m),则
A
T
A
A^TA
ATA矩阵有
r
r
r个非零特征值
(
λ
1
,
λ
2
,
.
.
.
,
λ
r
)
(\lambda_1,\lambda_2,...,\lambda_r)
(λ1,λ2,...,λr),存在两个正交矩阵
U
,
V
U,V
U,V,使得
A
A
A可以被分解为:
A
=
U
S
0
V
T
,
S
=
d
i
a
g
(
λ
1
,
λ
2
,
.
.
.
,
λ
r
,
0
,
.
.
.
,
0
)
n
×
n
(6)
A=US_0V^T,\quad S=diag(\lambda_1,\lambda_2,...,\lambda_r, 0,...,0)_{n \times n}\tag{6}
A=US0VT,S=diag(λ1,λ2,...,λr,0,...,0)n×n(6)
S
S
S中的元素被称为
A
A
A的奇异值,其中
V
V
V为
A
T
A
A^TA
ATA特征值对应的单位特征向量,
U
U
U为
A
A
T
AA^T
AAT特征值对应的单位特征向量。
由3阶反对称矩阵的特征值特点可以知道其奇异值一定是 d i a g ( σ , σ , 0 ) diag(\sigma,\sigma,0) diag(σ,σ,0),因为其有特征值0,以及两个相等的特征值。
二、本质矩阵的推导
如图所示,我们需要通过不同的2D图像,利用相同的路标点(特征点),来推算相机之间的运动R和t,下面我们根据对极几何的特性进行推导。
我们假设存在着一个路标点 P w P_w Pw,对应两个不同相机位姿的像素坐标为 p 1 、 p 2 p_1、p_2 p1、p2,分别对应着图像 I 1 和 I 2 I_1和I_2 I1和I2, 另外我们假设图像 I 1 I_1 I1对应的相机坐标与世界坐标重合(即 T 1 , w = E 4 × 4 T_{1,w}=\bm E_{4\times4} T1,w=E4×4)。
由相机模型可得:
s
1
p
1
=
K
T
1
,
w
P
w
=
K
P
w
s
2
p
2
=
K
T
2
,
w
P
w
=
K
(
R
P
w
+
t
)
(7)
\begin{aligned} s_1\bm p_1&=\bm {KT_{1,w}P_w}=\bm {KP_w}\\~\\ s_2\bm p_2&=\bm{KT_{2,w}P_w}=\bm{K(RP_w+t)} \end{aligned}\tag{7}
s1p1 s2p2=KT1,wPw=KPw=KT2,wPw=K(RPw+t)(7)
实际上,
T
2
,
w
T_{2,w}
T2,w也就是
T
2
,
1
T_{2,1}
T2,1,即相机1到相机2的变换矩阵。
则有:
K
−
1
p
1
=
1
s
1
P
w
K
−
1
p
2
=
1
s
2
(
R
P
w
+
t
)
(8)
\bm K^{-1}\bm p_1=\frac 1 {s_1}\bm P_w\\ ~\\ \bm K^{-1}\bm p_2=\frac 1 {s_2}\bm{(RP_w+t)} \tag{8}
K−1p1=s11Pw K−1p2=s21(RPw+t)(8)
我们令:
x
1
=
K
−
1
p
1
,
x
2
=
K
−
1
p
2
(9)
\bm x_1=\bm K^{-1}\bm p_1,\quad \bm x_2=\bm K^{-1}\bm p_2\tag{9}
x1=K−1p1,x2=K−1p2(9)
由公式可知,
x
1
x_1
x1和
x
2
x_2
x2是点
P
w
\bm P_w
Pw在两个相机坐标系下的归一化坐标点(深度坐标化为1,只需给出相机内参
K
K
K和像素坐标即可得到)
由式8可以得到:
s
2
K
−
1
p
2
=
s
1
R
K
−
1
p
1
+
t
(10)
s_2\bm K^{-1}\bm p_2=s_1\bm{R\bm K^{-1}\bm p_1+t}\tag{10}
s2K−1p2=s1RK−1p1+t(10)
两边同时左乘
t
∧
t ^\wedge
t∧可得:
t
∧
s
2
(
K
−
1
p
2
)
=
t
∧
s
1
R
(
K
−
1
p
1
)
+
0
(11)
t ^\wedge s_2\bm {(K^{-1}\bm p_2)}=t ^\wedge s_1\bm{R(\bm K^{-1}\bm p_1)+0}\tag{11}
t∧s2(K−1p2)=t∧s1R(K−1p1)+0(11)
在左乘一个
(
K
−
1
p
2
)
T
\bm {(K^{-1}\bm p_2)}^T
(K−1p2)T,由叉乘的性质可得,向量
(
K
−
1
p
2
)
\bm {(K^{-1}\bm p_2)}
(K−1p2)与
t
∧
(
K
−
1
p
2
)
t ^\wedge \bm {(K^{-1}\bm p_2)}
t∧(K−1p2)正交(垂直),同时深度信息也消失了(失去了一个自由度):
0
=
(
K
−
1
p
2
)
T
t
∧
s
1
R
(
K
−
1
p
1
)
(12)
0=\bm {(K^{-1}\bm p_2)}^Tt ^ \wedge \red {\sout {\textbf s_1}}\bm{R(\bm K ^{-1}\bm p_1)}\tag{12}
0=(K−1p2)Tt∧s1R(K−1p1)(12)
由式12和式9可得:
x
2
T
t
∧
R
x
1
=
0
\bm {x_2}^Tt ^\wedge \bm{R\space x_1}=0
x2Tt∧R x1=0
其中,
E
=
t
∧
R
\bm E=t ^\wedge \bm R
E=t∧R被称为本质矩阵,所以在本质矩阵中,包含了旋转和平移的信息。
接下来就是求解本质矩阵。
三、求解本质矩阵Rt
我们可以通过8个匹配点来求取本质矩阵 E \bm E E,这里继续介绍如何分解本质矩阵。
对本质矩阵进行SVD分解,首先对反对称矩阵 t ∧ t ^\wedge t∧分解:
t
∧
=
κ
⋅
U
Z
U
T
=
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
T
⋅
U
T
或
者
t
∧
=
−
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
⋅
U
T
其
中
,
W
=
[
0
−
1
0
1
0
0
0
0
1
]
(13)
t ^\wedge=\kappa \cdot \bm U\bm Z\bm U^T=\kappa \cdot \bm U\cdot diag(1,1,0)\bm W^T\cdot \bm U^T\\ ~\\或者\quad t ^\wedge=-\kappa \cdot \bm U\cdot diag(1,1,0)\bm W\cdot \bm U^T\\~\\ \\~\\ 其中,\bm W=\begin{bmatrix} 0 &-1&0\\ \\1&0&0\\\\0&0&1 \end{bmatrix} \tag{13}
t∧=κ⋅UZUT=κ⋅U⋅diag(1,1,0)WT⋅UT 或者t∧=−κ⋅U⋅diag(1,1,0)W⋅UT 其中,W=⎣⎢⎢⎢⎢⎡010−100001⎦⎥⎥⎥⎥⎤(13)
所以本质矩阵有两种表示法:
E
=
t
∧
R
=
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
T
⋅
U
T
R
E
=
t
∧
R
=
−
κ
⋅
U
⋅
d
i
a
g
(
1
,
1
,
0
)
W
⋅
U
T
R
\bm E =t ^\wedge \bm R =\kappa \cdot \bm U\cdot diag(1,1,0)\bm W^T\cdot \bm U^T\bm R\\~\\ \bm E =t ^\wedge \bm R =-\kappa \cdot \bm U\cdot diag(1,1,0)\bm W\cdot \bm U^T\bm R
E=t∧R=κ⋅U⋅diag(1,1,0)WT⋅UTR E=t∧R=−κ⋅U⋅diag(1,1,0)W⋅UTR
对本质矩阵奇异值分解:
E
=
U
S
0
V
T
则
V
T
=
W
⋅
U
T
R
或
W
T
⋅
U
T
R
\bm E=\bm U\bm S_0 \bm V^T\\~\\则\quad \bm V^T=\bm W\cdot \bm U^T\bm R\quad或 \quad \bm W^T\cdot \bm U^T\bm R
E=US0VT 则VT=W⋅UTR或WT⋅UTR;
由于 t ∧ t^ \wedge t∧特殊的特征值结构,所以可以推出本质矩阵奇异值一定是 d i a g ( σ , σ , 0 ) diag(\sigma,\sigma,0) diag(σ,σ,0)的形式,所以 κ \bm \kappa κ向量中的各元素相等,式13可以写成:
E
=
U
⋅
d
i
a
g
(
κ
,
κ
,
0
)
⋅
(
W
⋅
U
T
R
)
(14)
\bm E = \bm U\cdot diag(\kappa,\kappa,0)\cdot (\bm W\cdot \bm U^T\bm R)\tag{14}
E=U⋅diag(κ,κ,0)⋅(W⋅UTR)(14)
分解得到
U
、
V
\bm U、\bm V
U、V后,我们可以求出
R
R
R和
t
t
t:
R
=
U
W
V
T
或
R
=
U
W
T
V
T
t
∧
=
κ
U
⋅
Z
⋅
U
T
或
t
∧
=
−
κ
U
⋅
Z
⋅
U
T
其
中
,
Z
=
[
0
1
0
−
1
0
0
0
0
0
]
,
W
=
[
0
−
1
0
1
0
0
0
0
1
]
\bm R= \bm U\bm W \bm V^T\quad或\quad \bm R= \bm U\bm W^T \bm V^T\\ ~\\\quad \bm t^ \wedge= \space\kappa\bm U\cdot \bm Z\cdot \bm U^T \quad 或 \quad \bm t^ \wedge= - \space\kappa\bm U\cdot \bm Z\cdot \bm U^T\\ ~\\~\\ 其中,\quad \bm Z=\begin{bmatrix} 0 &1&0\\ \\-1&0&0\\\\0&0&0 \end{bmatrix},\bm W=\begin{bmatrix} 0 &-1&0\\ \\1&0&0\\\\0&0&1 \end{bmatrix}
R=UWVT或R=UWTVT t∧= κU⋅Z⋅UT或t∧=− κU⋅Z⋅UT 其中,Z=⎣⎢⎢⎢⎢⎡0−10100000⎦⎥⎥⎥⎥⎤,W=⎣⎢⎢⎢⎢⎡010−100001⎦⎥⎥⎥⎥⎤
又由于其尺度的等价性,可以忽略掉常数
κ
\kappa
κ,所以我们通常又可以把平移矩阵记为:
t
∧
=
±
κ
U
⋅
Z
⋅
U
T
\bm t^ \wedge= \pm \space \sout \red \kappa \bm U\cdot \bm Z\cdot \bm U^T
t∧=± κU⋅Z⋅UT
如图所示,我们解出的值有四种组合,这里就有了四种情况,但只有一种 R R R和 t t t使得相机的深度为正值;
我们可以利用计算得到的值 R \bm R R和 t \bm t t,代入到 K ( R P w + t ) \bm{K(RP_w+t)} K(RPw+t)中进行验证,得到最优的解;
另外我们也可以利用OpenCV自带的函数进行求解,利用findEssentialMat
函数进行求解:
Mat essential_matrix;
essential_matrix = findEssentialMat ( points1, points2, focal_length, principal_point, RANSAC );
recoverPose ( essential_matrix, points1, points2, R, t, focal_length, principal_point );
也可以通过基础矩阵求解:
Mat fundamental_matrix;
fundamental_matrix = findFundamentalMat ( points1, points2, CV_FM_8POINT );
至此,我们就可以估计相机的运动了.
四、三角测量
由式10可以得到:
s
2
K
−
1
p
2
=
s
1
R
K
−
1
p
1
+
t
(15)
s_2\bm K^{-1}\bm p_2=s_1\bm{R\bm K^{-1}\bm p_1+t}\tag{15}
s2K−1p2=s1RK−1p1+t(15)
即
s
2
x
2
=
s
1
R
x
1
+
t
(16)
s_2\bm x_2=s_1\bm{R\bm x_1+t}\tag{16}
s2x2=s1Rx1+t(16)
我们只要知道了s1,就能求出s2,一般来说,由于噪声的存在,我们用的是最小二乘解,而不是零解。我们可以利用cv::triangulatePoints
函数来求解方程。
参考代码:
void triangulation (
const vector< KeyPoint >& keypoint_1,
const vector< KeyPoint >& keypoint_2,
const std::vector< DMatch >& matches,
const Mat& R, const Mat& t,
vector< Point3d >& points )
{
Mat T1 = (Mat_<float> (3,4) <<
1,0,0,0,
0,1,0,0,
0,0,1,0);
Mat T2 = (Mat_<float> (3,4) <<
R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2), t.at<double>(0,0),
R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2), t.at<double>(1,0),
R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2), t.at<double>(2,0)
);
Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );
vector<Point2f> pts_1, pts_2;
for ( DMatch m:matches )
{
// 将像素坐标转换至相机坐标
pts_1.push_back ( pixel2cam( keypoint_1[m.queryIdx].pt, K) );
pts_2.push_back ( pixel2cam( keypoint_2[m.trainIdx].pt, K) );
}
Mat pts_4d;
cv::triangulatePoints( T1, T2, pts_1, pts_2, pts_4d );
// 转换成非齐次坐标
for ( int i=0; i<pts_4d.cols; i++ )
{
Mat x = pts_4d.col(i);
x /= x.at<float>(3,0); // 归一化
Point3d p (
x.at<float>(0,0),
x.at<float>(1,0),
x.at<float>(2,0)
);
points.push_back( p );
}
}
参考文献
1.Multiple View Geometry in Computer Vision Second Edition. P258-259.
2.奇异值分解(SVD)
3.视觉SLAM十四讲—第7讲:视觉里程计
4.百度百科:实反对称矩阵