视觉里程计-直接法
基于《视觉SLAM14讲》以及深蓝学院SLAM课程的学习笔记
引出
特征点法的缺点
- 耗时
- 丢弃了大部分可能有用的信息
- 运动到特征缺失的地方会失效
解决方法:
- 保留特征点,但只计算关键点,不计算描述子:光流法(Optical Flow)
- 只计算关键点,不计算描述子:直接法(Direct Method)
2D光流
光流是一种描述像素随时间在图像之间运动的方法。随着时间的流逝,同一个像素会在图像中运动,而我们希望追踪它的运动过程。
计算部分像素运动称为稀疏光流(如LK光流),计算所有像素运动为稠密光流
Lucas-Kanade光流
认为相机图像随时间变化,图像可以看作时间与位置的函数
I
(
t
)
\boldsymbol I(t)
I(t),在
t
t
t时刻,位于
(
x
,
y
)
(x,y)
(x,y)的像素,灰度可以写成:
I
(
x
,
y
,
t
)
\boldsymbol I(x,y,t)
I(x,y,t)
希望估计空间点在其他时刻图像中的位置,引入灰度不变假设:同一个空间点的像素灰度值,在各个图像中是固定不变的。
有方程:
[
I
x
I
y
]
[
u
v
]
=
−
I
t
\begin{bmatrix}\boldsymbol I_x&\boldsymbol I_y\end{bmatrix}\begin{bmatrix}u\\v\end{bmatrix}=-\boldsymbol I_t
[IxIy][uv]=−It
式中,
I
x
=
d
I
d
x
,
I
y
=
d
I
d
y
\boldsymbol I_x=\frac{d\boldsymbol I}{dx},\boldsymbol I_y=\frac{d\boldsymbol I}{dy}
Ix=dxdI,Iy=dydI为图像在一点
x
,
y
x,y
x,y方向的梯度,
I
t
\boldsymbol I_t
It为图像灰度对时间的变化量,
u
=
d
x
d
t
,
v
=
d
y
d
t
u=\frac{dx}{dt},v=\frac{dy}{dt}
u=dtdx,v=dtdy为像素在两个方向的运动速度。要计算
u
,
v
u,v
u,v,需要引入额外约束。
因此,假设某一窗口内的像素具有相同的运动。考虑大小为
w
×
w
w\times w
w×w的窗口,该窗口内像素有同样的运动,因此有
w
2
w^2
w2个方程:
[
I
x
I
y
]
k
[
u
v
]
=
−
I
t
k
,
k
=
1
,
…
,
w
2
\begin{bmatrix}\boldsymbol I_x&\boldsymbol I_y\end{bmatrix}_k\begin{bmatrix}u\\v\end{bmatrix}=-\boldsymbol I_{tk},\qquad k=1,\dots,w^2
[IxIy]k[uv]=−Itk,k=1,…,w2
记
A
=
[
[
I
x
I
y
]
1
⋮
[
I
x
I
y
]
k
]
,
b
=
[
I
t
1
⋮
I
t
k
]
\boldsymbol A=\begin{bmatrix}\begin{bmatrix}\boldsymbol I_x&\boldsymbol I_y\end{bmatrix}_1\\\vdots\\\begin{bmatrix}\boldsymbol I_x&\boldsymbol I_y\end{bmatrix}_k\end{bmatrix},\boldsymbol b=\begin{bmatrix}\boldsymbol I_{t1}\\\vdots\\\boldsymbol I_{tk}\end{bmatrix}
A=⎣
⎡[IxIy]1⋮[IxIy]k⎦
⎤,b=⎣
⎡It1⋮Itk⎦
⎤
于是整个方程为
A
[
u
v
]
=
−
b
\boldsymbol A\begin{bmatrix}u\\v\end{bmatrix}=-\boldsymbol b
A[uv]=−b
这是一个超定线性方程,可以求最小二乘解:
[
u
v
]
∗
=
−
(
A
T
A
)
−
1
A
T
b
\begin{bmatrix}u\\v\end{bmatrix}^*=-(\boldsymbol A^T\boldsymbol A)^{-1}\boldsymbol A^T\boldsymbol b
[uv]∗=−(ATA)−1ATb
得到了像素在图像间的运动速度 u , v u,v u,v,从而可以估计某块像素在若干个图像中出现的位置。
单层光流与多层光流
把光流看成一个优化问题:通过最小化灰度误差估计最优的像素偏移。其具体函数实现中的优化问题为:
min
Δ
x
,
Δ
y
∥
I
1
(
x
,
y
)
−
I
2
(
x
+
Δ
x
,
y
+
Δ
y
)
∥
2
2
\underset{\Delta x,\Delta y}{\min}\Vert\boldsymbol I_1(x,y)-\boldsymbol I_2(x+\Delta x,y+\Delta y)\Vert_2^2
Δx,Δymin∥I1(x,y)−I2(x+Δx,y+Δy)∥22
如果相机运动较快,两张图像差异较明显,那么单层图像光流法容易达到一个局部极小值。可以引入图像金字塔来改善。在计算光流时,先从顶层的图像开始计算,然后把上一层的追踪结果,作为下一层的初始值。也称为**由粗到精(Coarse-to-fine)**的光流。
LK光流跟踪能够直接得到特征点的对应关系。这个对应关系就像是描述子的匹配,只是光流对图像的连续性和光照稳定性要求更高一些。我们可以通过光流跟踪的特征点,用PnP、ICP或对极几何来估计相机运动。
如果角点提的位置不好,光流也容易跟丢或给出错误的结果。
直接法
直接法根据像素的亮度信息估计相机的运动,可以完全不用计算关键点和描述子。
相比于光流法和特征点法,知道点之间的匹配关系,直接法通过优化相机位姿来寻找点的位置。最小化的是两个点像素之间的亮度误差。
根据当前相机位姿估计值和
p
1
\boldsymbol p_1
p1来寻找
p
2
\boldsymbol p_2
p2,直接法通过最小化光度误差来优化相机的位姿,使得
p
1
\boldsymbol p_1
p1和
p
2
\boldsymbol p_2
p2差异尽可能小:
e
=
I
1
(
p
1
)
−
I
2
(
p
2
)
e=\boldsymbol I_1(\boldsymbol p_1)-\boldsymbol I_2(\boldsymbol p_2)
e=I1(p1)−I2(p2)
式中,
p
1
=
[
u
v
1
]
1
=
1
Z
1
K
P
p
2
=
[
u
v
1
]
2
=
1
Z
2
K
(
R
P
+
t
)
\boldsymbol p_1=\begin{bmatrix}u\\v\\1\end{bmatrix}_1=\frac{1}{Z_1}\boldsymbol K\boldsymbol P\\ \boldsymbol p_2=\begin{bmatrix}u\\v\\1\end{bmatrix}_2=\frac{1}{Z_2}\boldsymbol K(\boldsymbol R\boldsymbol P+\boldsymbol t)
p1=⎣
⎡uv1⎦
⎤1=Z11KPp2=⎣
⎡uv1⎦
⎤2=Z21K(RP+t)
基于灰度不变假设。优化目标为误差的二范数:
min
T
J
(
T
)
=
∥
e
∥
2
\underset{\boldsymbol T}{\min}J(\boldsymbol T)=\Vert e\Vert^2
TminJ(T)=∥e∥2
对
N
N
N个空间点
P
i
\boldsymbol P_i
Pi,有
min
T
J
(
T
)
=
∑
i
=
1
N
e
i
T
e
i
,
e
i
=
I
1
(
p
1
,
i
)
−
I
2
(
p
2
,
i
)
\underset{\boldsymbol T}{\min}J(\boldsymbol T)=\sum^N_{i=1}e_i^Te_i,\quad e_i=\boldsymbol I_1(\boldsymbol p_1,i)-\boldsymbol I_2(\boldsymbol p_2,i)
TminJ(T)=i=1∑NeiTei,ei=I1(p1,i)−I2(p2,i)
引入中间变量,分别是
P
P
P在第二个相机坐标系下的坐标
q
\boldsymbol q
q和像素坐标
u
\boldsymbol u
u:
q
=
T
P
u
=
1
Z
2
K
q
\boldsymbol q=\boldsymbol T\boldsymbol P\\ \boldsymbol u=\frac{1}{Z_2}\boldsymbol K\boldsymbol q
q=TPu=Z21Kq
考虑李代数的左扰动模型,推导出误差关于李代数的雅可比矩阵:
J
=
−
∂
I
2
∂
u
∂
u
∂
δ
ξ
\boldsymbol J = -\frac{\partial\boldsymbol I_2}{\partial\boldsymbol u}\frac{\partial\boldsymbol u}{\partial\delta\boldsymbol\xi}
J=−∂u∂I2∂δξ∂u
其中,
δ
ξ
\delta\boldsymbol\xi
δξ是
T
\boldsymbol T
T的左扰动。
∂
I
2
∂
u
\frac{\partial\boldsymbol I_2}{\partial\boldsymbol u}
∂u∂I2为
u
\boldsymbol u
u处的像素梯度。
∂
u
∂
δ
ξ
=
∂
u
∂
q
∂
q
∂
δ
ξ
=
[
f
x
Z
0
−
f
x
X
Z
2
f
x
X
Y
Z
2
f
x
+
f
x
X
2
Z
2
−
f
x
Y
Z
0
f
y
Z
−
f
y
Y
Z
2
−
f
y
−
f
y
Y
2
Z
2
f
y
X
Y
Z
2
f
y
X
Z
]
\frac{\partial\boldsymbol u}{\partial\delta\boldsymbol\xi}=\frac{\partial\boldsymbol u}{\partial\boldsymbol q}\frac{\partial\boldsymbol q}{\partial\delta\boldsymbol\xi}=\begin{bmatrix}\frac{f_x}{Z}&0&-\frac{f_xX}{Z^2}&\frac{f_xXY}{Z^2}&f_x+\frac{f_xX^2}{Z^2}&-\frac{f_xY}{Z}\\0&\frac{f_y}{Z}&-\frac{f_yY}{Z^2}&-f_y-\frac{f_yY^2}{Z^2}&\frac{f_yXY}{Z^2}&\frac{f_yX}{Z}\end{bmatrix}
∂δξ∂u=∂q∂u∂δξ∂q=[Zfx00Zfy−Z2fxX−Z2fyYZ2fxXY−fy−Z2fyY2fx+Z2fxX2Z2fyXY−ZfxYZfyX]
直接法的讨论
从直接法的推导可见,需要已知空间点 P P P的位置。根据 P P P的来源可以将直接法分为:
- 稀疏直接法: P P P来自于稀疏关键点,不必计算描述子,速度最快
- 半稠密(Semi-Dense)直接法:只使用带有梯度的像素点(因为梯度像素为0时,整项雅可比矩阵就为0,不会对计算运动增量有任何贡献)
- 稠密直接法:需要计算所有像素,需要GPU加速计算