3. 直接法基础回顾:光流法、直接法对齐
聊到视觉SLAM的鲁棒性,直接法是个绕不开的话题。很多朋友一听到「直接法」就觉得头大,觉得它不如特征法稳定。其实吧,我刚开始做SLAM时也这么想。直到有一次在弱纹理场景里,特征法彻底罢工,直接法反而撑住了——嗯,从那以后我对它彻底改观了。
今天咱们就花点时间,把直接法的基础好好捋一捋。说白了,直接法就是直接利用图像的像素亮度信息来估计相机运动,而不是先提取特征点再匹配。这个思路听起来简单,但里面的门道可不少。
3.1 光流法:直接法的前身
光流法,你可以把它理解为直接法的「轻量版」。它假设同一个空间点在不同图像中的像素亮度是不变的——这就是著名的灰度不变假设。
核心公式:
I(x+dx, y+dy, t+dt) = I(x, y, t)
说白了就是:同一个点,换个位置,换个时间,亮度值不变。
把这个公式泰勒展开,忽略高阶项,我们就得到了光流约束方程:
I_x * u + I_y * v + I_t = 0
其中 I_x、I_y 是图像梯度,I_t 是时间梯度,(u, v) 就是我们要求的光流向量。
一个方程两个未知数,怎么解?我习惯用Lucas-Kanade法——假设一个窗口内的像素运动一致,然后构建超定方程组,用最小二乘法求解。
我的经验:LK光流在纹理丰富的地方效果很好,但在弱纹理区域容易漂移。我曾经在一个白墙走廊里跑光流,结果直接飞了——后来加了金字塔分层才稳住。
3.2 直接法对齐:从稀疏到稠密
光流法只估计像素的运动,而直接法对齐直接估计相机的位姿变换。两者的关系,你可以这样理解:
- 光流法:先算像素运动,再反推相机运动(两步走)
- 直接法对齐:一步到位,直接优化位姿让光度误差最小
直接法对齐的优化目标函数长这样:
min_{T} ∑ || I1(p) - I2(π(T·P)) ||²
这里 T 是相机位姿,P 是空间点,π 是投影函数。我们不断调整 T,让参考帧和当前帧的像素亮度差最小。
根据使用像素的多少,直接法分为三类:
| 类型 | 使用像素 | 计算量 | 鲁棒性 |
|---|---|---|---|
| 稀疏直接法 | 只使用角点等特征点 | 低 | 中等 |
| 半稠密直接法 | 使用梯度明显的像素 | 中 | 较高 |
| 稠密直接法 | 使用所有像素 | 高 | 高(但易受光照影响) |
我个人在实际项目中用得最多的是半稠密直接法。为什么呢?因为稠密法太慢,稀疏法又容易丢。半稠密法只选梯度大的像素参与优化,既保证了信息量,又控制了计算量。
3.3 直接法对光照的鲁棒性:优势与局限
这是直接法最让人又爱又恨的地方。咱们先说说它的优势:
优势:
- 对局部光照变化不敏感:比如场景中某个区域被阴影遮挡,只要整体亮度分布没变,直接法依然能工作
- 可以利用半像素信息:不像特征法必须找到精确的角点,直接法在纹理模糊时也能提供约束
- 在弱纹理场景中表现更好:我做过一个仓库的SLAM,地面是纯色的,特征法直接跪了,直接法靠着墙角的微弱梯度撑了下来
但是,局限也很明显:
局限:
- 对全局光照变化极其敏感:比如你从室内走到室外,亮度突然变化,直接法基本就崩了
- 灰度不变假设太强:现实中哪有完全不变的亮度?自动曝光、光源移动、反射变化...这些都是直接法的天敌
- 对运动模糊敏感:快速运动时图像模糊,像素亮度被平均了,直接法的误差函数就变得很平坦
为什么会这样?你想想看,直接法的核心假设就是「同一个点的亮度不变」。一旦这个假设被打破,整个优化就失去了依据。我在一个户外项目中就吃过这个亏——上午10点到下午2点,太阳角度变了,同一面墙的亮度差了30%,直接法直接发散。
3.4 知识体系总览
为了让你更直观地理解直接法的知识结构,我画了张图:
3.5 实战中的避坑指南
说了这么多理论,最后分享几个我在项目中踩过的坑:
避坑1:不要直接拿原始图像跑直接法。我建议先做光度标定——校正镜头渐晕和传感器响应曲线。这一步能显著提升直接法对光照变化的容忍度。
避坑2:使用鲁棒核函数(比如Huber核)。直接法的误差项里经常混入 outliers(比如运动物体、高光反射),不加核函数的话,一个异常像素就能把整个优化带偏。
避坑3:注意自动曝光。很多相机在场景变化时会自动调整曝光时间,这会导致图像亮度突变。我曾经被这个坑惨了——后来要么锁定曝光参数,要么在优化中显式建模曝光时间变化。
好了,直接法的基础就聊到这儿。记住一句话:直接法不是万能的,但在合适的场景下,它比特征法更鲁棒。关键是要理解它的假设条件,知道什么时候该用,什么时候不该用。
公众号:蓝海资料掘金营,微信deep3321