1. 直接法的引出

虽然特征点法是现在主流的方法,但随着算法的发展直接法一定程度上可以和特征点法平分秋色。特征点法具有一些缺点:

  1. 关键点的提取和描述子的计算非常耗时
  2. 使用特征点就会忽略非特征点的信息,可能有用的信息
  3. 当相机运动到特征缺失的地方比如一道白墙,就找不到足够的匹配点计算相机运动

对于特征点法,解决的思路有:

  1. 使用光流法(optical flow),保留特征点,只计算关键点,不计算描述子。光流的计算小于描述子和匹配的计算时间。估计相机运动时仍使用对极几何或PNP算法。提取的关键点需要有可区别性。
  2. 使用直接法(direct method),只计算关键点,不计算描述子,计算特征点在下一时刻图像中的位置。提取的关键点不要求可区别性,甚至可以随机。根据图像像素灰度信息同时估计相机运动和点的投影

区别:

  • 特征发通过最小化投影误差(Reprojection Error)优化相机运动,是像素坐标距离
  • 直接法通过最小化光度误差(Photometric Error)求得相机运动以及点的投影,是像素值差距

    2. 2D光流

    直接法是由光流法演变而来的。光流法只描述了像素在图像中的运动,而直接法附带了一个相机运动模型。
    光流法分为:

  • 稀疏光流:Lucas-Kanade(LK光流),计算部分像素运动

  • 稠密光流:Horn-Schunck,计算所有像素运动

光流法的基本假设是灰度不变假设:同一个空间点的像素灰度值,在各个图像中是固定不变的。
推导过程:

  1. 构建灰度不变假设关系式:第8讲 视觉里程计2 光流法/直接法 - 图1
  2. 对左边进行泰勒展开,保留一阶项
  3. 因为灰度不变假设,使得一阶导数项等于0
  4. 两边同时除以dt,得到像素在x和y轴上的运动速度u,v,像素在x,y方向上的提取Ix,Iy,灰度相对于时间的变化量
  5. 构建出了:梯度 × 运动速度 = 图像灰度时间变化量 的关系式
  6. 在LK光流中,假设某一个窗口内的像素都具有相同的运动即满足这个关系式
  7. 既可以构建w x w个这样的关系式。然后通过最小二乘法求解u,v

再具体使用是,可以自己编写单层光流或者多层光流(图像金字塔由粗到精),或者直接使用OpenCV的函数cv::calcOpticalFlowPyrLK,提供前后两张图像以及对应的特征点(第一张图的特征点),即可得到追踪后的点(第二张图的匹配点)。可以根据status变量判断是否追踪到

3. 直接法

光流法,首先追踪特征点的位置,再根据这些位置确定相机的运动。two-stage方案很难保证全局最优。

直接法的思路是,假设认为相机右转了15°,我再根据这个15°作为初始值的假设,调整计算结果。

在直接法中,由于没有特征匹配,我们无从知道哪一个p2和p1对应这同一个点。直接法的思路是根据当前相机的位姿估计值寻找p2的位置,但若相机位姿不够好,p2的外观和p1会有明显差别。于是为了减小这个差别,我们优化相机的位姿,来寻找与p1更相似的p2。这就可以通过求解一个优化问题解决,即最小化光度误差。(这里所说的相机位姿,应该是以相机1为基础的变换矩阵,即T21,代码也是这么写的)

推导过程:

  1. 构建最小化光度误差,即误差=像素1的值 - 像素2的值
  2. 用高斯牛顿法或列文伯格法求解
  3. 构建像素2的坐标和空间点相机坐标系的关系式(相机坐标系->像素)
  4. 对误差做关于作扰动模型李代数的求导
  5. 链式法则展开
  6. 分别推导,得到一个2 x 6的矩阵
  7. 最后的一阶导数雅可比矩阵就是u处的像素梯度和2x6矩阵的乘积
  8. 知道一阶导数矩阵后,就可以用高斯牛顿法和列文伯格法迭代求解

3.1 直接法的讨论

前面所讨论的空间点P是一直的。可能由RGBD或者双目相机获得。但是在单目相机中,这个深度有很大的不确定性。根据P的来源,可以把直接法做一下分类:

  1. P来自稀疏关键点,为稀疏直接法。这种稀疏直接法不必计算描述子,速度最快,但只能计算稀疏的重构
  2. P来自部分像素。如果像素梯度为0,那么整个雅可比矩阵就为0,不会对计算运动增量有任何贡献。因此,可以考虑带有梯度的像素点。这称为半稠密(semi-dense)的直接法;
  3. P为所有的像素,称为稠密直接法。需要GPU加速

相比较于特征点法,直接法完全依靠优化来求解相机位子。从式中可以看到,像素梯度引导着优化的方向。如果想要得到正确的优化结果,就必须保证大部分像素梯度能够把优化引导到正确的方向。并且,优化算法不能只考虑单个像素,还要考虑其他所有像素,以此给出正确的方向,使得误差变小。

但实际上,直接法的梯度是直接由图像梯度确定的,因此我们必须保证沿着图像梯度走,灰度误差会下降,但是图像通常是一个很强烈的非凸函数(凸函数:任意两点的向线段都在集合内),我们很容易陷入由于图像的非凸性而产生的一个局部极小值中,无法继续优化。只有当相机运动很小,图像没有很强的非凸性,直接法才成立。

在例程中,我们计算的是单个像素之间的误差。然而单个像素没有什么区别性。所以我们有时会用晓得图像块patch,并且使用更复杂的差异度量方式(而不是直接像素值相减),例如归一化相关性(normalized cross correlation,NCC)等。

4. 直接法优缺点总结

直接法优点:

  • 省去计算特征点,描述子的时间
  • 只要求,有像素梯度即可,不需要特征点。这样子,直接法可以再特征缺失的场合下使用(比如一面白墙)
  • 可以构建半稠密乃至稠密的地图,这是特征点无法做到的

缺点也很明显:

  • 非凸性。直接法完全依靠梯度搜索(一个位置沿着各个方向搜索),降低目标函数来计算相机位姿。其目标函数中需要取像素点的灰度值,而图像是强烈非凸的函数。这使得优化算法容易进入局部最小。针对于此,金字塔的引入可以在一定程度上减小非凸性的影响。
  • 单个像素没有区分度。因为相似的像素太多了。直接法在选点较少的时候表现明显下降,通常建议用500个点以上
  • 灰度值不变是很强的假设。如果相机是自动曝光的,图像整体会变白或者变黑。特征法对光照具有一定的容忍性,而直接法由于计算灰度间的差异,整体灰度变化会破坏灰度不变假设,使得算法失败。