RF-DETR + ByteTrack 多目标跟踪实战教程:从命令行到 Python 视频轨迹可视化

这篇教程是根据近期学习目标检测、多目标跟踪和视频分析项目的复现过程整理出来的,重点演示如何把 RF-DETR 检测器和 ByteTrack 跟踪器组合起来,对视频中的目标进行连续跟踪,并绘制检测框、轨迹和跟踪 ID。

ByteTrack 和 SORT 一样,都建立在卡尔曼滤波与匈牙利匹配算法的基本框架上,但它的核心改进是数据关联策略:ByteTrack 会尽可能利用几乎所有检测框,而不是简单丢弃低置信度框。它通常先用高置信度检测框匹配已有轨迹,再用低置信度检测框通过 IoU 匹配仍未关联的轨迹。这样可以减少遮挡、弱检测带来的漏跟踪和轨迹断裂,同时保持较高的运行速度。

本文会分别演示两种使用方式:

  • 使用 trackers 命令行工具快速跑通视频跟踪
  • 使用 Python 代码组合 RF-DETR、ByteTrack 和 supervision 标注器
  • 在移动镜头场景中加入相机运动补偿,让轨迹显示更稳定

在这里插入图片描述

如果你正在系统学习目标检测、多目标跟踪和视频理解任务,可以先收藏本文;配套 notebook、示例视频和后续同系列更新,我会整理成资料包,后面统一放到更方便获取的位置。


⚙️ 环境准备

这一部分主要完成 GPU 检查、依赖安装和示例视频下载。视频跟踪任务通常会逐帧运行检测模型,因此建议优先使用 GPU 环境。

🧪 检查 GPU 是否可用

先确认当前环境是否可以访问 GPU。可以使用 nvidia-smi 命令进行检查。如果在 Colab 中遇到 GPU 不可用的问题,可以进入 Runtime -> Change runtime type -> Hardware accelerator,将硬件加速器设置为 GPU,然后点击 Save

!nvidia-smi

🔧 安装依赖

这里安装 inference-gputrackers==2.3.0。在 Google Colab 中可能会看到依赖冲突警告,这通常来自 Colab 预装环境,不影响本教程功能。

!pip install -q inference-gpu trackers==2.3.0

🎬 下载示例视频

下面会下载 3 段示例视频,分别用于普通视频跟踪和移动镜头下的轨迹补偿实验。你也可以把路径替换成自己的视频。

!wget -q https://storage.googleapis.com/com-roboflow-marketing/supervision/video-examples/bikes-1280x720-1.mp4
!wget -q https://storage.googleapis.com/com-roboflow-marketing/supervision/video-examples/bikes-1280x720-2.mp4
!wget -q https://storage.googleapis.com/com-roboflow-marketing/supervision/video-examples/skiers-1280x720-5.mp4

💻 方式一:使用 CLI 进行目标跟踪

trackers 库提供了命令行接口(CLI),可以直接对视频运行目标跟踪,不需要先写 Python 代码。对于快速验证模型、调参数或批量处理视频,这种方式很方便。

更多 CLI 参数和配置可以参考 Track from CLI documentation

SOURCE_VIDEO_PATH = "/content/bikes-1280x720-1.mp4"
TARGET_VIDEO_PATH = "/content/bikes-1280x720-1-result.mp4"

!trackers track \
    --source {SOURCE_VIDEO_PATH} \
    --output {TARGET_VIDEO_PATH} \
    --model rfdetr-medium \
    --tracker bytetrack \
    --show-trajectories
TARGET_VIDEO_COMPRESSED_PATH = "/content/bikes-1280x720-1-result-compressed.mp4"

!ffmpeg -y -loglevel error -i {TARGET_VIDEO_PATH} -vcodec libx264 -crf 28 {TARGET_VIDEO_COMPRESSED_PATH}
from IPython.display import Video

Video(TARGET_VIDEO_COMPRESSED_PATH, embed=True, width=1080)

🐍 方式二:使用 Python 组合检测器和跟踪器

如果你希望更细粒度地控制检测阈值、NMS、标注样式、轨迹长度或类别过滤,就更适合使用 Python 代码。

🚀 初始化检测器和跟踪器

这里使用 get_model("rfdetr-medium") 加载 RF-DETR Medium 检测模型,并初始化 ByteTrackTracker

from inference import get_model
from trackers import ByteTrackTracker

model = get_model("rfdetr-medium")
tracker = ByteTrackTracker()

🎨 配置标注器

这里使用 supervision 配置三类标注器:

  • BoxAnnotator:绘制检测框
  • LabelAnnotator:绘制跟踪 ID 或标签
  • TraceAnnotator:绘制目标运动轨迹
import supervision as sv

color = sv.ColorPalette.from_hex([
    "#ffff00", "#ff9b00", "#ff8080", "#ff66b2", "#ff66ff", "#b266ff",
    "#9999ff", "#3399ff", "#66ffff", "#33ff99", "#66ff66", "#99ff00"
])

box_annotator = sv.BoxAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK)

label_annotator = sv.LabelAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK,
    text_color=sv.Color.BLACK,
    text_scale=0.8)

trace_annotator = sv.TraceAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK,
    thickness=2,
    trace_length=100)

🧩 运行检测和跟踪

这一段是 Python 版本的核心流程:

  • 每一帧先用 RF-DETR 做目标检测
  • 使用 NMS 去除重叠框
  • 将检测结果交给 ByteTrack 更新轨迹
  • 在当前帧上绘制检测框、轨迹和跟踪 ID
  • 最后用 sv.process_video 逐帧处理并生成新视频
CONFIDENCE_THRESHOLD = 0.2
NMS_THRESHOLD = 0.3

SOURCE_VIDEO_PATH = "/content/bikes-1280x720-2.mp4"
TARGET_VIDEO_PATH = "/content/bikes-1280x720-2-result.mp4"

def callback(frame, i):
    result = model.infer(frame, confidence=CONFIDENCE_THRESHOLD)[0]
    detections = sv.Detections.from_inference(result).with_nms(threshold=NMS_THRESHOLD)
    detections = tracker.update(detections)

    annotated_image = frame.copy()
    annotated_image = box_annotator.annotate(annotated_image, detections)
    annotated_image = trace_annotator.annotate(annotated_image, detections)
    annotated_image = label_annotator.annotate(annotated_image, detections, detections.tracker_id)

    return annotated_image

tracker.reset()

sv.process_video(
    source_path=SOURCE_VIDEO_PATH,
    target_path=TARGET_VIDEO_PATH,
    callback=callback,
    show_progress=True,
)

📺 显示 Python 跟踪结果

TARGET_VIDEO_COMPRESSED_PATH = "/content/bikes-1280x720-2-result-compressed.mp4"

!ffmpeg -y -loglevel error -i {TARGET_VIDEO_PATH} -vcodec libx264 -crf 28 {TARGET_VIDEO_COMPRESSED_PATH}
from IPython.display import Video

Video(TARGET_VIDEO_COMPRESSED_PATH, embed=True, width=1080)

🛰️ 相机运动补偿

当视频由移动相机拍摄时,比如无人机、手持设备、滑雪跟拍或车辆行驶画面,目标轨迹可能会因为相机本身的平移或旋转而显得不稳定。相机运动补偿会通过光流估计相机运动,并在绘制轨迹时进行稳定化处理。

这种能力对移动镜头视频尤其重要,因为我们真正关心的是目标自身的运动,而不是相机移动造成的画面偏移。

from inference import get_model
from trackers import ByteTrackTracker, MotionEstimator, MotionAwareTraceAnnotator

PERSON_CLASS_ID = 0

model = get_model("rfdetr-large")
tracker = ByteTrackTracker(minimum_consecutive_frames=3)
motion_estimator = MotionEstimator(
    max_points=500,
    min_distance=10,
    quality_level=0.001,
    ransac_reproj_threshold=1.0,
)

color = sv.ColorPalette.from_hex([
    "#ffff00", "#ff9b00", "#ff8080", "#ff66b2", "#ff66ff", "#b266ff",
    "#9999ff", "#3399ff", "#66ffff", "#33ff99", "#66ff66", "#99ff00"
])

box_annotator = sv.BoxAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK)

label_annotator = sv.LabelAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK,
    text_color=sv.Color.BLACK,
    text_scale=0.8)

motion_aware_trace_annotator = MotionAwareTraceAnnotator(
    color=color,
    color_lookup=sv.ColorLookup.TRACK,
    thickness=2,
    trace_length=100)
CONFIDENCE_THRESHOLD = 0.2
NMS_THRESHOLD = 0.3

SOURCE_VIDEO_PATH = "/content/skiers-1280x720-5.mp4"
TARGET_VIDEO_PATH = "/content/skiers-1280x720-5-result.mp4"

def callback(frame, i):
    coord_transform = motion_estimator.update(frame)

    result = model.infer(frame, confidence=CONFIDENCE_THRESHOLD)[0]
    detections = sv.Detections.from_inference(result).with_nms(threshold=NMS_THRESHOLD)
    detections = detections[detections.class_id == PERSON_CLASS_ID]
    detections = tracker.update(detections)

    annotated_image = frame.copy()
    annotated_image = box_annotator.annotate(annotated_image, detections)
    annotated_image = motion_aware_trace_annotator.annotate(
        annotated_image, detections, coord_transform=coord_transform)
    annotated_image = label_annotator.annotate(annotated_image, detections, detections.tracker_id)

    return annotated_image

tracker.reset()
motion_estimator.reset()
motion_aware_trace_annotator.reset()

sv.process_video(
    source_path=SOURCE_VIDEO_PATH,
    target_path=TARGET_VIDEO_PATH,
    callback=callback,
    show_progress=True,
)
TARGET_VIDEO_COMPRESSED_PATH = "/content/skiers-1280x720-5-result-compressed.mp4"

!ffmpeg -y -loglevel error -i {TARGET_VIDEO_PATH} -vcodec libx264 -crf 28 {TARGET_VIDEO_COMPRESSED_PATH}
from IPython.display import Video

Video(TARGET_VIDEO_COMPRESSED_PATH, embed=True, width=1080)

📌 小结

这篇教程把 RF-DETR 检测器和 ByteTrack 跟踪器组合起来,分别演示了命令行和 Python 两种用法。对于入门多目标跟踪来说,可以重点理解下面几件事:

  • 检测器负责逐帧找出目标框
  • 跟踪器负责把不同帧中的同一目标关联起来
  • ByteTrack 会利用低置信度检测框来减少轨迹断裂
  • supervision 标注器可以快速绘制检测框、轨迹和跟踪 ID
  • 移动镜头场景下,相机运动补偿能让轨迹显示更稳定

后续我会继续把类似的目标检测、多目标跟踪、OCR 和图像分割项目整理成系列教程。配套 notebook、示例视频和运行环境说明也会按主题逐步整理出来,适合刚入门计算机视觉和视频分析的同学跟着实践。

📚 同系列教程汇总

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐