Ultralytics YOLO27: Trag dich in die Warteliste ein.
Get Started
Ultralytics YOLO in der Produktion·Tracking und Pipelines erstellen·Lektion 5/9
LektionFortgeschrittene

Objekte mit ByteTrack, BoT-SORT und TrackTrack verfolgen

Gib jedem Objekt über mehrere Bilder hinweg eine stabile ID, wähle einen Tracker und passe seine Schwellenwerte an deinen Detektor an.

Jede Zählung, Verweildauer und Geschwindigkeitsschätzung hängt von einer Frage ab: Ist ID 17 in diesem Bild dasselbe Objekt wie ID 17 im vorherigen Bild? Im selben 62 Bilder langen Clip mit etwa 30 Fußgängern und demselben Detektor fand ByteTrack 32 IDs, während TrackTrack mit Standardeinstellungen 9 fand. Die Wahl und Abstimmung des Trackers gehören zum Modell; eine falsche Wahl verfälscht unbemerkt alle nachfolgenden Zahlen.

Lernergebnis

Führe drei Tracker auf einem Video aus, erkläre anhand der Konfidenzwerte des Detektors, wie viele IDs sie gefunden haben, verwende box.id in einer Pipeline und passe einen nicht passenden Tracker mit einer abgestimmten YAML-Datei an.

Schnellkurs
Wenn du dich bereits auskennst, findest du hier die Kurzfassung.
  1. model.track(source, stream=True, tracker="bytetrack.yaml"); jede Box erhält eine stabile id.

  2. Übergibst du die Bilder selbst? Setze persist=True, damit die IDs über mehrere Aufrufe hinweg erhalten bleiben; verwende einen Tracker pro Kamera.

  3. Standardmäßig wird tracktrack.yaml verwendet; ByteTrack ist schnell und fehlertolerant; BoT-SORT bietet zusätzlich einen Ausgleich von Kamerabewegungen, während ReID optional ist.

  4. Zu wenige IDs: Ermittle die Konfidenzwerte des Detektors und senke new_track_thresh und track_high_thresh in einer kopierten YAML-Datei.

Praxisnah

Was ein Tracker leistet#

Ultralytics YOLO verfolgt den Autobahnverkehr: Jedes Auto, jeder Bus und jeder Lkw behält eine nummerierte ID (Auto #12, Bus #21, Lkw #16) und hinterlässt entlang seines jüngsten Wegs eine farbige Linie

Die Beschriftungen und Spuren in diesem Bild stammen vom Tracker. Jede ID ist ein Track, also eine Hypothese zu einem realen Objekt; die Spur zeigt dessen jüngsten Verlauf. In jedem Bild sagt der Tracker mit einem Kalman-Filter voraus, wo sich jeder Track befinden sollte, und ordnet dann die neuen Erkennungen diesen Vorhersagen anhand der Überlappung der Boxen (und optional des Erscheinungsbilds) zu:

Tracks, die über track_buffer Bilder hinweg keiner Erkennung zugeordnet werden, werden gelöscht. Das ist der gesamte Mechanismus; seine Schwellenwerte bestimmen alles Weitere.

Einen Tracker auswählen#

Der Tracking-Modus bietet sechs Tracker: BoT-SORT, ByteTrack, OC-SORT, Deep OC-SORT, FastTracker und TrackTrack (Standard, wenn du kein tracker angibst). Drei decken die meisten Anforderungen ab:

TrackerAbgleichmerkmale (Standardkonfiguration)Wann du ihn verwenden solltest
ByteTrackBewegung und Box-Überlappung sowie ein zweiter Durchlauf, der Boxen mit geringer Konfidenz berücksichtigtFeste Kameras, kleine oder unsichere Detektoren, wenn hoher Durchsatz wichtig ist
BoT-SORTAbgleich wie bei ByteTrack, ergänzt um Bewegungsausgleich der Kamera (gmc_method: sparseOptFlow)Bei bewegten oder wackelnden Kameras; setze with_reid: True für Menschenmengen und lange Verdeckungen
TrackTrackKostenfunktion mit mehreren Merkmalen (Boxform, Konfidenz, Winkel), trackbezogene Initialisierung und Bewegungsausgleich der KameraErkennungen mit hoher Konfidenz von einem leistungsfähigen, gut trainierten Modell

Der Abgleich anhand des Erscheinungsbilds von BoT-SORT (Wiedererkennung) ist standardmäßig deaktiviert; mit model: auto verwendet er die eigenen Merkmale des Detektors, sodass die Aktivierung kaum zusätzlichen Rechenaufwand verursacht.

Tracker auf einem Clip vergleichen#

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"

for tracker in ("bytetrack.yaml", "botsort.yaml", "tracktrack.yaml"):
    ids, frames = set(), 0
    for r in model.track(video, stream=True, tracker=tracker, classes=[0], verbose=False):
        frames += 1
        if r.boxes.is_track:
            ids.update(r.boxes.id.int().tolist())
    print(f"{tracker:16s} {frames} frames, {len(ids)} unique person IDs")
bytetrack.yaml   62 frames, 32 unique person IDs
botsort.yaml     62 frames, 33 unique person IDs
tracktrack.yaml  62 frames, 9 unique person IDs

Der Clip zeigt von oben etwa 30 Menschen, die einen Platz überqueren, daher liegen ByteTrack und BoT-SORT nahe am tatsächlichen Ergebnis. TrackTrack ist nicht defekt: Ein Track wird erst oberhalb von new_track_thresh: 0.7 gestartet und der Abgleich beginnt erst oberhalb von track_high_thresh: 0.6. Die mediane Konfidenz für Personen von YOLO26n liegt in diesem Clip bei 0,53, und nur 17 % der Erkennungen erreichen 0,7. Die meisten Menschen erhalten nie eine ID. Die Entscheidungsregel: Vergleiche die Schwellenwerte des Trackers mit der Konfidenzverteilung deines Detektors, bevor du einer Zählung vertraust.

IDs in einer Pipeline verwenden#

from collections import defaultdict

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"

counts = defaultdict(set)
for r in model.track(video, stream=True, tracker="bytetrack.yaml", verbose=False):
    if not r.boxes.is_track:  # no confirmed tracks in this frame yet
        continue
    for cls, tid in zip(r.boxes.cls.int().tolist(), r.boxes.id.int().tolist()):
        counts[r.names[cls]].add(tid)

for cls, ids in counts.items():
    print(f"{cls}: {len(ids)} unique objects")
person: 32 unique objects

Eine Menge pro Klasse zählt jede ID nur einmal, egal in wie vielen Bildern sie erscheint. Das Ergebnis sind also Objekte und keine Erkennungen. stream=True liefert die Ergebnisse Bild für Bild, statt das gesamte Video im Speicher zu halten. Bereichszählung, Wärmekarten und Abstandsmessung sind einfache Erweiterungen dieser Schleife.

Selbst eingelesene Bilder verfolgen#

Bei einem Pfad oder einer URL wird der Tracker-Zustand automatisch verwaltet. Wenn die Bilder von deinem eigenen Decoder, einer Webcam oder einer RTSP-Kamera kommen, setze persist=True, damit jeder Aufruf dieselbe Sequenz fortsetzt (die Dokumentation zum Vorhersagemodus listet alle Quelltypen auf):

import cv2

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

model = YOLO("yolo26n.pt")
video = safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4")
cap = cv2.VideoCapture(str(video))  # or 0 for a webcam, or an rtsp:// URL

seen = set()
while True:
    ok, frame = cap.read()
    if not ok:
        break
    r = model.track(frame, persist=True, tracker="bytetrack.yaml", classes=[0], verbose=False)[0]
    if r.boxes.is_track:
        seen.update(r.boxes.id.int().tolist())  # your logic: dwell time, trajectories, alerts
cap.release()
print(f"{len(seen)} unique IDs")
32 unique IDs

Das Ergebnis entspricht der Übergabe des Pfads, denn persist=True hat über alle 62 Aufrufe hinweg denselben Tracker aktiv gehalten.

Einen Tracker auf deinen Detektor abstimmen#

Kopiere eine mitgelieferte Konfiguration, senke die Schwellenwerte, die nicht zu deinem Detektor passen, und übergib die neue Datei:

from pathlib import Path

from ultralytics import YOLO
from ultralytics.utils import ROOT

cfg = (ROOT / "cfg/trackers/tracktrack.yaml").read_text()  # packaged defaults
for old, new in (
    ("track_high_thresh: 0.6", "track_high_thresh: 0.3"),
    ("track_low_thresh: 0.25", "track_low_thresh: 0.1"),
    ("new_track_thresh: 0.7", "new_track_thresh: 0.35"),
):
    cfg = cfg.replace(old, new)
Path("tracktrack_tuned.yaml").write_text(cfg)

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
for tracker in ("tracktrack.yaml", "tracktrack_tuned.yaml"):
    ids = set()
    for r in model.track(video, stream=True, tracker=tracker, classes=[0], verbose=False):
        if r.boxes.is_track:
            ids.update(r.boxes.id.int().tolist())
    print(f"{tracker:22s} {len(ids)} unique person IDs")
tracktrack.yaml        9 unique person IDs
tracktrack_tuned.yaml  27 unique person IDs

Indem du die Schwellenwerte knapp unter der medianen Konfidenz des Detektors festlegst, stieg die Anzahl der IDs bei TrackTrack von 9 auf 27 und lag damit nahe an der manuellen Zählung. Die Einstellungen, die alle Tracker gemeinsam haben:

EinstellungByteTrack-StandardwertErhöhen, umSenken, um
track_high_thresh0.25Schwache Erkennungen beim ersten Abgleich ignorierenEinen Detektor mit niedriger Konfidenz verfolgen
new_track_thresh0.25Kurzlebige falsche Tracks vermeidenTracks für schwach erkennbare Objekte starten
track_buffer30 BilderLängere Verdeckungen überstehenIDs verschwundener Objekte früher freigeben
match_thresh0.8Großzügiger abgleichen (schnelle Bewegung, sprunghafte Boxen)Strenger abgleichen (Menschenmengen)

Stolperfallen#

Schwellenwerte oberhalb der Detektorkonfidenz

Symptom: Deutlich weniger IDs als Objekte, besonders bei einem kleinen Modell. Lösung: Gib die mediane Detektionskonfidenz aus (siehe Lösung) und setze new_track_thresh und track_high_thresh knapp darunter.

persist vergessen oder gemeinsam verwenden

Symptom: IDs werden bei jedem Frame zurückgesetzt, wenn du model.track(frame) selbst aufrufst, oder wechseln zwischen Objekten, wenn zwei Kameras ein Modell verwenden. Lösung: Übergib persist=True für aufeinanderfolgende Frames desselben Streams und verwende für jede Kamera eine eigene Modellinstanz (oder nutze eine .streams-Quelle, die für jeden Stream einen eigenen Tracker verwaltet).

ID-Flackern bei langsamen Objekten

Symptom: Die ID eines geparkten Autos ändert sich alle paar Frames. Lösung: Der Tracker beginnt neue Tracks, anstatt alte zuzuordnen. Prüfe zuerst die Konfidenz des Detektors für das Objekt und erhöhe anschließend match_thresh und track_buffer.

Ausprobieren

Nimm ein 30–60 Sekunden langes Video aus deinem eigenen Einsatzbereich auf und zähle die Objekte einer Klasse manuell. Führe compare_trackers.py darauf aus, ermittle die Konfidenzwerte des Detektors mit dem Skript für die Lösung und stimme eine Tracker-YAML-Datei so ab, dass sich die Anzahl der IDs deiner manuellen Zählung annähert. Erstelle eine Tabelle mit Tracker, eindeutigen IDs und manueller Zählung.

Abgeschlossen, wenn
Du hast die Lektion abgeschlossen, wenn alle folgenden Punkte zutreffen.
  • Du hast die Anzahl eindeutiger IDs für ByteTrack, BoT-SORT und TrackTrack im selben Video sowie eine manuelle Zählung vorliegen.

  • Du kannst die niedrigste Anzahl anhand der Schwellenwerte des Trackers und der medianen Konfidenz des Detektors erklären.

  • Eine abgestimmte Tracker-YAML-Datei hat die Anzahl in die Richtung verändert, die du vor dem Ausführen vorhergesagt hast.

Lösung anzeigen

Ermittle zuerst die Konfidenzwerte des Detektors und lege dann die Schwellenwerte knapp darunter fest:

import torch

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
conf = torch.cat([r.boxes.conf for r in model.predict(video, stream=True, classes=[0], verbose=False)])
print(f"median {conf.median():.2f}, share >= 0.7: {(conf >= 0.7).float().mean():.0%}")
median 0.53, share >= 0.7: 17%

Für den Clip vom Platz zeigt die Tabelle: ByteTrack 32, BoT-SORT 33, TrackTrack 9, abgestimmtes TrackTrack 27, manuelle Zählung etwa 30. Nur 17 % der Erkennungen überschreiten new_track_thresh: 0.7 von TrackTrack, daher ist es richtig, diesen Wert auf 0,35 zu senken (mit track_high_thresh: 0.3); für diese feste Kamera mit Blick von oben ist ByteTrack ohne weitere Anpassungen die einfachere Wahl.

Wie es weitergeht

Mit stabilen IDs baut die nächste Lektion darauf auf und zeigt die gängigsten Produktionspipelines: Zählungen, Zonen, Wärmekarten und Geschwindigkeiten.