第四章:目标检测与跟踪基础

各位同学,今天我们来聊聊自动驾驶感知系统中一个绕不开的话题——目标跟踪。说实话,我刚入行那会儿,觉得目标检测才是重头戏,跟踪嘛,不就是把检测框连起来?后来在实车上跑了一次才发现,事情远没那么简单。

4.1 卡尔曼滤波:状态估计的基石

卡尔曼滤波,说白了就是一套“预测+修正”的数学框架。你想想看,传感器每帧都有噪声,目标还可能被遮挡,怎么才能得到平滑、可信的轨迹?卡尔曼滤波就是干这个的。

它的核心思想其实很朴素:

  • 预测阶段:根据上一帧的状态,推测当前帧目标大概在哪
  • 更新阶段:用当前帧的观测值,修正这个推测

我个人习惯把卡尔曼滤波拆成五个公式来理解,但实际工程中,我更关注两个矩阵:状态转移矩阵 F观测矩阵 H

工程要点:在自动驾驶场景中,我们通常用匀速模型或匀加速模型。状态向量一般取 [x, y, vx, vy, w, h] 或 [x, y, vx, vy, ax, ay]。

举个简单的例子,假设我们要跟踪一辆车的位置:

// 伪代码:卡尔曼滤波预测与更新
// 预测
x_pred = F * x_prev + B * u
P_pred = F * P_prev * F^T + Q

// 更新
K = P_pred * H^T * (H * P_pred * H^T + R)^(-1)
x_updated = x_pred + K * (z - H * x_pred)
P_updated = (I - K * H) * P_pred

这里 Q 是过程噪声协方差,R 是测量噪声协方差。我在项目中遇到过一个问题:Q 和 R 调不好,跟踪结果要么抖动得厉害,要么反应迟钝。后来我总结了一个经验——先固定 R,再调 Q,这样调试效率高很多。

避坑指南:我曾经把 Q 设得太小,结果目标突然加速时,卡尔曼滤波完全跟不上,轨迹直接断掉。后来我改用自适应 Q,根据目标的加速度残差动态调整,效果好了不少。

4.2 匈牙利匹配算法:数据关联的艺术

检测到了目标,也预测了轨迹,接下来要回答一个问题:当前帧的检测框,到底该匹配给哪条历史轨迹?

匈牙利算法就是解决这个分配问题的。它的输入是一个代价矩阵,比如用 IOU(交并比)或马氏距离作为代价。算法输出一个最优匹配,使得总代价最小。

嗯,这里要注意:匈牙利算法要求代价矩阵是方阵,但实际场景中检测数和轨迹数往往不相等。所以工程上我们会引入虚拟节点,把矩阵补成方阵。

检测框 轨迹1 轨迹2 轨迹3
D1 0.8 0.3 0.1
D2 0.2 0.9 0.4
D3 0.5 0.6 0.7

表:代价矩阵示例(数值越小表示匹配度越高)

匈牙利算法会找出一个匹配组合,比如 D1→轨迹1、D2→轨迹2、D3→轨迹3,使得总代价最小。实际工程中,我还会加一个阈值门控——如果最小代价都大于某个阈值(比如 IOU < 0.3),那就认为这个检测是新目标,不匹配给任何轨迹。

注意:匈牙利算法的时间复杂度是 O(n³),当目标数量超过 100 时,计算开销会明显增加。我建议在目标密集场景下,先用距离粗筛,缩小匹配范围,再跑匈牙利算法。

4.3 目标ID管理:给每个目标一个身份

跟踪系统里,每个目标都需要一个唯一的 ID。这个 ID 从目标出现开始,到目标消失结束,中间不能变。你想想看,如果一辆车在画面里 ID 跳来跳去,下游的预测和规划模块根本没法用。

ID 管理的核心原则就一条:一个 ID 只能对应一个物理目标。但实际中经常出现 ID Switch(ID 交换)的问题,比如两辆车交错后,ID 互换了。

我遇到过最头疼的情况是:一辆车被遮挡后重新出现,系统给它分配了新 ID,导致轨迹断裂。后来我引入了轨迹生命周期管理

  • 初始化:连续 3 帧都检测到该目标,才分配 ID
  • 维持:每帧都更新轨迹状态
  • 终止:连续 5 帧没有匹配到检测,就删除轨迹

经验之谈:我建议把 ID 分配和轨迹状态机结合起来。比如用三个状态:候选(Candidate)确认(Confirmed)丢失(Lost)。只有 Confirmed 状态的轨迹才输出给下游模块。

4.4 轨迹初始化与终止

轨迹初始化,说白了就是决定什么时候给一个新目标“上户口”。太早了容易引入噪声,太晚了又丢失信息。

我个人习惯用多帧确认策略

  1. 第一帧检测到目标,创建临时轨迹,标记为 Candidate
  2. 第二帧再次匹配到,更新轨迹,仍为 Candidate
  3. 第三帧依然匹配到,升级为 Confirmed,分配正式 ID

轨迹终止则相反:

  1. 连续 N 帧没有匹配到检测,标记为 Lost
  2. Lost 状态下再维持 M 帧,如果还没出现,就彻底删除

N 和 M 怎么选?我一般设 N=3,M=5。但具体要看场景:高速场景目标移动快,N 可以小一点;城市道路目标容易被遮挡,N 可以大一点。

小技巧:我曾经在项目中加入了一个“预测补偿”机制——当目标短暂丢失时,用卡尔曼滤波的预测值继续更新轨迹位置,而不是直接标记为 Lost。这样能有效减少轨迹断裂。

好了,这一章的内容就到这里。卡尔曼滤波、匈牙利匹配、ID 管理、轨迹初始化与终止,这四个模块构成了目标跟踪的骨架。下一章我们会聊到行为预测,到时候这些跟踪结果就是预测的输入了。

记住一句话:跟踪做不好,预测就是空中楼阁。希望各位在实际项目中,能把这些基础打扎实。