从检测到追踪:手把手教你用Grounded SAM 2处理自定义视频,实现目标连续跟踪
从检测到追踪:手把手教你用Grounded SAM 2处理自定义视频,实现目标连续跟踪
当你已经完成了Grounded SAM 2的基础环境搭建,接下来最令人兴奋的部分莫过于让它真正跑起来——用你自己的视频数据实现目标检测与连续跟踪。本文将带你深入grounded_sam2_tracking_demo_custom_video_input_gd1.0_local_model.py这个核心脚本,从视频准备到参数调优,再到结果分析,一步步解锁多目标跟踪的完整流程。
1. 准备你的自定义视频数据
在开始之前,确保你的视频素材符合以下要求:
- 格式兼容性:支持MP4、AVI等常见格式,建议使用H.264编码的MP4文件以获得最佳兼容性
- 分辨率建议:1080p或更低分辨率,过高分辨率会增加显存消耗
- 时长控制:初期测试建议使用10-30秒的短视频片段
- 内容特点:
- 目标物体在视频中保持可见性(避免完全遮挡)
- 光照条件相对稳定
- 背景复杂度适中
提示:可以使用FFmpeg对原始视频进行预处理:
ffmpeg -i input.mov -vf "scale=1280:-1" -c:v libx264 -preset fast output.mp4
将处理好的视频文件放置在项目目录下的data/videos文件夹中(如不存在请手动创建)。建议使用英文命名且不含空格,例如my_test_video.mp4。
2. 理解并配置核心脚本参数
打开grounded_sam2_tracking_demo_custom_video_input_gd1.0_local_model.py脚本,以下是最关键的几组参数及其作用:
2.1 输入输出配置
# 视频输入路径 video_path = "data/videos/my_test_video.mp4" # 修改为你的视频路径 # 输出配置 output_dir = "outputs/tracking_results" # 结果保存目录 os.makedirs(output_dir, exist_ok=True)2.2 检测与跟踪参数
# 检测提示词(支持多目标,用分号分隔) text_prompt = "person;car;dog" # 根据你的视频内容修改 # 检测置信度阈值(0-1) box_threshold = 0.3 # 值越小检测越敏感但可能有更多误检 iou_threshold = 0.5 # 用于NMS的去重阈值 # 跟踪参数 tracking_frame_skip = 1 # 跳帧处理,1表示处理每一帧 min_track_length = 5 # 最短跟踪长度(帧数)2.3 模型选择与性能权衡
# 模型选择 sam_model_type = "vit_h" # 可选: vit_h(高精度)/vit_l(平衡)/vit_b(快速) gdino_model = "groundingdino_swinb_cogcoor" # 检测模型版本 # 性能调节 device = "cuda" if torch.cuda.is_available() else "cpu" half_precision = True # 半精度推理加速(需GPU支持)3. 运行脚本与常见问题排查
执行脚本命令:
python grounded_sam2_tracking_demo_custom_video_input_gd1.0_local_model.py3.1 可能遇到的错误与解决方案
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| CUDA out of memory | 显存不足 | 降低视频分辨率或使用更小的SAM模型(vit_l/vit_b) |
| No such file or directory | 路径错误 | 检查视频路径是否准确,使用绝对路径更可靠 |
| Invalid text prompt | 提示词格式问题 | 确保使用英文分号分隔多个目标,无特殊字符 |
| Tracking ID频繁跳变 | 检测阈值过低 | 适当提高box_threshold(如0.4-0.5) |
3.2 性能优化技巧
显存优化:
# 在脚本中添加内存清理逻辑 torch.cuda.empty_cache()速度提升:
- 设置
tracking_frame_skip=2跳过部分帧 - 使用
vit_b模型版本 - 启用
half_precision=True
- 设置
4. 结果分析与可视化评估
运行完成后,在输出目录中你会得到以下文件:
outputs/tracking_results/ ├── my_test_video_tracked.mp4 # 带跟踪框的视频 ├── masks/ # 每帧的分割掩码 │ ├── frame_0001.png │ └── ... └── tracking_data.json # 跟踪元数据4.1 关键指标解读
打开tracking_data.json,重点关注这些字段:
{ "track_stats": { "num_tracks": 5, // 检测到的独立目标数 "avg_track_length": 23.4, // 平均跟踪长度(帧数) "id_switches": 2 // ID切换次数(越少越好) }, "frame_stats": { "avg_detection_time": 0.12, // 平均每帧检测耗时(秒) "avg_tracking_time": 0.05 // 平均每帧跟踪耗时(秒) } }4.2 可视化检查要点
- ID一致性:观察同一目标在整个视频中是否保持相同ID
- 边界框稳定性:检测框是否紧密贴合目标且不剧烈抖动
- 分割精度:掩码是否准确覆盖目标边缘
- 漏检与误检:是否有明显目标未被检测或背景被误识别
注意:初次运行时建议在简单场景下验证,逐步增加复杂度。室内固定摄像头场景通常比移动拍摄的户外场景更容易获得好结果。
5. 高级调优策略
当基础流程跑通后,可以通过这些方法进一步提升效果:
5.1 提示词工程
- 具体化描述:用"red car"替代"car","standing person"替代"person"
- 排除干扰:添加否定提示如"not shadow, not reflection"
- 层级结构:尝试组合提示"vehicle;car;truck;bus"
5.2 运动模型调整
修改脚本中的跟踪器参数:
# 在初始化跟踪器处添加 tracker_params = { "motion_model": { "position_weight": 0.8, # 位置权重 "size_weight": 0.2 # 尺寸权重 }, "reid_threshold": 0.7 # 重识别阈值 }5.3 后处理优化
添加轨迹平滑处理:
from scipy.signal import savgol_filter def smooth_tracks(tracks): # 对轨迹坐标应用Savitzky-Golay滤波 for track_id in tracks: x_coords = [box[0] for box in tracks[track_id]] y_coords = [box[1] for box in tracks[track_id]] window_size = min(15, len(x_coords)) if window_size > 3: x_smooth = savgol_filter(x_coords, window_size, 3) y_smooth = savgol_filter(y_coords, window_size, 3) for i, box in enumerate(tracks[track_id]): box[0], box[1] = x_smooth[i], y_smooth[i] return tracks在实际项目中,我发现当视频中存在快速移动目标时,适当降低box_threshold(0.25-0.35)同时提高iou_threshold(0.6-0.7)能有效减少ID切换。而对于静态场景,使用更保守的参数组合效果更好。
