一、直接法的引出(8.1)
1)回顾特征点法(Feature-Based Method)
前面讲的视觉里程计(VO)通常是:
提取特征点(FAST、ORB、SIFT...)
描述子匹配
根据匹配点估计相机运动
这种方法优点是成熟、稳定,但对特征依赖强:
弱纹理区域(白墙、天空)→ 特征少
光照变化大 → 描述子不稳定
计算量大(描述子计算、匹配)
2)直接法的核心思想
**直接法(Direct Method)** 不依赖特征点和描述子,而是:
利用像素亮度本身,来估计相机运动
假设前提(非常关键):
灰度不变假设
同一空间点在各个图像中灰度相同
也就是说:
特征法是**"先找点,再算运动"**
直接法是"直接通过亮度误差最小化,求运动"
二、光流(Optical Flow)(8.2)
1)什么是光流?
光流 = 像素在图像中的运动
比如:
相机在动
同一个像素在两张图中位置变了
这个位移就是光流
形式化表达:
u=(u,v)
表示像素的运动向量。
2)光流的基本假设
(1)灰度不变假设(Brightness Constancy)
I(x,y,t)=I(x+u,y+v,t+1)意思是:
同一个点的亮度在时间变化时保持不变。
(2)小运动假设(Small Motion)
光流不能太大,否则线性近似失效。
三、Lucas-Kanade 光流(8.2.1)
这是最经典的光流算法之一。
1)基本思路
LK 光流假设:
在一个小窗口内,所有像素具有相同的运动
2)数学推导(直观版)
对灰度不变假设做泰勒展开:
I(x+u,y+v,t+1)≈I(x,y,t)+Ixu+Iyv+It令误差为 0,得到:
Ixu+Iyv=−It这里:
Ix,Iy:图像梯度
It:时间梯度
u,v:光流(未知)
3)为什么需要多个像素?
一个像素只能提供 1 个方程,但有 2 个未知数(u, v)。
👉 所以 LK 方法在一个窗口内堆叠多个像素,形成最小二乘问题:
u,vmin∑(Ixu+Iyv+It)2
4)LK 光流的适用条件
✅ 优点:
快速
简单
实时性好
❌ 缺点:
大运动容易失败
纹理少的区域不可靠
易受遮挡影响
一、直接法的推导(8.4.1)
1)直接法要解决的问题
特征法的流程是:
特征点 → 匹配 → 几何估计
而直接法跳过"匹配",直接问:
假设一个相机运动,能不能让投影后的像素亮度误差最小?
2)基本符号设定
当前帧:I
参考帧:Iref
像素坐标:u=(x,y)⊤
深度:d
相机内参:K
3)空间点到像素的投影关系
参考帧中的一个 3D 点:
p=dK−1u~经过相机运动 T后,投影到当前帧:
u′=π(T⋅p)其中 π是投影函数。
4)光度误差(Photometric Error)
直接法的目标函数:
E(T)=u∑∥Iref(u)−I(u′)∥2含义:
如果相机位姿 T正确
那么同一个 3D 点在不同图像中亮度应相同
误差来自位姿不准确
5)优化问题
直接法本质上是一个非线性最小二乘问题:
TminE(T)用高斯牛顿 / LM 算法迭代求解。
6)雅可比推导(重点)
残差对位姿的雅可比:
∂T∂r=∂u′∂I⋅∂p′∂u′⋅∂T∂p′分别对应:
图像梯度
投影雅可比
位姿雅可比
二、直接法的讨论(8.4.2)
1)直接法 vs 特征法
方面 特征法 直接法 是否需要特征 ✅ ❌ 是否依赖匹配 ✅ ❌ 灰度不变假设 弱 强 弱纹理表现 差 较好 计算量 中等 较高 鲁棒性 较强 较敏感
2)直接法的优点
✅ 不需要特征提取和匹配
✅ 可用更多像素(稀疏 / 半稠密 / 稠密)
✅ 对弱纹理场景更友好
3)直接法的缺点
❌ 强烈依赖灰度不变假设
❌ 易受光照、曝光变化影响
❌ 容易陷入局部极小值
❌ 大运动容易失败
4)直接法的分类
按使用的像素数量分为:
稀疏直接法(Sparse Direct)
- 只用少数关键点
半稠密直接法(Semi-Dense Direct)
- 用梯度明显的像素
稠密直接法(Dense Direct)
- 用几乎全部像素
三、一句话总结本小节
直接法通过最小化光度误差来估计相机运动,核心是"不用匹配,只信亮度",但对光照和运动非常敏感。
一、稀疏直接法(8.5.1)
1)为什么先做"稀疏"?
直接法最怕两件事:
计算量大
梯度不明显导致优化发散
👉 稀疏直接法的思路是:
只在"可靠像素"上做直接法,其余不管
这些"可靠像素"通常来自:
FAST / Shi-Tomasi 角点
梯度较大的点
2)稀疏直接法的流程
在第一帧选角点
给每个角点反投影出 3D 点(用深度图)
在下一帧中,根据当前位姿预测像素位置
构建光度误差
用高斯牛顿 / LM 优化位姿
✅ 优点:快、稳定
❌ 缺点:信息量少,不如半稠密/稠密精确
二、定义直接法的边(8.5.2)
这一节本质上是:把直接法写成图优化问题
1)什么是"边"?
在 g2o / Ceres 里:
节点(Vertex):相机位姿
边(Edge):误差项
对于直接法:
- 一条边 = 一个像素的光度误差
2)边的误差模型
误差函数:
e=Iref(u)−I(π(T⋅p))这条边连接:
一个位姿节点
一个 3D 点(有时隐含在参考帧中)
3)雅可比怎么来?
前面推导过:
∂T∂e=∂u∂I⋅∂p∂u⋅∂T∂p在图优化里:
框架负责求导
你只需要告诉它残差怎么算
👉 这就是为什么书中会专门写一个
EdgeSE3ProjectDirect。
三、使用直接法估计相机运动(8.5.3)
1)整体流程(非常关键)
for 每一对相邻帧: 1. 选取参考帧中的像素 2. 反投影得到 3D 点 3. 根据当前位姿预测像素位置 4. 构建光度误差边 5. 加入优化器 6. 优化位姿 7. 更新当前位姿
2)几个工程细节(书里容易忽略)
深度有效性检查
- 深度 ≤ 0 的点直接丢弃
投影点越界检查
- 投影到图像外就删掉
光度误差阈值
- 误差太大的边当作 outlier 去掉
金字塔(可选)
- 多尺度直接法能提高大运动鲁棒性
四、半稠密直接法(8.5.4)
1)为什么要"半稠密"?
稀疏直接法只用角点:
点太少
位姿估计噪声大
稠密直接法:
计算量爆炸
很多像素梯度几乎为 0,没用
👉 半稠密 = 折中方案
2)半稠密的选择标准
只保留:
图像梯度大的像素
深度可靠的像素
公式直觉:
∣∇I∣>τ这样:
优化有意义
计算量可控
3)半稠密的效果
✅ 比稀疏法精度高
✅ 比稠密法快很多
✅ 是目前直接法 SLAM(如 LSD-SLAM、DSO)的主流选择
五、直接法的讨论(8.5.5)
1)直接法对什么最敏感?
曝光变化
自动增益(AGC)
快门时间变化
👉 实际工程中经常要:
固定曝光
关闭自动白平衡
使用光度标定(photometric calibration)
2)直接法适合什么场景?
✅ 室内 RGB-D
✅ 纹理较弱环境
✅ 实时系统(配合半稠密)
❌ 室外强光变化
❌ 动态物体多
❌ 高速运动
六、直接法优缺点总结(8.5.6)
✅ 优点
不需要特征提取和匹配
可利用大量像素信息
对弱纹理场景友好
可实现半稠密 / 稠密建图
❌ 缺点
强依赖灰度不变假设
对光照极度敏感
容易局部极小
大运动鲁棒性差
实现复杂度高
七、一句话收束整章
特征法稳健但依赖特征,直接法高效但挑剔光照;
工程上,稀疏直接法保速度,半稠密直接法保精度。
K 光流 → 稀疏直接法 → 半稠密直接法:一条逻辑演进线
起点:同一个核心假设
灰度不变假设
同一个空间点在各帧图像中亮度不变
所有方法都建立在这个假设之上,区别只在于:
如何用它
用在哪些像素上
如何保证它成立
第一步:LK 光流 ------ "我只关心像素怎么动"
核心想法
我不关心这个像素是哪里的 3D 点,我只想知道它在下一帧去哪了。
做法
在图像平面直接估计像素位移 (u,v)
假设一个小窗口内所有像素运动一致
解最小二乘问题
本质
✅ 2D → 2D 问题
❌ 不涉及 3D 结构
❌ 不知道深度,无法恢复真实尺度(单目)
局限性
只用了很少的角点
大运动容易失败
没有显式建模相机运动
👉 LK 光流 = 直接法的"2D 特例"
第二步:稀疏直接法 ------ "我知道像素是谁,我想求相机运动"
动机
LK 光流有两个痛点:
不知道深度
不知道相机到底怎么动
改进思路
如果有深度(RGB-D),我就可以把像素反投影成 3D 点,然后直接优化相机位姿。
做法
在参考帧选角点
用深度图反投影得到 3D 点
假设一个相机位姿 T
把 3D 点投影到当前帧
最小化光度误差
E(T)=∑∥Iref(u)−I(π(Tp))∥2本质
✅ 2D → 3D → 2D + 位姿优化
✅ 不再只是"像素在动",而是"相机在动"
进步点
显式估计相机运动
可用于 VO
不再依赖匹配描述子
遗留问题
仍然只用角点
信息利用率低
位姿估计噪声较大
👉 稀疏直接法 = LK 光流 + 深度 + 位姿优化
第三步:半稠密直接法 ------ "不只角点,我要所有'有用'的像素"
动机
稀疏直接法太"吝啬":
大部分像素被浪费
位姿约束不足
但直接用所有像素又太"奢侈":
梯度为 0 的像素没用
计算量爆炸
关键观察
只有图像梯度大的地方,光度误差对位姿才敏感
改进思路
不用角点,也不用全图,只用"有梯度的像素"。
做法
在参考帧中筛选:
∣∇I∣>τ
同时要求深度有效
对这些像素统一构建光度误差
联合优化相机位姿
本质
✅ 从"几何显著性"升级为"光度显著性"
✅ 像素选择标准从"是不是角点"变成"有没有信息量"
优势
约束更强 → 位姿更准
计算量可控
更接近现代直接法 SLAM(DSO / LSD-SLAM)
👉 半稠密直接法 = 稀疏直接法 + 梯度筛选 + 大规模像素利用
一条统一的演进公式
阶段 输入 优化对象 像素策略 本质 LK 光流 2D 图像 像素位移 角点 + 窗口 2D→2D 稀疏直接法 RGB-D 相机位姿 角点 2D→3D→2D 半稠密直接法 RGB-D 相机位姿 梯度显著像素 信息驱动
用一句话串起三者
LK 光流只问"像素去哪了";稀疏直接法开始问"相机怎么动了";半稠密直接法则进一步问"哪些像素值得我问"。
再往后一步(帮你建立体系感)
半稠密 → 稠密直接法
用几乎所有像素
计算量大,DTAM 为代表
DSO(Direct Sparse Odometry)
表面叫"Sparse"
实际是"高密度的梯度点 + 滑动窗口 + 光度标定"
是现代直接法的集大成者
本文系统梳理了视觉SLAM中的直接法,包括其核心思想、数学推导与实现方法。主要内容分为三部分:首先介绍直接法原理,即通过最小化光度误差估计相机运动,摆脱对特征点的依赖;其次详细推导LK光流和稀疏/半稠密直接法的数学模型,分析其优缺点及适用条件;最后总结直接法的演进路径------从LK光流(2D运动估计)到稀疏直接法(3D位姿优化),再到半稠密直接法(梯度显著像素筛选),形成了一套基于灰度不变假设的完整技术路线。直接法对光照敏感但能有效处理弱纹理场景,与特征点法形成优势互补。