4.2 KiB
Executable File
4.2 KiB
Executable File
ByteTrack 核心原理
多目标跟踪(MOT)算法详解
1. 问题背景
传统方法的局限
大多数 MOT 方法通过高于阈值的高分检测框来获取目标 ID:
- 遮挡物体的检测分数较低(低分检测框)
- 低分物体被直接丢弃
- 导致轨迹断裂和漏检
ByteTrack 的解决思路
核心思想:不仅仅关联高分检测框,而是关联所有检测框
2. 算法流程
Two-Stage Association
输入:视频序列
↓
┌─────────────────────────────┐
│ Step 1: 高分检测框关联 │
│ (High Score Detection) │
│ 使用 IoU/特征匹配高分框 │
└─────────────┬───────────────┘
↓
┌─────────────────────────────┐
│ Step 2: 低分检测框关联 │
│ (Low Score Detection) │
│ 利用轨迹相似度恢复目标 │
│ 过滤背景误检 │
└─────────────┬───────────────┘
↓
输出:完整轨迹
Byte 名称由来
- "Byte" = 8 bits = 256 种可能性
- 每个检测框有 0-255 的检测分数
- 关联所有分数的检测框,如同处理字节一样
3. 核心创新点
创新一:双重关联
| 阶段 | 输入 | 目的 |
|---|---|---|
| 第一关联 | 高分检测框 (score > θ₁) | 找到明确的目标 |
| 第二关联 | 低分检测框 (θ₂ < score ≤ θ₁) | 恢复被遮挡的目标 |
创新二:YOLOX 检测器
ByteTrack 使用 YOLOX 作为检测器:
- Anchor-free 设计
- SimOTA 标签分配
- 优秀的检测性能
创新三:简单强大的 Tracker
- 不依赖 Re-ID 特征
- 仅使用 IoU 关联
- 高效且易于部署
4. 匹配策略
卡尔曼滤波
- 预测下一帧目标位置
- 处理物体运动平滑
IoU 匹配
# 高分关联
matched, unmatched_dets = IoUMatching(tracklets, high_score_dets)
# 低分关联(仅对未匹配轨迹)
matched, unmatched_tracks = IoUMatching(unmatched_tracks, low_score_dets)
阈值设置
| 参数 | 说明 | 典型值 |
|---|---|---|
high_score_thresh |
高分阈值 | 0.5 |
match_thresh |
IoU 匹配阈值 | 0.8 |
low_score_thresh |
低分阈值 | 0.6 |
5. 为什么有效?
遮挡场景示例
帧 1: [Person A] → 检测分数 0.95 ✓
帧 2: [Person A] → 检测分数 0.85 ✓
帧 3: [被遮挡] → 检测分数 0.35 ✗ (传统方法丢弃)
ByteTrack 处理:
- 帧 1-2: 正常关联,建立轨迹
- 帧 3: 低分框仍参与第二关联
- 利用运动预测 + IoU 匹配
- 成功恢复被遮挡目标
效果提升
| 指标 | 提升 | 原因 |
|---|---|---|
| MOTA | +2-3% | 减少漏检 |
| IDF1 | +1-10% | 轨迹更连续 |
| IDs | 大幅减少 | 减少轨迹断裂 |
6. 与其他 Tracker 对比
ByteTrack 可集成到多种现有 tracker:
- ✅ ByteTrack + SORT
- ✅ ByteTrack + DeepSORT
- ✅ ByteTrack + MOTDT
所有组合都获得 一致的性能提升。
7. 核心代码框架
class BYTETracker:
def __init__(self, args):
self.high_score_thresh = args.track_thresh
self.low_score_thresh = args.low_thresh
self.match_thresh = args.match_thresh
def update(self, dets, frame_info):
# 分离高低分检测框
high_dets = dets[dets[:, 4] >= self.high_score_thresh]
low_dets = dets[dets[:, 4] < self.high_score_thresh]
# 第一阶段:高分关联
online_targets = self.associate(high_dets, tracks)
# 第二阶段:低分关联
online_targets = self.associate_low(online_targets, low_dets)
return online_targets