ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【自动驾驶】Sparse4D Track Query 理解与其他E2E tracking方法横评

【自动驾驶】Sparse4D Track Query 理解与其他E2E tracking方法横评

Sparse4D Track Query 理解与其他E2E trakcing横评

1. 什么是 Track Query?

Track Query(跟踪查询)是端到端多目标跟踪(MOT)中的核心概念。它指的是用于表示和跟踪目标的查询(query),这些查询在视频序列中保持一致性,从而实现对同一目标的持续跟踪。

1.1 基本概念

在端到端跟踪方法中:

  • Query:表示一个潜在的目标实例
  • Track Query:在时间上保持一致的 query,用于跟踪同一个目标
  • Track ID:分配给每个 track query 的唯一标识符

2. Sparse4D 的 Track Query 实现

2.1 核心思想

Sparse4D不使用显式的 track query,而是通过以下机制实现跟踪:

  1. 时序实例传播:通过InstanceBank将高置信度的实例传播到下一帧
  2. Instance ID 管理:为每个实例分配和维护唯一的 ID
  3. 基于置信度的匹配:根据置信度和空间位置进行匹配

2.2 实现机制

2.2.1 Instance ID 的生成和管理
# 在 InstanceBank.get_instance_id 中defget_instance_id(self,confidence,anchor=None,threshold=None):""" 为实例分配 ID 策略: 1. 继承上一帧的时序实例的 ID 2. 为新检测到的实例分配新的 ID """confidence=confidence.max(dim=-1).values.sigmoid()instance_id=confidence.new_full(confidence.shape,-1).long()# 1. 继承上一帧的时序实例的 IDifself.instance_idisnotNone:instance_id[:,:self.instance_id.shape[1]]=self.instance_id# 2. 为新实例分配新 IDmask=instance_id<0# 未分配 ID 的实例ifthresholdisnotNone:mask=mask&(confidence>=threshold)# 只给高置信度的分配num_new_instance=mask.sum()new_ids=torch.arange(num_new_instance)+self.prev_id instance_id[torch.where(mask)]=new_ids self.prev_id+=num_new_instance# 3. 更新时序实例的 IDifself.num_temp_instances>0:self.update_instance_id(instance_id,confidence)returninstance_id
2.2.2 时序实例的传播
# 在 InstanceBank.cache 中defcache(self,instance_feature,anchor,confidence,metas=None):""" 缓存当前帧的高置信度实例,用于下一帧的时序融合 流程: 1. 选择 top-K 个高置信度实例 2. 应用置信度衰减 3. 缓存特征和 anchor """ifself.num_temp_instances<=0:return# 1. 计算置信度confidence=confidence.max(dim=-1).values.sigmoid()# 2. 应用置信度衰减(对已缓存的实例)ifself.confidenceisnotNone:confidence[:,:self.num_temp_instances]=torch.maximum(self.confidence*self.confidence_decay,# 例如: 0.6confidence[:,:self.num_temp_instances])# 3. 选择 top-K 个实例进行缓存self.confidence,(self.cached_feature,self.cached_anchor)=topk(confidence,self.num_temp_instances,instance_feature,anchor)# 4. 保存元数据self.metas=metas
2.2.3 Instance ID 的更新
# 在 InstanceBank.update_instance_id 中defupdate_instance_id(self,instance_id=None,confidence=None):""" 更新时序实例的 ID 策略: 1. 选择 top-K 个高置信度实例 2. 保留这些实例的 ID 用于下一帧 """# 使用缓存的置信度或当前置信度ifself.temp_confidenceisnotNone:temp_conf=self.temp_confidenceelse:temp_conf=confidence.max(dim=-1).values# 选择 top-K 个实例,保留它们的 IDinstance_id=topk(temp_conf,self.num_temp_instances,instance_id)[1][0]instance_id=instance_id.squeeze(dim=-1)# Padding 到 num_anchor 长度self.instance_id=F.pad(instance_id,(0,self.num_anchor-self.num_temp_instances),value=-1# -1 表示未分配 ID)

2.3 工作流程

Frame t-1: └─> 处理完成后 ├─> 选择 top-600 个高置信度实例 ├─> 缓存: cached_feature, cached_anchor, instance_id └─> 保存元数据: metas Frame t: ├─> 1. 获取时序实例 │ └─> 从缓存中获取: cached_feature, cached_anchor, instance_id │ ├─> 2. 坐标变换 │ └─> 将时序 anchor 变换到当前帧坐标系 │ ├─> 3. 时序融合 │ └─> Temporal GNN: 当前实例 ← 关注 → 时序实例 │ ├─> 4. 解码器处理 │ └─> 所有 instances 一起处理 │ ├─> 5. 分配 Instance ID │ ├─> 时序实例: 继承上一帧的 ID │ └─> 新实例: 分配新 ID │ └─> 6. 更新缓存 └─> 选择 top-600 个实例缓存到下一帧

3. 与其他端到端跟踪方法的对比

3.1 MOTR (End-to-End Multi-Object Tracking with Transformer)

核心思想:

  • 使用显式的 track query,每个 query 对应一个跟踪轨迹
  • Track query 在时间上持续存在,直到目标消失
  • 使用 Hungarian matching 进行 query 和目标的匹配

特点:

# MOTR 的 track queryclassTrackQuery:def__init__(self):self.query=nn.Parameter(...)# 可学习的 query embeddingself.track_id=Noneself.active=True# 是否激活self.age=0# 存在时间defupdate(self,detection):# 更新 query 特征self.query=self.query+detection.feature self.age+=1

与 Sparse4D 的差异:

  • ✅显式 vs 隐式:MOTR 使用显式的 track query,Sparse4D 使用隐式的实例传播
  • ✅Query 数量:MOTR 的 query 数量固定(如 300),Sparse4D 的实例数量可变(900 + 600 时序)
  • ✅匹配方式:MOTR 使用 Hungarian matching,Sparse4D 使用基于置信度的选择

3.2 TrackFormer (Tracking Objects as Points)

核心思想:

  • 将跟踪问题转化为点跟踪问题
  • 使用 DETR 的 query 机制,但为每个目标维护一个 track query
  • Track query 通过 attention 机制与检测 query 交互

特点:

# TrackFormer 的 track queryclassTrackFormer:defforward(self,frame_t,track_queries_t_1):# 1. 检测 query 处理当前帧det_queries=self.detection_head(frame_t)# 2. Track query 与检测 query 交互track_queries_t=self.track_decoder(track_queries_t_1,# 上一帧的 track queriesdet_queries# 当前帧的检测 queries)# 3. 匹配和更新matches=self.match(track_queries_t,det_queries)returntrack_queries_t,matches

与 Sparse4D 的差异:

  • ✅Query 类型:TrackFormer 区分 track query 和 detection query,Sparse4D 统一使用 instance
  • ✅交互方式:TrackFormer 使用 cross-attention,Sparse4D 使用 temporal GNN
  • ✅3D vs 2D:TrackFormer 主要用于 2D,Sparse4D 用于 3D

3.3 QDTrack (Quasi-Dense Similarity Learning)

核心思想:

  • 使用相似度学习进行跟踪
  • 为每个目标学习一个特征 embedding
  • 通过特征相似度进行匹配

特点:

# QDTrack 的跟踪方式classQDTrack:defforward(self,frame_t,frame_t_1):# 1. 提取特征features_t=self.backbone(frame_t)features_t_1=self.backbone(frame_t_1)# 2. 检测detections_t=self.detector(features_t)detections_t_1=self.detector(features_t_1)# 3. 特征匹配similarity=cosine_similarity(detections_t.features,detections_t_1.features)# 4. 匹配matches=self.match(similarity)returnmatches

与 Sparse4D 的差异:

  • ✅匹配方式:QDTrack 使用特征相似度,Sparse4D 使用置信度+位置
  • ✅端到端程度:QDTrack 需要后处理匹配,Sparse4D 更端到端
  • ✅特征学习:QDTrack 显式学习相似度,Sparse4D 隐式通过时序融合

3.4 Sparse4D 的独特之处

特性Sparse4DMOTRTrackFormerQDTrack
Query 类型隐式实例显式 track queryTrack + Detection query特征 embedding
3D/2D3D2D2D2D
匹配方式置信度+位置HungarianAttention相似度
时序融合Temporal GNNQuery 更新Cross-attention特征匹配
实例数量可变 (900+600)固定 (300)固定可变
端到端程度高高高中

4. Sparse4D Track Query 的优势

4.1 隐式跟踪机制

优势:

  • ✅无需显式维护 track query:通过实例传播自然实现跟踪
  • ✅灵活性强:实例数量可变,适应不同场景
  • ✅计算效率高:不需要额外的 query 管理开销

实现:

# Sparse4D 不需要显式的 track query# 只需要:# 1. 缓存高置信度实例self.instance_bank.cache(instance_feature,anchor,confidence)# 2. 在下一帧使用时序实例temp_feature,temp_anchor=self.instance_bank.get(...)# 3. 分配 IDinstance_id=self.instance_bank.get_instance_id(confidence)

4.2 基于置信度的选择

优势:

  • ✅自适应:只跟踪高置信度的目标
  • ✅鲁棒性:低置信度目标自然消失,不会产生错误跟踪
  • ✅简单有效:不需要复杂的匹配算法

实现:

# 选择 top-K 个高置信度实例confidence,(selected_feature,selected_anchor)=topk(confidence,num_temp_instances,instance_feature,anchor)# 应用置信度衰减confidence=torch.maximum(prev_confidence*confidence_decay,# 0.6current_confidence)

4.3 时序融合

优势:

  • ✅信息丰富:通过 temporal GNN 融合时序信息
  • ✅位置感知:考虑坐标变换和时间间隔
  • ✅端到端:在模型内部完成,无需后处理

实现:

# Temporal GNNinstance_feature=self.temp_graph_model(instance_feature,# 当前帧实例temp_instance_feature,# 时序实例temp_instance_feature,# 时序实例query_pos=anchor_embed,key_pos=temp_anchor_embed,)

5. 代码示例

5.1 完整的跟踪流程

# 在 Sparse4DHead.forward 中defforward(self,feature_maps,metas):# 1. 获取实例(包括时序实例)instance_feature,anchor,temp_feature,temp_anchor,time_interval=\ self.instance_bank.get(batch_size,metas)# 2. 时序融合iftemp_featureisnotNone:instance_feature=self.temp_graph_model(instance_feature,temp_feature,temp_feature,...)# 3. 解码器处理forlayerindecoder_layers:instance_feature=layer(instance_feature,anchor,...)# 4. 缓存当前帧实例(用于下一帧)self.instance_bank.cache(instance_feature,anchor,cls,metas)# 5. 分配 Instance ID(推理时)ifnotself.training:instance_id=self.instance_bank.get_instance_id(cls,anchor,self.decoder.score_threshold)output["instance_id"]=instance_idreturnoutput

5.2 Instance ID 的分配

# 在推理时defget_instance_id(self,confidence,anchor=None,threshold=0.2):# 1. 继承上一帧的 IDinstance_id=confidence.new_full(confidence.shape,-1).long()ifself.instance_idisnotNone:instance_id[:,:self.instance_id.shape[1]]=self.instance_id# 2. 为新实例分配新 IDmask=(instance_id<0)&(confidence>=threshold)num_new=mask.sum()new_ids=torch.arange(num_new)+self.prev_id instance_id[mask]=new_ids self.prev_id+=num_new# 3. 更新时序实例的 IDself.update_instance_id(instance_id,confidence)returninstance_id

6. 总结

6.1 Sparse4D Track Query 的特点

  1. 隐式跟踪:不使用显式的 track query,通过实例传播实现
  2. 基于置信度:选择高置信度实例进行跟踪
  3. 时序融合:通过 temporal GNN 融合时序信息
  4. 端到端:在模型内部完成,无需后处理

6.2 与其他方法的差异

方面Sparse4D其他方法
Query 类型隐式实例显式 track query
匹配方式置信度+位置Hungarian/相似度
3D 支持✅❌ (主要是 2D)
实例数量可变通常固定
实现复杂度简单较复杂

6.3 适用场景

Sparse4D 适合:

  • ✅ 3D 多目标跟踪
  • ✅ 需要处理大量目标的场景
  • ✅ 需要端到端训练的模型
  • ✅ 对实时性要求较高的场景

其他方法适合:

  • ✅ 2D 多目标跟踪
  • ✅ 需要显式轨迹管理的场景
  • ✅ 需要更精确匹配的场景
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进