
目标跟踪这行做久了你会发现一个挺反直觉的事实检测器再强也救不回一个抖到漂移的跟踪框。前阵子帮一个做视觉计数的朋友看线上问题YOLO 那一路的召回已经到 0.93 了可 ID switch 还是哗哗地涨最后定位下来不是检测的锅是后处理里那个用了三年的卡尔曼滤波参数压根没跟着场景调过。目标跟踪里滤波算法承担的是“用历史信息压制观测噪声、在漏检时外推目标位置”的角色它决定了跟踪框稳不稳、ID 断不断、轨迹顺不顺。这篇东西我打算把目标跟踪里最常被拿出来说的五大滤波算法——卡尔曼滤波、扩展卡尔曼滤波、无迹卡尔曼滤波、粒子滤波、交互式多模型——从原理到选型到工程落地完整拆一遍中间会带上噪声参数的整定过程、可跑的代码骨架、还有我自己踩过的那些坑。适合刚接触多目标跟踪、想搞清楚“Q 和 R 到底怎么填”的同学也适合已经能跑通 SORT 系列、但想把跟踪质量再往上顶一截的工程同学。1. 五大滤波算法到底在解决什么问题1.1 从“目标为什么会跟丢”说起先把问题摆清楚。摄像头每帧给你一个检测框这个框本身是不准的目标被遮挡一半、运动模糊、光照突变、检测器阈值抖动都会让框心在几像素范围内随机跳。如果你直接把这个框当真实位置输出轨迹就是锯齿状的速度估计更是没法看——相邻两帧框心差 3 像素下一帧差 -2 像素算出来的速度一会儿正一会儿负下游的轨迹预测、越界判断全乱套。滤波算法干的事说白了就两件一是预测用上一时刻的状态和运动模型推这一时刻目标大概在哪二是更新拿这一帧的观测去修正预测。预测给的是先验观测给的是证据两者按不确定度加权融合得到一个后验估计。这个“按不确定度加权”就是滤波的灵魂——谁的方差小就更信谁。卡尔曼增益本质上就是这个加权系数的解析解。那为什么会有五种算法而不是一种因为现实里的系统不总是“线性 高斯”这么理想。卡尔曼滤波是线性高斯条件下的最优估计一旦运动模型或观测模型带非线性比如雷达给的是斜距和方位角转成笛卡尔坐标就是非线性的KF 就不再最优甚至直接失效。于是有了 EKF 的线性化、UKF 的 sigma 点采样、PF 的蒙特卡洛采样。而 IMM 解决的是另一个维度的问题目标不是一直匀速的它会突然加速、转弯、停住单一运动模型描述不了全场景。1.2 五种算法的定位与选型地图我把这五种算法的核心特征先摆成一张表后面再逐个拆。这张表是我自己选型时最常翻的一页建议先扫一眼建立整体印象。算法线性假设噪声假设计算量典型适用场景主要短板卡尔曼滤波 KF必须线性高斯极低视觉跟踪匀速/匀加速目标、雷达航迹的笛卡尔坐标处理非线性场景直接失效扩展卡尔曼滤波 EKF局部线性化高斯低雷达斜距-方位观测、IMU 融合、弱非线性系统雅可比推导繁琐强非线性下发散无迹卡尔曼滤波 UKF无需线性化高斯中强非线性但状态仍近似高斯的系统、姿态估计维度高时 sigma 点代价上升粒子滤波 PF无任意分布高多峰分布、遮挡后重捕、非线性非高斯粒子退化、计算量大、参数敏感交互式多模型 IMM取决于子模型取决于子模型中高机动目标跟踪、无人机、车辆变道模型集设计与转移概率难调选型的基本判断顺序是这样先看观测模型线不线性非线性就排除纯 KF再看后验分布是不是单峰遮挡频繁、容易出现多假设的场景考虑 PF最后看目标机动性强不强强机动优先 IMM 或者给 KF 加自适应 Q。绝大多数视觉多目标跟踪SORT、DeepSORT 这一系用的都是最朴素的 KF因为 bbox 中心坐标到状态量的映射是线性的而且 25~30fps 下目标帧间运动近似匀速KF 完全够用没必要上重武器。这里我想强调一个容易被忽略的点算法复杂度不是选型的第一维度可解释性和可调试性才是。线上出问题时KF 的协方差矩阵你能一眼看出是 Q 给大了还是 R 给小了PF 出了同样的问题你得去翻粒子云分布排查成本高一个量级。我在实际项目里见过不少“为了先进而上 UKF”的例子结果效果还不如调好参数的 KF。2. 算法原理逐层拆解从高斯假设到非线性2.1 卡尔曼滤波线性高斯下的最优解KF 的两个前提必须记牢状态转移和观测都是线性的过程噪声和观测噪声都服从零均值高斯分布。满足这两条KF 就是最小均方误差意义下的最优估计没有之一。标准五公式我按“预测—更新”两段来记。预测段x F * x B * u P F * P * F^T Q更新段K P * H^T * (H * P * H^T R)^(-1) x x K * (z - H * x) P (I - K * H) * P以视觉跟踪最常见的匀速模型为例状态量取[cx, cy, vx, vy]观测量取[cx, cy]那么F [[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]] H [[1, 0, 0, 0], [0, 1, 0, 0]]z - H*x这一项叫新息innovation它表示“观测和预测差了多少”。K 乘以新息就是把预测往观测方向拉。K 大说明更信观测K 小说明更信预测。而 K 的大小由P和R的相对关系决定——P是预测不确定度R是观测不确定度两者比值直接决定融合权重。这就是我前面说的“按不确定度加权”的数学形式。P的更新用的是(I - K*H)*P这个形式数值上简单但容易因为浮点误差导致 P 失去对称正定性。工程上更稳的写法是 Joseph 形式P (I - K*H) * P * (I - K*H)^T K * R * K^T多花一点矩阵乘法换来协方差长期稳定不发散我觉得这笔买卖非常划算。长期跑的服务我基本都用 Joseph 形式。2.2 扩展卡尔曼滤波用一阶泰勒展开硬啃非线性EKF 的思路很直白非线性函数在当前估计点附近做一阶泰勒展开用雅可比矩阵代替原来的线性矩阵。预测段把F换成f的雅可比F_j更新段把H换成h的雅可比H_j其余公式和 KF 一模一样。举个具体例子。雷达跟踪里观测量是[斜距 r, 方位角 θ]状态量是[x, y, vx, vy]观测函数是r sqrt(x^2 y^2) θ atan2(y, x)对状态求偏导得到雅可比H_j [[ x/r, y/r, 0, 0], [ -y/r^2, x/r^2, 0, 0]]注意这个雅可比是随状态变化的每一帧都要重算这也是 EKF 计算量比 KF 大的主要原因。而且r接近 0 的时候x/r会炸工程上必须加一个下限保护比如r max(r, 1e-6)。EKF 最要命的问题是线性化误差。一阶泰勒展开只在展开点附近有效如果系统非线性强、或者初始估计离真值远雅可比描述的“局部线性”和真实曲率差得远滤波就会发散。我遇到过的典型翻车场景是目标从正前方横向切过去方位角变化率极大EKF 在这一段经常把协方差算得过度自信然后观测一进来就被压死轨迹直接甩飞。后来改成 UKF 才解决。不过 EKF 也不是没有优势它的计算量在非线性滤波里是最低的而且雅可比可以离线推导好、代码里手写固定形式实时性极好。嵌入式平台、算力紧张的场景EKF 仍然是首选。2.3 无迹卡尔曼滤波sigma 点比线性化更靠谱UKF 换了个思路不去线性化函数而是去采样。它在当前状态分布上按一定规则取一组确定性采样点sigma 点把这组点直接送进非线性函数得到变换后的点集再从点集里重新算均值和协方差。这套操作叫无迹变换Unscented Transform。具体流程状态维度 n取 2n1 个 sigma 点第一个是均值本身其余沿协方差矩阵的平方根方向对称分布缩放系数由三个超参α, β, κ控制λ α^2 * (n κ) - nα控制 sigma 点离均值的散布范围通常取 1e-3 到 1 之间κ一般取 0 或3-nβ用来引入分布的先验信息高斯分布取 2 最优。均值权重和协方差权重是两套Wm[0] λ / (n λ) Wc[0] λ / (n λ) (1 - α^2 β) Wm[i] Wc[i] 1 / (2*(n λ)) i 1..2nUKF 的精度优势在于无迹变换对非线性函数的逼近至少能达到二阶精度泰勒展开二阶项而 EKF 只有一阶。对于前面那个方位角剧烈变化的问题UKF 明显更稳我实测在横向穿越段的位置 RMSE 比 EKF 低 30% 左右而且不需要推导雅可比改模型的时候省事很多。代价是计算量。状态维度 4 的时候 sigma 点 9 个每个点都要过一次非线性函数如果观测模型复杂比如带相机畸变校正的投影这个开销不能忽略。另外α取得太小会让 sigma 点过于聚集数值上容易出问题实践中我一般取 1e-3配合双精度浮点跑问题不大。2.4 粒子滤波放弃高斯假设用样本逼近PF 是最“暴力”的一种既然后验分布不好解析表达那就用一堆带权重的随机样本粒子去近似它。每个粒子代表一个可能的状态权重代表这个状态的可信度观测来了就按似然更新权重然后重采样把低权重粒子淘汰掉。核心三步循环预测每个粒子按状态转移模型加噪声采样x_i f(x_i) w_i权重更新w_i w_i * p(z | x_i)似然函数通常取高斯形式重采样按权重比例复制粒子权重重置为 1/NPF 最大的优势是不受线性、高斯假设约束后验多峰也能表达。遮挡场景下目标可能从左边出去也可能从右边出去PF 能同时保留这两个假设等观测恢复后再收敛到正确的一支——这是 KF 系做不到的。所以做长时间遮挡后的重捕PF 常常是更优解。但 PF 的坑也非常多。粒子退化是头号问题跑几十帧之后绝大多数粒子权重趋近 0只有一两个粒子权重接近 1相当于用 1 个粒子在做估计方差巨大。标准解法是引入有效粒子数N_eff 1 / sum(w_i^2)当N_eff N/2时触发重采样。但重采样本身又会带来粒子贫化——高权重粒子被反复复制种群多样性丢失。工程上的缓解手段有重采样后加一点过程噪声roughening、用系统重采样代替多项式重采样、或者用正则化粒子滤波。粒子数 N 的选择是个纯工程取舍。我做过一组对比一维状态跟踪N100 时轨迹明显抖动N500 基本平滑N2000 之后收益递减但耗时线性上涨。视觉跟踪里如果状态是 4 维、帧率 30fpsN 取 300~500 是比较常见的平衡点。另外 PF 对过程噪声的分布形状很敏感如果真实噪声是重尾的而你用了高斯粒子云会覆盖不到真实状态表现为“目标明明在视野里但粒子全跑偏了”。2.5 IMM让多个模型投票IMM 不关心单个滤波器的内部它解决的是“目标运动模式会切换”这个问题。做法是并行跑多个不同运动模型的滤波器比如一个匀速 CV、一个匀加速 CA、一个协调转弯 CT每个模型有自己的模型概率每帧根据各模型的似然更新概率再把各模型的估计按概率加权混合。四个步骤输入混合 → 各模型滤波 → 模型概率更新 → 输出混合。输入混合这一步容易被忽略但很关键。它根据模型转移概率矩阵p_ij和上一时刻的模型概率μ_i算出混合权重c_j sum_i(p_ij * μ_i) μ_ij p_ij * μ_i / c_j然后每个模型 j 的初始状态由所有模型的上一时刻估计按μ_ij加权得到。这一步的意义是即使某个模型上一帧概率很低它这一帧的起点也不是自己的旧状态而是被高概率模型“拉”过去的状态这样模型切换时不会出现状态跳变。模型概率更新用似然μ_j (1/c) * Λ_j * c_j其中Λ_j是模型 j 的新息似然c sum_j(Λ_j * c_j)是归一化因子。IMM 的调参重点在模型集设计和转移概率矩阵。模型集要覆盖目标可能的运动模式但也不是越多越好——模型多了每个模型的概率都被稀释切换反而迟钝。车辆跟踪我一般用 CV CT 两个模型就够无人机加上 CA。转移概率矩阵的对角线元素模型保持概率通常取 0.9~0.98非对角线元素均分剩下的概率。这个值反映的是“目标运动模式切换的频繁程度”切换越频繁对角线越小。3. 工程化实现状态量、参数与代码骨架3.1 状态量与观测量的定义这部分是最容易被轻视、但错了后面全白搭的环节。状态量要包含你关心的所有量而且要能通过线性或已知非线性变换对应到观测量。视觉跟踪里我常用的两套定义方案 Abbox 中心 尺度状态[cx, cy, s, r, vx, vy, vs]其中 s 是面积r 是宽高比。SORT 系列用的就是这套宽高比 r 假设不变所以不参与状态转移。优点是尺度变化能被滤波平滑检测框忽大忽小时输出稳定。方案 B纯中心 速度状态[cx, cy, vx, vy]尺度直接用检测值。优点是维度低、计算快、调参简单缺点是尺度抖动会原样透传到输出。目标尺度变化剧烈的场景迎面走来的人用 A 更好。观测量的定义要和检测输出严格对齐。很多同学踩的坑是状态里是cx, cy检测给的是x1, y1, x2, y2转换的时候忘了除 2 或者用错了坐标系原点导致滤波一直在“纠偏”表现就是轨迹持续往一个方向偏。这种错误很难从现象上看出来一定要在初始化阶段打日志验证。提示初始化时不要直接把第一个检测框当状态协方差 P 要给一个合理的不确定度。P 给太小滤波器过度自信前几帧观测根本拉不动它表现为“起步跟不上”。3.2 过程噪声与观测噪声的整定Q 和 R 是 KF 系滤波器的命门我见过 80% 的跟踪效果问题最终都归到这两个矩阵上。R 的整定相对客观它反映的是检测器的定位精度。方法很直接拿一段静态场景或者慢速运动的数据让检测器跑统计同一个目标连续帧的框心位置标准差。假设实测σ_cx 1.5 pxσ_cy 2.0 px且两个方向独立那么R diag(1.5^2, 2.0^2) diag(2.25, 4.0)如果要考虑 x、y 的相关性斜向运动时确实存在就统计协方差矩阵直接填。这个值不用每帧改但换检测器、换分辨率之后必须重新统计。Q 的整定主观得多它反映的是“你有多不信任运动模型”。匀速模型下目标实际上会加速、会转弯这些模型没描述的运动就体现为过程噪声。工程上常用连续白噪声加速度模型Q σ_a^2 * [[dt^4/4, 0, dt^3/2, 0 ], [0, dt^4/4, 0, dt^3/2 ], [dt^3/2, 0, dt^2, 0 ], [0, dt^3/2, 0, dt^2 ]]其中σ_a是目标加速度的标准差。怎么估看目标的最大加速度。假设跟踪的是行人正常走路加速度不超过 2 m/s²那么σ_a取 1~2 是合理的。帧率 25fps 时dt 0.04sdt^2 0.0016 dt^3/2 3.2e-5 dt^4/4 6.4e-7取σ_a^2 2则 Q 的对角元素约为[1.28e-6, 1.28e-6, 3.2e-3, 3.2e-3]。可以看到速度项的 Q 比位置项大三个数量级这符合直觉——模型对速度的不确定性远大于位置。实际调参时我不会死磕这个公式而是把它当起点然后按现象微调轨迹滞后于目标转弯时跟不上→ Q 偏小加大σ_a轨迹抖动明显 → Q 偏大减小σ_a或加大 R漏检几帧后恢复慢→ Q 偏小滤波器对外推太自信一个实用技巧是把 Q 做成自适应的用新息的马氏距离监控。定义d^2 y^T * S^(-1) * y其中S H*P*H^T R。在 2 维观测、4 自由度下d^2超过 9.49 的概率只有 5%超过 13.28 的概率只有 1%。如果连续多帧d^2都超阈值说明模型和实际偏离了这时候临时放大 Q 让滤波器更信观测。这个机制在目标突然加速时特别管用。3.3 可跑的代码骨架下面这段是我常用的 4 维匀速 KF用 numpy 手写不依赖额外库方便嵌入任何管线。注意我用了 Joseph 形式更新协方差。import numpy as np class KalmanCV: def __init__(self, dt0.04, sigma_a2.0, r_std(2.0, 3.0)): self.dt dt # 状态 [cx, cy, vx, vy] self.x np.zeros((4, 1)) self.F np.array([[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]], dtypefloat) self.H np.array([[1, 0, 0, 0], [0, 1, 0, 0]], dtypefloat) # 过程噪声 q sigma_a ** 2 self.Q q * np.array([ [dt**4/4, 0, dt**3/2, 0 ], [0, dt**4/4, 0, dt**3/2], [dt**3/2, 0, dt**2, 0 ], [0, dt**3/2, 0, dt**2 ]], dtypefloat) # 观测噪声 self.R np.diag([r_std[0]**2, r_std[1]**2]).astype(float) self.P np.eye(4) * 10.0 self.I np.eye(4) def predict(self): self.x self.F self.x self.P self.F self.P self.F.T self.Q return self.x[:2].flatten() def update(self, z): z np.asarray(z, dtypefloat).reshape(2, 1) y z - self.H self.x S self.H self.P self.H.T self.R K self.P self.H.T np.linalg.inv(S) self.x self.x K y A self.I - K self.H # Joseph form数值更稳 self.P A self.P A.T K self.R K.T # 新息马氏距离可用于自适应Q与异常观测剔除 d2 float(y.T np.linalg.inv(S) y) return self.x[:2].flatten(), d2调用的时候严格按“先预测、后更新”的顺序漏检的帧只调 predict 不调 update这样滤波器会自动外推。连续漏检超过阈值比如 30 帧就把这条航迹标记为丢失。UKF 的骨架我贴一个核心的无迹变换部分其余流程和 KF 类似def unscented_transform(x, P, f, alpha1e-3, beta2.0, kappa0.0): n x.shape[0] lam alpha**2 * (n kappa) - n # 协方差的平方根用 cholesky 更稳 U np.linalg.cholesky((n lam) * P) sigmas [x] for i in range(n): sigmas.append(x U[:, i:i1]) sigmas.append(x - U[:, i:i1]) sigmas np.hstack(sigmas) # (n, 2n1) Wm np.full(2*n1, 1.0 / (2*(nlam))) Wc Wm.copy() Wm[0] lam / (n lam) Wc[0] lam / (n lam) (1 - alpha**2 beta) sigmas_f np.hstack([f(sigmas[:, i:i1]) for i in range(2*n1)]) x_new sigmas_f Wm.reshape(-1, 1) d sigmas_f - x_new P_new (d * Wc) d.T return x_new, P_new, sigmas_f, Wm, Wc这段代码里np.linalg.cholesky要求矩阵正定实际跑的时候如果 P 因为数值误差变得不正定会直接抛异常。稳妥做法是加一层对称化P (P P.T) / 2或者退回用特征值分解算平方根。4. 场景选型与实测对比4.1 不同场景的算法选型建议选型这事我给个更具体的对照按场景直接抄场景推荐算法理由关键参数常规视觉 MOT目标匀速运动KFCV 模型线性观测、单峰后验、极致轻量σ_a 1~3R 按检测抖动统计视觉 MOT 但目标尺度剧烈变化KF含尺度状态尺度平滑收益明显尺度项 Q 单独调大雷达/激光雷达航迹EKF 或 UKF极坐标观测天然非线性雅可比保护 r 1e-6姿态估计 / IMU 融合UKF四元数非线性强EKF 误差大α1e-3, β2频繁遮挡后的重捕PF 或多假设跟踪后验多峰需要保留假设N300~500N_eff 阈值 N/2车辆变道 / 无人机机动IMM运动模式切换频繁CVCT 双模型对角线 0.95嵌入式、算力极紧张KF必要时退化为 α-β 滤波计算量最小α、β 手工整定α-β 滤波这里补充一句它是 KF 的稳态简化版把卡尔曼增益固定成两个常数省掉所有矩阵运算。在老式雷达和单片机项目里很常见精度损失不大但计算量能降一个数量级。如果板子实在跑不动矩阵乘法这个是兜底方案。4.2 一组模拟数据上的对比记录我在一个模拟场景上跑过对比目标做“匀速—急转—匀速—停止”的运动观测加入σ2px的高斯噪声每 40 帧随机丢弃 5 帧模拟漏检跑 1000 帧取位置 RMSE。这组数是模拟环境下的不代表所有场景但趋势有参考价值。算法位置 RMSE (px)转弯段峰值误差 (px)单帧耗时 (ms)漏检恢复帧数KF (CV)2.318.70.026EKF (CV)2.298.50.056UKF (CV)2.287.90.116PF (N500)2.446.21.854IMM (CVCT)1.874.10.095几个结论值得记一下。匀速段上 KF 系的 RMSE 几乎没差别说明线性场景下没必要上复杂算法差距全部集中在转弯段IMM 靠模型切换把峰值误差压到了 KF 的一半以下PF 在转弯段表现也不错但整体 RMSE 反而略高因为粒子数不够时稳态抖动大耗时上 PF 是 KF 的近百倍这个代价在 30fps 的多目标场景里是要认真掂量的——20 个目标同时跑 PF光滤波就吃掉 37ms一帧预算直接爆掉。还有一组关于 Q 的敏感性数据我觉得比算法对比更有价值σ_a 设置RMSE (px)现象0.53.42转弯严重滞后轨迹被“拽”在后面1.02.68略滞后2.02.31平衡点5.02.55稳态抖动增大10.03.18轨迹几乎跟着观测走滤波形同虚设这张表说明的问题很明确参数整定的收益往往大于换算法。σ_a 从 2 调到 0.5误差涨了 48%比 KF 换成 UKF 的那点提升大得多。所以我的建议是先把手上的 KF 参数调透确实撞到天花板了再考虑换算法。5. 常见问题与排查技巧实录5.1 跟踪框滞后、抖动、漂移的归因路径这三种现象是最高频的抱怨但成因完全不同得分开处理。滞后轨迹总是跟在目标后面一小段距离几乎一定是 Q 太小或者 R 太大。物理意义是滤波器太相信运动模型观测拉不动它。快速验证方法临时把 Q 乘以 100 看滞后是否消失如果消失就说明是 Q 的问题再二分法往回找合适的值。抖动框心高频小幅跳动通常是 Q 太大或者 R 太小滤波器过度跟随观测噪声。也可能是检测本身在抖这时候要看的是检测框和滤波输出的对比如果检测框本身就在抖先解决检测侧的问题别指望滤波兜底。漂移轨迹持续往一个方向偏大概率是坐标系或状态定义错了比如 cx/cy 和 x1/y1 混用、图像坐标和归一化坐标混用。这类问题不会自愈必须回到 3.1 节检查定义。另一种可能是速度项的初始值设错了——初始速度如果给了个非零值滤波器会认为目标在动前几帧就会往那个方向偏。5.2 常见问题速查表现象可能原因排查动作处理方式轨迹整体滞后Q 太小 / R 太大Q 乘 100 试跑增大 σ_a 或重估 R框心高频抖动Q 太大 / R 太小对比检测框与滤波输出减小 σ_a或改用平滑后的检测轨迹单向漂移坐标系或状态定义错误打印首帧状态与观测修正转换关系转弯段发散单一 CV 模型不够看新息马氏距离是否持续超限上 IMM 或自适应 Q漏检后恢复慢Q 小外推过度自信统计恢复所需帧数增大 Q设最大外推帧数协方差报非正定浮点误差累积检查 P 的特征值用 Joseph 形式P 每帧对称化PF 粒子全跑偏过程噪声分布不匹配 / 粒子贫化看 N_eff 和粒子云分布加 roughening换系统重采样UKF 结果异常α 过小导致 sigma 点退化打印 sigma 点散布α 调到 1e-3检查 cholesky 是否成功IMM 切换迟钝转移概率对角线过大看模型概率曲线对角线降到 0.9 左右多目标 ID 频繁切换关联门限与滤波协方差脱节检查门限是否用 S 而非固定值用马氏距离 卡方门限做关联5.3 几个只有实际跑过才知道的细节第一个是协方差的初始化比想象中重要。P 初始给eye(4)和给eye(4)*100前 10 帧的表现能差出天际。给太小滤波器前几帧几乎不听观测轨迹从初始位置缓慢爬过去看起来像“初始化延迟”给太大前几帧完全被观测主导抖动明显。我的经验是按检测器的定位精度来估P 的位置项取(3*σ_det)^2速度项取(v_max*dt)^2。第二个是不要用滤波输出去更新滤波器的量测。有些实现为了“省事”把上一帧滤波后的框喂回给检测或者关联形成闭环误差会被反复放大。滤波器的观测输入必须是原始检测滤波输出只用于展示和下游逻辑。第三个是马氏距离门限的妙用。除了做自适应 Q它还能直接用来剔除异常观测。检测器偶尔会给出离谱的框比如把背景误检成目标如果直接拿去 update滤波器会被拽偏。做法是先算d^2超过卡方门限就跳过这一帧的 update只做 predict。这个机制在多目标场景里能挡掉相当一部分误检干扰。4 维观测对应的 95% 门限是 9.49但这个值要按实际观测量维度查表别照抄。第四个是时间戳不规整时 dt 不能写死。摄像头掉帧、异步推流的情况下帧间间隔可能是 0.033s 也可能是 0.12s如果 F 和 Q 里都用固定的 0.04模型和实际就对不上了表现为“偶发性的轨迹跳变”。正确做法是每帧传入真实 dt重建 F 和 Q。这个改动很小但能消掉一类很难复现的间歇性故障。第五个是别在滤波器和下游之间引入额外平滑。我见过在 KF 输出后面再接一个指数滑动平均的理由是“让轨迹更顺”。结果是滤波器的相位滞后被 EMA 又放大了一次越平滑越滞后。滤波本身就是最优的平滑手段参数调对了就不需要再加一层。5.4 一个关于 IMM 模型概率的踩坑记录最后分享一个我在车辆跟踪上踩过的坑。当时用 IMM 跑 CV CT 双模型发现变道时轨迹总是慢半拍。一开始以为是 CT 模型参数写得不对调了半天转弯率效果不明显。后来把模型概率曲线打出来才看明白CT 模型的概率在变道开始后要过 8~10 帧才升到 0.5 以上而变道过程本身也就十几帧等概率升上来人已经变完了。根因在转移概率矩阵对角线设了 0.98意味着模型保持概率极高、切换概率只有 0.01模型概率更新被这个先验死死压住似然再大也翻不了身。把对角线降到 0.90、非对角线各 0.05 之后模型切换的响应时间缩短到 3 帧以内变道段的峰值误差直接砍掉一半。这件事给我的教训是IMM 的调参重点不在各子滤波器的内部参数而在模型概率的调度机制。子滤波器参数只影响单模型的精度转移概率矩阵决定的是模型切换的灵敏度后者对机动段的跟踪质量影响更大。调 IMM 的正确顺序是先把每个子模型单独调稳再调转移概率最后才回头看输出混合的细节。后续如果还要把这套东西往上扩我会优先考虑把马氏距离门限做成在线自适应——用滑动窗口统计最近 N 帧的新息分布动态更新卡方门限而不是用一个固定的常数。这样在检测器性能波动比如远处目标置信度低、框更抖的时候关联门限能自己跟着松紧比手工设一个值靠谱得多。