【Deep-OC-SORT 06】多轨迹算法Deep-OC-SORT-CMC相机运动补偿

CMC:相机运动补偿

Deep-OC-SORT 的第二个通道:每帧估计相机自身 的运动,把全体轨迹的参考坐标搬到新相机坐标系下,再走正常的预测-关联流程。代码位置:deep_ocsort/cmc.py(估计器)、deep_ocsort/ocsort.py(调用与轨迹搬移)、deep_ocsort/kalmanfilter.py(KF 状态搬移)。


一、为什么需要 CMC

多目标跟踪的运动模型默认相机静止:目标在画面里的位移 = 目标自身的运动。相机一动(手持、车载、云台转动、变焦),这个等式破功:

复制代码
画面位移 = 目标运动 ⊕ 相机运动        ← 两者耦合,检测框直接观测到的只有左边

相机运动的受害者清单:

模块 相机不动时的假设 相机动了会怎样
卡尔曼速度 画面位移即目标速度 速度估计混入相机速度,全是偏的
VDC 方向 惯性方向是目标行进方向 方向整体偏转,密集处配错加剧
OCR 找回锚点(last_observation) 目标会回到"最后被看到的位置" 锚点还留在旧坐标系,找回轮大面积失效
IoU 关联 预测框与检测框同一坐标系 整体错位,IoU 集体下跌

典型症状:相机一抖,满屏 ID 切换、轨迹集体断裂。

CMC 的解法:先解耦再跟踪------用背景估计相机运动,把轨迹全部"搬"过去,让等式右边只剩目标运动。


二、怎么估计相机运动

2.1 核心原则:只用背景

compute_affine(img, bbox) 第一步就把本帧检测框区域掩掉:

python 复制代码
mask = np.ones_like(img)
for bb in bbox: mask[bb[1]:bb[3], bb[0]:bb[2]] = 0    # 检测框内不取点

画面里"动的东西"有两类:目标(自己动)和背景(跟着相机动)。目标是干扰源------一辆车和相机同向同速行驶时它在画面里不动,反向时动得飞快,混进估计就把目标运动泄漏进"相机运动"。掩掉检测框,剩下的特征点全部假设属于背景,其位移即相机运动的像。

2.2 方法一:稀疏光流(sparse,默认)

复制代码
上一帧灰度图 + 上帧角点
        ↓ cv2.calcOpticalFlowPyrLK(金字塔 LK 光流)
本帧角点跟踪对
        ↓ cv2.estimateAffinePartial2D(RANSAC)
2×3 仿射矩阵 [m | t]
  • 取角点 :goodFeaturesToTrack(maxCorners=3000, qualityLevel=0.01, minDistance=1, blockSize=3)------ Shi-Tomasi 角点,纹理丰富处密集采样;
  • 跟踪:LK 金字塔光流逐点算位移,两帧间小运动足够准;
  • RANSAC 估刚体变换 :estimateAffinePartial2D 只估旋转+缩放+平移(4 自由度,不含剪切)------相机小幅运动的主成分就是这三个,自由度少则抗噪强;RANSAC 自动剔除跟丢/误配的离群点(正好补上掩码漏掉的运动目标);
  • 兜底:首帧只记录返回单位矩阵;匹配点 < minimum_features(10) 不估、返回单位矩阵;估计失败(返回 None)也回单位矩阵。

2.3 方法二:SIFT 特征匹配(sift)

复制代码
上一帧 SIFT 描述子 ── 暴力匹配(k=2) ──> Lowe 比值筛选(0.7) ──> RANSAC 仿射

SIFT 对光照变化和较大位移更鲁棒(光流假设亮度恒定),代价是提取与匹配更慢。--cmc_method sift 切换。两种方法输出同构(2×3 仿射),后处理完全一致。

2.4 固定相机时的行为

固定机位下相邻帧背景不动,估出的仿射≈单位矩阵(RANSAC 在纯噪声上拟合出的旋转/缩放/平移都接近 0),轨迹坐标几乎不变------CMC 对固定相机是无害的常量开销(一次角点检测 + 一次光流,每帧固定毫秒级),因此默认开启不需要按场景手动切换。


三、拿到仿射之后:轨迹搬移

OCSort.update 每帧把仿射矩阵发给全体轨迹:

python 复制代码
transform = self.cmc.compute_affine(img, dets[:, :4])
for trk in self.trackers:
    trk.apply_affine_correction(transform)

KalmanBoxTracker.apply_affine_correction 搬三处:

3.1 last_observation(OCR 找回锚点)

python 复制代码
ps = last_observation[:4].reshape(2, 2).T     # 4 坐标排成 2x2(两个角点)
ps = m @ ps + t

x1,y1,x2,y2 重排成两列(左上角点、右下角点),各自仿射。有真实观测的轨迹才搬(占位符全 -1 跳过)。

3.2 observations 字典(VDC 参考点)

Δt 范围内(速度估计会用到的那几条)的观测同样搬------VDC 用的参考点与惯性方向必须在同一坐标系,否则夹角是错的。

3.3 KF 状态(kalmanfilter.py apply_affine_correction)

8 维(默认):

python 复制代码
big_m = np.kron(np.eye(4), m)          # 2x2 → 8x8 块对角
x = big_m @ x;x[:2] += t              # [x,vx]、[y,vy]、[w,vw]、[h,vh] 四对各自变换
P = big_m @ P @ big_m.T                # 协方差共轭变换
  • 每个物理量与其速度组成 2 维子空间被 m 旋转缩放------速度向量跟着相机转,方向语义保持;
  • 平移 t 只加在中心 x、y(相机平移不改尺寸与速度);
  • 共轭变换保持 P 正定,不确定性椭圆跟着旋转。

7 维 (new_kf_off):只搬 [x,y] 与 [vx,vy],s(面积)、r(宽高比)是非线性量无法直接仿射,原地不动------7 维模式下 CMC 的补偿打了折扣,这是新 KF 与 CMC 配合更优的原因之一。

3.4 冻结快照同步搬移

漏检中的轨迹(attr_saved 非空且 observed 为 False)连快照一起搬:快照里的 x、P、last_measurement 同样变换------找回重放的起点也在新坐标系,ORU 虚拟轨迹不会从旧坐标出发。


四、在每帧流程中的位置

复制代码
① 检测分拣(conf > track_thresh)
② 外观特征提取(embedding)
③ CMC:估仿射 → 全体轨迹搬移(last_observation / observations / KF 状态 / 冻结快照)
④ 全体轨迹 predict(在已校正的坐标系里外推)
⑤ 第一轮关联(IoU + VDC + 外观AW)→ ⑥ OCR 找回轮 → ⑦ 冻结/建档 → ⑧ 输出清理

CMC 排在 predict 之前:先搬坐标系再外推,速度估计建立在正确的基准上;排在 embedding 之后无依赖关系(源码即此顺序)。


五、参数与调参

参数 默认 作用
--cmc_off 不传(开) 关闭 CMC(仿射恒为单位矩阵)
--cmc_method sparse sparse 稀疏光流 / sift 特征匹配
minimum_features 10(构造参数) 匹配点低于它不估仿射,返回单位矩阵
sparse_flow_param 预置 dict 角点检测参数(maxCorners=3000 等)

调参直觉:

  • 固定相机:默认开即可,仿射≈单位矩阵,无害;
  • 相机剧烈晃动(手持):默认 sparse 通常够用;光照突变(隧道口)时 LK 光流跟丢率高,试 --cmc_method sift;
  • 画面纹理极少(黑夜、空墙):角点数可能低于门槛,CMC 自动退化为不补偿(打 Warning "not enough matching points")------此时要么接受,要么给 qualityLevel 降到更低(构造参数);
  • 纯静止机位想省这点开销:--cmc_off。

六、局限

  • 仅 4 自由度刚体模型(旋转+缩放+平移):透视效应明显的场景(相机平移近景)实际是单应变换,partial affine 只是近似------但 MOT 相邻帧位移小,近似误差有限;
  • 背景纹理依赖:无纹理画面无点可估,自动退化为不补偿;
  • 检测框外的运动目标仍可能漏进特征点:掩码只挡检出的框,漏检目标(检测没框出来的)会污染光流------RANSAC 能剔掉一部分,剩不多的污染由 4 自由度的强约束兜底。
描述 链接
项目 基于 Ultralytics + Deep-OC-SORT 多目标跟踪与改进
往期回顾 链接
数据集 数据集汇总
软件开发 深度学习软件开发汇总
相关推荐
LongRunning13 小时前
【Linux】RK3568-OpenCV+YOLO(八)
linux·opencv·yolo
电科_银尘2 天前
【深度学习项目实战·17】行人目标检测:用Faster R-CNN找出图片中的行人
深度学习·目标检测·r语言
星云_byto2 天前
CSS布局
人工智能·机器学习·目标跟踪·1024程序员节
小豆庄4 天前
测试视频里的人脸车牌敏感信息自动化脱敏方案
计算机视觉·目标跟踪·ffmpeg·音视频·边缘计算·视频·敏捷流程
微尘hjx5 天前
【Deep-OC-SORT 01】多轨迹算法Deep-OC-SORT源码分析
深度学习·yolo·目标跟踪·ultralytics·轨迹算法·deep-oc-sort·车流统计
AI日报派送佬5 天前
高效目标检测利器:X-AnyLabeling 加载自定义 YOLO 模型自动标注实操指南
人工智能·yolo·目标检测
微尘hjx5 天前
【Deep-OC-SORT 02】多轨迹算法Deep-OC-SORT-相对 OC-SORT 的改进点
人工智能·算法·yolo·目标跟踪·视觉检测·ultralytics·deep-oc-sort
微尘hjx5 天前
【Deep-OC-SORT 03】多轨迹算法Deep-OC-SORT-卡尔曼滤波预测过程
算法·yolo·目标跟踪·ultralytics·车跟踪·轨迹算法·deep-oc-sort
小豆庄5 天前
监控视频脱敏的追踪漂移与ID撞号陷阱
目标跟踪·ffmpeg·音视频·视频·敏捷流程