4. 光流计算方法
在无人机光流定位中,摄像头连续两帧图像之间的像素运动被转换为速度信息,而“如何从像素亮度变化中估计运动矢量”正是光流计算的核心。不同算法在稀疏/稠密、精度/速度、鲁棒性/实现复杂度上差异明显。本节围绕三类经典方法展开:Lucas-Kanade(LK)、Horn-Schunck(HS)与Farneback,并给出实现要点与选型建议。
一、共同基础:亮度恒定与光流约束
几乎所有光流算法都建立在两个假设之上:亮度恒定(同一物点在相邻帧中灰度不变)与小运动(位移足够小,可用一阶泰勒展开近似)。由此得到光流约束方程:
I(x, y, t) = I(x+u, y+v, t+1)
Ix·u + Iy·v + It = 0
其中:Ix、Iy 为图像空间梯度,It 为时间梯度,(u, v) 为待求光流矢量
该方程只有一个约束却有两个未知量,属于欠定问题。不同算法的本质区别,就在于如何补充额外约束:LK 假设局部邻域内运动一致,HS 假设全局光流平滑,Farneback 则用多项式展开近似邻域。
二、Lucas-Kanade:局部窗口最小二乘
LK 的核心思想是:在像素点周围取一个 n×n 窗口(如 15×15),假设窗口内所有像素具有相同的光流 (u, v)。于是每个像素提供一个约束方程,窗口内形成超定方程组,用最小二乘求解:
# 伪代码:LK 单层求解
for each pixel p in window:
Ix, Iy, It = gradient(p)
A.append([Ix, Iy])
b.append(-It)
(u, v) = solve_least_squares(A, b) # (AᵀA)⁻¹Aᵀb
实现要点:
- 可解性判断:AᵀA 的两个特征值都要足够大,否则窗口内纹理单一(如白墙、天空),光流不可靠。Shi-Tomasi 角点正是基于此准则。
- 金字塔分层:原始 LK 只适用于小位移。构建 3~4 层图像金字塔,从顶层粗估、逐层细化,可处理大运动。
- 窗口大小权衡:窗口越大越鲁棒,但会平滑掉运动边界;窗口越小越敏感,但易受噪声影响。
- 迭代细化:每层可迭代 3~5 次,用当前估计 warp 图像后重新计算残差。
三、Horn-Schunck:全局平滑约束
HS 方法不再假设局部一致,而是引入全局平滑约束:相邻像素的光流应尽量连续变化。它将光流求解转化为能量最小化问题:
E = ∬ [(Ix·u + Iy·v + It)² + α²(‖∇u‖² + ‖∇v‖²)] dx dy
其中 α 为平滑权重:α 越大,光流场越平滑
通过变分法得到欧拉-拉格朗日方程,再离散化为迭代公式:
u(k+1) = ū(k) - Ix·(Ix·ū(k) + Iy·v̄(k) + It) / (α² + Ix² + Iy²)
v(k+1) = v̄(k) - Iy·(Ix·ū(k) + Iy·v̄(k) + It) / (α² + Ix² + Iy²)
其中 ū、v̄ 为邻域均值
实现要点:
- 迭代次数:通常 100~500 次,次数不足则光流未收敛,次数过多则耗时。
- 平滑权重 α:α 小则保留细节但噪声大,α 大则平滑但边界模糊,需按场景调节。
- 初始化:一般从零光流开始,也可用上一层金字塔结果加速收敛。
- 边界处理:图像边缘需特殊处理,否则邻域均值会引入误差。
四、Farneback:多项式展开的稠密光流
Farneback 算法用二次多项式近似每个像素邻域的亮度分布,通过比较两帧多项式系数来估计位移。其核心步骤为:
- 对图像做多尺度高斯模糊,构建金字塔。
- 在每个像素邻域用加权最小二乘拟合二次多项式,得到系数 A、b、c。
- 假设两帧间多项式系数满足 A₂ = A₁,由 Δb = -2A d 解出位移 d。
- 在金字塔各层迭代细化,得到最终稠密光流场。
OpenCV 中可直接调用:
import cv2
flow = cv2.calcOpticalFlowFarneback(
prev, next,
None,
pyr_scale=0.5, # 金字塔缩放
levels=3, # 层数
winsize=15, # 窗口大小
iterations=3, # 每层迭代次数
poly_n=5, # 多项式邻域大小
poly_sigma=1.2, # 高斯标准差
flags=0
)
实现要点:
- poly_n 与 poly_sigma:poly_n 越大,多项式拟合越平滑,但细节丢失;poly_sigma 控制高斯权重。
- winsize:窗口越大越鲁棒,但运动边界越模糊。
- 金字塔层数:层数多可处理大位移,但计算量增加。
- 后处理:可对光流场做中值滤波,去除异常矢量。
五、算法对比与选型清单
| 算法 | 光流类型 | 核心约束 | 计算量 | 精度 | 无人机适用场景 |
|---|---|---|---|---|---|
| Lucas-Kanade | 稀疏 | 局部窗口运动一致 | 低 | 中高(角点处) | 特征点跟踪、定点悬停 |
| Horn-Schunck | 稠密 | 全局光流平滑 | 高 | 中(边界模糊) | 离线分析、稠密运动场 |
| Farneback | 稠密 | 多项式展开匹配 | 中高 | 高 | 稠密测速、避障辅助 |
选型建议:若无人机主控为 MCU 或低功耗 SoC,优先选 LK + 角点检测,配合金字塔处理大位移;若算力充足且需要稠密运动场,可选 Farneback;HS 因迭代慢、边界模糊,通常仅用于教学或离线验证。
六、常见误区与复盘
- 误区一:忽略亮度恒定假设。无人机在光照变化剧烈的场景(如从阴影飞入强光)下,光流约束失效,需先做直方图均衡或使用对光照鲁棒的描述子。
- 误区二:窗口越大越好。大窗口会平滑运动边界,导致悬停时对微小位移不敏感,建议根据飞行高度和纹理尺度动态调整。
- 误区三:只算光流不做尺度恢复。光流是像素位移,必须结合高度、焦距、IMU 才能转换为真实速度,否则定点悬停会漂移。
- 误区四:忽略异常矢量剔除。纹理重复区域会产生错误匹配,需用 RANSAC 或中值滤波剔除离群点。
复盘时建议记录:算法耗时、特征点数量、光流矢量分布、悬停漂移量,并与 IMU 数据做融合对比,逐步优化参数。