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) 局部窗口 · 稀疏光流 假设:窗口内运动一致 最小二乘求解 (u,v) A·[u v]ᵀ = b AᵀA 可逆时求解 金字塔解决大位移 优点:快、特征点友好 缺点:纹理弱处失效 适用:角点跟踪、稀疏 Horn-Schunck(HS) 全局平滑 · 稠密光流 假设:光流场全局平滑 最小化能量泛函 E = ∫(Ix u+Iy v+It)² + α²(|∇u|²+|∇v|²) 迭代求解欧拉-拉格朗日 优点:稠密、平滑连续 缺点:慢、边界模糊 适用:稠密运动场分析 Farneback 多项式展开 · 稠密光流 假设:邻域可用二次多项式 近似 f(x) ≈ xᵀAx+bᵀx+c 两帧多项式系数匹配 A₂ = A₁ Δb = -2A d 求位移 d 优点:稠密、精度高 缺点:计算量较大 适用:无人机稠密测速

二、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 图像后重新计算残差。
在无人机定点悬停中,LK 常用于跟踪地面特征点(如角点、标记点),配合 IMU 做尺度恢复,计算量小,适合嵌入式实时运行。

三、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 次,次数不足则光流未收敛,次数过多则耗时。
  • 平滑权重 α:α 小则保留细节但噪声大,α 大则平滑但边界模糊,需按场景调节。
  • 初始化:一般从零光流开始,也可用上一层金字塔结果加速收敛。
  • 边界处理:图像边缘需特殊处理,否则邻域均值会引入误差。
HS 得到的是稠密光流,每个像素都有矢量,但计算量大、对噪声敏感,在无人机实时定位中通常不作为首选,更多用于离线分析或稠密运动场可视化。

四、Farneback:多项式展开的稠密光流

Farneback 算法用二次多项式近似每个像素邻域的亮度分布,通过比较两帧多项式系数来估计位移。其核心步骤为:

  1. 对图像做多尺度高斯模糊,构建金字塔。
  2. 在每个像素邻域用加权最小二乘拟合二次多项式,得到系数 A、b、c。
  3. 假设两帧间多项式系数满足 A₂ = A₁,由 Δb = -2A d 解出位移 d。
  4. 在金字塔各层迭代细化,得到最终稠密光流场。

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 数据做融合对比,逐步优化参数。