初めに
trackers は、Roboflow が提供するマルチオブジェクト追跡(MOT)アルゴリズムのクリーンルーム実装ライブラリです。Apache 2.0 ライセンスで公開されており、任意の検出モデルと組み合わせて使えます。
今回は YOLO で物体を検出し、ByteTrack で追跡、supervision で可視化する一連のパイプラインを動かします。ByteTrack は二段階アソシエーション(高信頼度 → 低信頼度の順でマッチング)を行うアルゴリズムで、低信頼度の検出も活用することでオクルージョンに強い追跡が可能です。
結果
入力

出力

開発環境
| 項目 | バージョン |
|---|---|
| OS | Windows 11 |
| Python | 3.13 |
| パッケージマネージャ | uv |
| trackers | 2.2.0rc0 |
| YOLO モデル | yolo11m.pt (Ultralytics) |
環境構築
リポジトリをクローンして依存パッケージをインストールします。
git clone https://github.com/roboflow/trackers.git cd trackers
uv sync
trackers は ultralytics と opencv-python を依存に含んでいるため、追加インストールは不要です。
テスト用動画のダウンロード
supervision ライブラリの download_assets を使うとサンプル動画を簡単に取得できます。
from supervision.assets import download_assets, VideoAssets video_path = download_assets(VideoAssets.PEOPLE_WALKING)
実行すると people-walking.mp4 がカレントディレクトリにダウンロードされます。
デモスクリプトの解説
スクリプトは examples/demo_bytetrack.py にあります。
引数
| 引数 | デフォルト | 説明 |
|---|---|---|
--source |
(必須) | 入力動画のパス |
--output |
output.mp4 |
出力動画のパス |
--model |
yolo11m.pt |
YOLO モデル名またはパス |
検出
YOLO で各フレームの物体を検出し、sv.Detections.from_ultralytics() で supervision の形式に変換します。
results = model(frame, verbose=False)[0] detections = sv.Detections.from_ultralytics(results)
追跡
ByteTrackTracker().update(detections) を呼ぶだけでトラッカーID が付与されます。tracker_id が -1 の場合は、まだ連続フレーム数の閾値(デフォルト2フレーム)に達していない未成熟なトラックです。
tracker = ByteTrackTracker() detections = tracker.update(detections)
可視化
sv.BoxAnnotator と sv.LabelAnnotator でバウンディングボックスとラベルを描画します。
box_annotator = sv.BoxAnnotator()
label_annotator = sv.LabelAnnotator()
annotated = box_annotator.annotate(scene=frame.copy(), detections=detections)
annotated = label_annotator.annotate(
scene=annotated, detections=detections, labels=labels
)
ソースコード全文
import argparse import time import cv2 import supervision as sv from ultralytics import YOLO from trackers import ByteTrackTracker def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="YOLO + ByteTrack object tracking demo" ) parser.add_argument("--source", type=str, required=True) parser.add_argument("--output", type=str, default="output.mp4") parser.add_argument("--model", type=str, default="yolo11m.pt") return parser.parse_args() def main() -> None: args = parse_args() model = YOLO(args.model) tracker = ByteTrackTracker() box_annotator = sv.BoxAnnotator() label_annotator = sv.LabelAnnotator() cap = cv2.VideoCapture(args.source) if not cap.isOpened(): print(f"Error: cannot open video '{args.source}'") return width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) or 30.0 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) fourcc = cv2.VideoWriter_fourcc(*"mp4v") writer = cv2.VideoWriter(args.output, fourcc, fps, (width, height)) frame_idx = 0 prev_time = time.time() print(f"Processing '{args.source}' ({total_frames} frames, {fps:.1f} FPS)") print(f"Output: '{args.output}'") print("Press 'q' to stop early.\n") while True: ret, frame = cap.read() if not ret: break results = model(frame, verbose=False)[0] detections = sv.Detections.from_ultralytics(results) detections = tracker.update(detections) tracker_ids = ( detections.tracker_id if detections.tracker_id is not None else [] ) labels = [ f"#{int(tid)}" if tid >= 0 else "?" for tid in tracker_ids ] annotated = box_annotator.annotate( scene=frame.copy(), detections=detections ) annotated = label_annotator.annotate( scene=annotated, detections=detections, labels=labels ) now = time.time() processing_fps = 1.0 / max(now - prev_time, 1e-9) prev_time = now frame_idx += 1 n_tracks = ( int((detections.tracker_id >= 0).sum()) if detections.tracker_id is not None else 0 ) print( f"\rFrame {frame_idx}/{total_frames}" f" FPS: {processing_fps:.1f}" f" Tracks: {n_tracks}", end="", flush=True, ) writer.write(annotated) cv2.imshow("ByteTrack Demo", annotated) if cv2.waitKey(1) & 0xFF == ord("q"): print("\nStopped by user.") break cap.release() writer.release() cv2.destroyAllWindows() print(f"\n\nDone. Output saved to '{args.output}'") if __name__ == "__main__": main()
実行
以下のコマンドで実行します。
uv run python examples/demo_bytetrack.py --source people-walking.mp4
ターミナルに処理状況が表示されます。
Processing 'people-walking.mp4' (210 frames, 30.0 FPS) Output: 'output.mp4' Press 'q' to stop early. Frame 210/210 FPS: 15.2 Tracks: 7
ウィンドウが開いてリアルタイムで追跡結果が表示されます。途中で止めたい場合は q キーを押してください。完了すると output.mp4 が出力されます。