第七讲: 视觉里程计1
1. 特征点法
slam分为视觉前端和视觉后端.前端也称为视觉里程计(VO). 它根据相邻图像的信息粗略估计相机的运动,给后端提供较好的初始值.
本讲学习如果提取匹配特征点,然后估计两帧之间的相机运动和场景结构.
1.1. 特征点
图像本身是由亮度和色彩组成的矩阵.
特征点:
- 朴素角点: 简单,受环境,相机旋转等影响.
- 人工设计的特征点: 可重复性,可区别性,高效率性,本地性.
特征点是由关键点和描述子组成:
- 关键点: 图像中的位置
- 描述子: 附加信息,为了更好的区别其他点.
描述子通常是一个向量,按照某种人为设计的方式,描述了该关键点周围像素的信息.设计原则: 外观相似的特征应该有相似的描述子.
ORB(Oriented FAST and Rotated BRIEF) 是目前非常具有代表性的实时图像特征.
ORB是质量与性能较好的折中.
1.2. ORB特征
ORB由关键点和描述子组成.
关键点称为: Oriented FAST.是一种改进的FAST角点.
描述子称为: BRIEF(Binary Robust Independent Elementary Feature).
提取ORB特征点的步骤为:
- FAST角点提取: 找出图像中的角点. 相较于原版FAST,ORB中计算了特征点的主方向,为后续的BRIEF描述子增加了旋转不变性.
- BRIEF描述子: 对前一步中的特征点的周围进行描述.
FAST 关键点:
FAST是一种角点,主要检测局部像素灰度变化明显的地方.特点是速度快.
FAST特征点:⎩⎪⎪⎪⎨⎪⎪⎪⎧优点:仅比较像素间亮度的差异速度快缺点:⎩⎪⎨⎪⎧特征点很多且不确定−解决方法:指定要提取的角点数N,选取前N个具有最大响应值的点作为最终角点的合不具有方向信息−解决方法:添加旋转描述,其特征的旋转由灰度实心法实现存在尺度问题−解决方法:添加尺度描述,尺度不变性由构建图像金字塔,并在金字塔每层检验角点来实现.
质心:图像块灰度值作为质心.
操作步骤如下:
-
在一个小的图像块B中,定义图像块的矩阵为:
mpq=x,y∈B∑xpyqI(x,y),p,q={0,1}
-
通过矩可以找到图像块的质心
C=(m00m10,m00m01)
-
连接图形块的几何中心O与质心C, 得到一个方向向量OC,于是特征点的方向可以定义为:
θ=arctan(m10m01)
通过以上信息,FAST便具有了尺度与旋转的描述.提升了健壮性. 在ORB中把这种改进后的FAST称为:Oriented FAST.
BRIEF描述子:
提取关键点后对每个点计算其描述子.
BRIEF是一种二进制描述子. 例如,取关键点附近的p和q,如果p比q大,则取1,否则取0,如果去了128对这样的点,那么描述子可以用一个128位的二进制数来表示.
与原始的BRIEF相比,ORB描述子具有良好的旋转不变性.
1.3. 特征匹配
特征匹配解决了SLAM中数据关联问题,即确定当前看到的路标与之前看到的路标之间的对于关系.
通过对图像与图像之间或者图像与地图之间的描述进行准确匹配,我们可以为后续姿态估计,优化等操作减轻大量负担.
如何两个图片中特征点集合的对应关系呢?
- 暴力匹配: 对每个特征点都测量描述子的距离,然后排序,取得最近的一个作为匹配点.
描述子的距离,
对于浮点型的描述子使用欧氏距离
对于二进制类型的描述子使用汉明距离
- 快速近似最邻近匹配: 更适合与匹配点的情况.它已经集成到了opencv当中.
2. 实践: 特征提取和匹配
目前主流的几种特征提速方法在OpenCV中已经集成.
以下为openCV中图像特征提取,计算和匹配的过程.
代码见:code\第七讲
我们希望根据匹配的点对来估计相机的运动.
- 当相机为单目时,我们只知道2D的像素坐标,因而问题是根据两组2D点估计运动.该问题用
对极几何来解决.
- 当相机为双目,RGB等,即有距离信息. 那么就根据3D点估计运动. 常用
ICP来解决.
- 如果有3D点及在其他相机的投影位置,也能估计相机的运动. 该问题是通过
PnP求解.
3. D-2D:对极几何
3.1. 对极约束

在第一帧的坐标系下,设P的空间位置为;
P=[X,Y,Z]T
根据第五讲针孔相机模型,我们知道两个像素点p1,p2的像素位置为:
s1p1=KP,s2p2=K(RP+t)
K为相机的内参矩阵. R,t为相机的运动,也可以写成李代数的形式.
如果使用齐次坐标,那么上式也可以写成如下形式;
p1=KP,p2=K(RP+t)
取:
x1=K−1p1,x2=K−1p2
x1,x2是两个像素点 归一化平面的坐标.带入上式得:
x2=Rx1+t
两边同时左乘t∧(^表示将向量变成矩阵),相当于两侧同时与t做外积:
t∧x2=t∧Rx1
然后同时左乘x2T
x2Tt∧x2=x2Tt∧Rx1
因为t∧x2=0,所以上式化简为:
x2Tt∧Rx1=0
重新带入p1,p2得:
p2TK−Tt∧RK−1p1=0
以上两个式子都成为 对极约束.
它的几何意义是O1,P,O2三者共面. 対极约束中同时包含了 平移和旋转.
把中间部分记做两个矩阵:
于是进一步简化対极约束;
E=r∧R,F=K−TEK−1,x2TEx1=p2TFp1=0
対极约束简洁的给出了两个匹配点的空间位置关系. 于是相机的位姿估计可以分为以下步骤:
- 根据匹配点的像素位置求出E 或者 F
- 根据E或者F 求出 R,t
由于E和F只相差了相机内参,所以往往使用更简洁的EK
3.2. 本质矩阵
本质矩阵E=t∧R. 它是一个3×3矩阵. 从E的构造方式看,有以下几点需要注意:
- 本质矩阵由対极约束定义.由于対极约束是等式为0的,所以对E乘以任意非零常数, 対极约束仍然满足. 我们把这件事称为E在不同尺度下是等价的.
- 根据E=t∧R ,课证明本质矩阵E的奇异值必定是[σ,σ,0]T的形式. 这称为 本质矩阵的内在性质.
- 平移加旋转共有6个自由度,所以 t∧R共有6个自由度.但是由于 尺度等价性, 实际上只有5个自由度.
使用8点法求解E.
⎣⎢⎢⎢⎡u11u21u12u22⋮u18u28u11v21u12v22⋮u18v28u11u12⋮u18v11u21v12u22⋮v18u28v11v21v12v22⋮v18v28v11v12⋮v18u21u22⋮u28v21v22⋮v2811⋮1⎦⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡e1e2e3e4e5e6e7e8⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤=0
一声个方程构成了线性方程组. 它的系数矩阵由特征点位置构成,大小为8×9. e位于该矩阵的零空间中. 如果系数矩阵的秩为8,那么零空间的维数为1,也就是e构成一条线.
如果系数矩阵的秩为8,那么上述方程可以解得E的值.
接下来根据估计的本质矩阵E,恢复出相机运动R,t.这个过程由奇异值分解(SVD)得到.
E=UΣVT
U,V为正交矩阵,Σ为奇异值矩阵.
根据E的内在性质,Σ=diag(σ,σ,0)
对于任意E,存在两个可能的t,R与之对应:
t1∧=URZ(2π)ΣUT,R1=URZT(2π)VTtt2∧=URZ(−2π)ΣUT,R2=URZT(−2π)VTt
RZ(2π)表示旋转90度的旋转矩阵. 同时,由于−E等价于E,所以任意一个t取负号,会得到同样的结果. 因此,从E分解得到t,R,一个存在4种结果.
如下图;

最后还有一个问题,线性方程组求解出E后,它可能不满足E的内在性质:奇异值不为(σ,σ,0) 的形式.
对8点大求得的E进行SVD分解后,会得到奇异值矩阵Σ=diag(σ,σ,0).取(σ1⩾σ2⩾σ3):
E=Udiag(2σ1+σ2,2σ1+σ2,0)VT
最简单的方法是将奇异值取diag(1,1,0)
3.3. 单应矩阵
单应矩阵H:它描述了两个平面之间的映射关系.
单应矩阵通常扫描处于共平面上的一些点在两张图像之间的变换关系.
经过计算我们可以得到一个直接描述图像坐标p1到p2之间的变换,把中间部分记做H:
p2=Hp1
把上式展开:
⎣⎡u2v21⎦⎤=⎣⎡h1h4h7h2h5h8h3h6h9⎦⎤⎣⎡u1v11⎦⎤
在实际中通常乘以一个非零因子,使得h9=1,于是有:
u2=h7u1+h8v1+h9h1u1+h2v2+h3v2=h7u1+h8v1+h9h4u1+h5v1+h6
于是自由度为8的单应矩阵可以通过4对匹配特征点算出.即求解以下方程:
⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎛u110u120u130u140v110v120v130v140101010100u110u120u130u140v110v120v130v1401010101−u11u21−u11u21−u12u22−u12u22−u13u23−u13u23−u14u24−u14u24−v11u21−v11u21−v12u22−v12u22−v13u23−v13u23−v14u24−v14u24⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎛h1h2h3h4h5h6h7h8⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎞=⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎛u21v21u22v22u23v23u24v24⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎞
通过解线性方程来求解H矩阵. 求出单应矩阵后需要对其分解,才能得到响应的旋转矩阵R和平移向量t.过程与本质矩阵类似.
单应性的意义: 当特征点共面或者相机发生纯旋转时,基础矩阵的自由度下降,这被称为 退化. 为了避免退化现象造成的影响,通常我们会同时估计 基础矩阵F和 单应矩阵H,选择投影误差较小的那个作为最终的运动估计矩阵.
4. 实践:对极约束求解相机运动
下面练习通过本质矩阵求解相机运动. 代码见code/第七讲
5. 三角测量
在估计了相机的运动之后,我们接下来用相机的运动估计特征点的空间位置.
在单目SLAM中无法无法通过单张图片获取像素的深度信息,需要通过 三角测量来获取.
三角测量: 通过在两处观察同一个点的夹角,从而确定该点的距离.

考虑图像I1,I2,右图的变换矩阵为T. 相机光心为O1,O2. 理论上O1p1与O2p2相交于p点,但是由于噪声的存在,并不能相交.可以使用最小二乘法求解.
设x1,x2为连个特征点的归一化坐标,它们满足以下关系:
s1x1=s2Rx2+t
s1,s2表示两个特征点的深度.
对上式左乘x1∧:
s1x1∧x1=0=s2x1∧Rx2+x1∧t
可以求出s2,进而求出s1
6. 实践:三角测量
6.1. 三角测量代码
代码演示利用対极几何求解相机的位姿,通过三角化求出特征点的空间位置.
代码见code/第七讲.
6.2. 讨论
纯旋转是无法使用三角测量的,因为対极约束将永远满足.
三角测量的不确定性
三角测量的矛盾{平移太大→不确定性小→虽然不确定性小,但是外观变化大,使得特征提取和匹配变得困难平移太小→不确定性大→像素的不确定性导致深度不确定性

7. D-2D:PnP
PnP (Perspective-n-Point):是求解3D到2D点对的运动方法.它描述了当知道了n个3D空间点及投影位置时,如何估计相机的位姿.
如果两张图中一张的特征点的3D位置已知,那么只需要3对特征点来估计相机的运动.
特征点的位置估计可以由 三角化 或 RGB-D 相机的深度图确定.
PnP有很多求解方法,例如: P3P,直接线性变化(DLT),EPnP,UPnP,非线性优化等.
7.1. 直接线性优化(6对匹配点)
假设空间点P=(X,Y,Z,1)T. 在图 I1 中投影特征点为: x1=(u1,v1,1)T
相机的位姿R,t是未知的,定义一个增广矩阵表示平移和旋转:[R∣t],
sx1=[R∣t]P⇛s⎝⎛u1v11⎠⎞=⎝⎛t1t5t9t2t6t10t3t7t11t4t8t12⎠⎞⎝⎜⎜⎛XYZ1⎠⎟⎟⎞
用最后一行把s消掉,得到:
u1=t9X+t10Y+t11Z+t12t1X+t2Y+t3Z+t4u1=t9X+t10Y+t11Z+t12t5X+t6Y+t7Z+t8
我们定义T=[R∣t]的行向量为:
t1=(t1,t2,t3,t4)T,t2=(t5,t6,t7,t8)T,t3=(t9,t10,t11,t12)T,
于是约束关系可以简写成如下形式:
t1TP−t3TPu1=0t2TP−t3TPv1=0
假设一共有N个特征点(不要忘了我们要求解的是T),可以列出如下的线性方程:
⎝⎜⎜⎜⎜⎜⎛P1T0⋮PNT00P1T⋮0PNT−u1P1T−v1P1T⋮−uNPNT−vNPNT⎠⎟⎟⎟⎟⎟⎞⎝⎛t1t2t3⎠⎞=0
由于t有12维,所以至少6对匹配点可以求出t
因为旋转矩阵R∈SO(3),但是SLT求解的T并不一定满足该条件,所以对T=[R′∣t]中的R′进行QR分解(相当与将结果从矩阵空间重新投影到SE(3)流上,转化成旋转和平移两部分).
7.2. P3P(3对匹配点)
它的输入点为三对3D-2D,记3D点为A,B,C,2D点为a,b,c,另外还需要使用一对验证点D-d.
A,B,C是世界坐标系中的坐标.
一旦3D点在相机坐标系下的坐标能够算出,那么就得到了3D-3D的对应点,即把PnP问题转化成了ICP问题.
三角形存在对应关系(相似):
ΔOab−ΔOAB,ΔObc=ΔOBC,ΔOac=ΔOAC

根据余弦定理:
OA2+OB2−2OA⋅OB⋅cos(a,b)=AB2
其他善恶三角形有类似性质.
对上式除以OC2,并且记x=OA/OC,y=OB/OC,得:
x2+y2−2xycos(a,b)=AB2/OC2y2+12−2ycos(b,c)=BC2/OC2x2+12−2xcos(a,c)=AC2/OC2
记:
⎩⎪⎨⎪⎧v=AB2/OC2u=BC2/AB2w=AC2/AB2⇒{uv=BC2/OC2wv=AC2/OC2
得:
x2+y2−2xycos(a,b)=vy2+12−2ycos(b,c)=uvx2+12−2xcos(a,c)=wv
把第一个式子中的v带入到后两个中,得:
(1−u)y2−ux2−cos(b,c)y+2uxycos(a,b)+1=0(1−w)x2−wy2−cos(a,c)x+2wxycos(a,b)+1=0
该组方程最多会得到4组解,可以用验证点来得到正确的解,得到A,B,C的在相机坐标系下的3D坐标,然后根据3D-3D对求得R,t.
P3P存在的问题:
- 只利用了三组点,当配对点多于3组,利用不上多余的点.
- 如果3D点或2D点受到噪声的影响,或者存在误匹配,则算法失效.
7.3. Bundle adjustment
除了使用线性方法外,还可以把PnP问题构建成一个定义在李代数上的最小二乘问题.
前面的线性方法都是 先求相机位姿,再求空间点位置 , 而非线性优化则是把他们都看成优化变量,放在一起优化.
在PnP中,Bundle Adjustment 问题是最小化 重投影误差问题.
假设有n个三维空间点P及其投影p, 我们希望计算机位姿R,t,它的李代数表示,记为ξ.
假设空间点坐标Pi=[Xi,Yi,Zi]T,投影的像素坐标为:ui=[ui,vi]T,根据第五讲可得:
si⎝⎛uivi1⎠⎞=Kexp(ξ∧)⎝⎜⎜⎛XiYiZi1⎠⎟⎟⎞
写成矩阵形式:
siui=Kexp(ξ∧)Pi
由于相机的位姿未知以及噪声的存在,我们把误差求和构建最小二乘问题:
ξ∗=argmin21i=1∑n∥ui−si1Kexp(ξ∧)Pi∥22
该问题的误差项是像素坐标(观测到的投影坐标)与3D点按照当前估计位置进行投影得到的位置相比较得到的误差,所以称为 重投影误差
使用 李代数可以构建无约束的优化问题,很方便的通过高斯牛顿法,列文伯格-马夸尔特方法进行求解.
在求解之前我们需要每个误差项关于优化变量的导数,即 线性化:
e(x+Δx)≈e(x)+JΔx
J的形式是关键所在.可以使用数值导数,但是如果能够推导出解析形式,则我们会优先考虑解析形式.
当e为像素坐标误差,x为相机位姿,J将是一个2×6矩阵.
设P′为P在相机坐标系下坐标,并且将其前三维取出:
P′=(exp(ξ∧)P)1:3=[X′,Y′,Z′]T
那么,相机的投影模型相对于P′:
su=KP′
展开:
⎣⎡susvs⎦⎤=⎣⎡fx000fy0cxcy1⎦⎤⎣⎡X′Y′Z′⎦⎤
利用第三行消去s,得:
u=fxZ′X′+cx,v=fyZ′Y′+cy
求误差时,可以把u,v与实际测量值比较,求差.
定义了中间变量之后,对ξ∧左乘扰动量δξ,然后考虑e的变化关于扰动量的导数.利于链式法则:
∂δξ∂e=δξ→0limδξe(δξ⊕ξ)=∂P′∂e∂δξ∂P′
⊕表示李代数上左乘扰动.
第一项是误差关于投影点的导数.
∂P′∂e=−[∂X′∂u∂X′∂v∂Y′∂u∂Z′∂u∂Y′∂v∂Z′∂v]=−[Z′fx00Z′fy−Z′2fxX′−Z′2fyY′]
第二项为变换后的点关于李代数的导数:
∂δξ∂P′=∂δξ∂(TP)=(TP)⊙=[I0T−P′∧0T]
取前三维:
∂δξ∂P′=[I−P′∧]
两式相乘可以得到一个2×6的雅克比矩阵:
∂δξ∂e=−[Z′fx00Z′fy−Z′2fxX′−Z′2fyY′−Z′2fxX′Y′−fy−Z′2fyY′2fx+Z′2fxX2Z′2fyX′Y′−Z′fxY′Z′fyX′]
这个雅克比矩阵描述了 重投影误差关于 相机位姿李代数 的一阶变化关系.
前面的负号由于误差是由 观测值减预测值定义的, 如果是预测值减观测值,那么可以不加负号,
如果se(3) 定义方式是旋转在前,平移在后,那么只需要把前三列与后三列置换
除了优化位姿,还希望优化空间点位置,因此需要讨论e关于空间点P的导数:
∂P∂e=∂P′∂e∂P∂P′
因为:
P′=exp(ξ∧)P=RP+t
所以:
∂P∂e=−[Z′fx00Z′fy−Z′2fxX′−Z′2fyY′]R
现在我们有了 观测相机方程关于 相机位姿 与 特征点 的两个导数矩阵.他们能够在优化过程中提供梯度方向.
8. 实践:求解UPnP
8.1. 使用ePnP求解
使用openCV提供的EPnP求解PnP问题,然后通过g2o对计算结果进行优化.
代码见code/第七讲/
8.2. 使用BA优化
BA(Bundle Adjustment)
可以使用Ceres或g2o库实现优化.
9. D-3D:ICP
假设有一组匹配好的3D点:
P={p1,⋯,pn},P′={p1′,⋯,pn′}
现在需要欧式变换R,t,使得:
∀i,pi=Rpi′+t
这个问题可以用迭代最近点来求解(ICP,Iterative Closest Point).
仅考虑两组3D点时和相机并没有关系. 因此,在激光SLAM中也会碰到ICP,不过由于激光数据特征不够丰富,我们无法知道两个点集之间的匹配关系,只能认为距离最近的两个点为同一个点,所以这个方法称为迭代最近点.
ICP的求解也分为两种方式:利用线性代数求解(SVD),以及利用非线性优化方式求解(BA).
9.1. SVD
根据上一节中的ICP问题,我们定义第i对点的误差项为:
ei=pi−(Rpi′+t)
然后,构建最小二乘问题,求使误差平方和达到极小的R,t
R,tminJ=21i=1∑n∥pi−(Rpi′+t))∥22
定义两组点的质心:
p=21i=1∑n(pi),p′=n1i=1∑n(pi′)
… 推到过程略
优化目标函数可以简化为:
R,tminJ=21i=1∑n∥pi−p−R(pi′−p′)∥2+∥p−Rp′−t∥2
观察发现左右两项中,左边只有R,右边有R,t,但是只和质心相关. 只要计算出R,令第二项为0就可以计算出t.
ICP可以分为以下三个步骤:
-
计算两组点的质心p,p′,然后计算每个点的去质心坐标: p
qi=pi=p,qi′=pi′−p′
-
根据以下的优化问题计算旋转矩阵:
R∗=argRmin21i=1∑n∥pi−Rqi′∥2
-
根据第二步计算出的R,计算times
t∗=p−Rp′
所以我们重点关注的是R的计算.将R的误差项展开:
21i=1∑n∥pi−Rqi′∥2=21i=1∑nqiTqi+qi′TRTRqi′−2qiTRqi′
RTR=I,所以前两项与R无关,所以实际优化目标函数为:
n∑n−2qiTRqi′=i=1∑n−tr(Rqi′qiT)=−tr(Ri=1∑nqi′qiT)
接下来通过SVD解出最优的R.
先定义矩阵:
W=i=1∑nqi′T
W是一个3×3矩阵,对W进行SVD分解,得:
W=UΣVT
Σ 为奇异值组成的对角阵, 对角线元素从大到小排列, 而U和V为对角阵.
当W满秩:
R=UVT
解得R后,即可求出t.
9.2. 非线性优化
用非线性优化求解ICP,以迭代的方式求解最优值. 该方法与PnP方法类似. 以李代数表示位姿,目标函数可以写成:
ξmin=21i=1∑n∥pi−exp(ξ∧)pi′∥22
使用李代数的扰动模型:
∂δξ∂e=−(exp(ξ∧)pi′)⊙
在非线性优化中只需要不断迭代就可以找到极小值.
ICP问题存在唯一解和无穷多解的情况. 在唯一解情况下,极小值的解即是全局最优解,这种情况下ICP求解可以选定任意的初始值.
混合使用PnP和ICP优化:对于深度已知的特征点,建模他们的3D-3D误差;对于深度未知的特征点,建模它们的3D-2D的重投影误差.
10. 实践:求解ICP
代码见code/第七讲
10.1. SVD方法
10.2. 非线性优化方法