Inferenz auf Videos ausführen
Führe YOLO26 auf Videodateien und Live-Kameras mit begrenztem Speicherverbrauch aus, verfolge Objekte, um jedes nur einmal zu zählen, und prüfe, ob das Modell mit der Bildrate Schritt hält.
Die meisten eingesetzten Bildverarbeitungssysteme überwachen Videos: Kameras an Förderbändern, Türen und Straßen. Videos bringen zwei Probleme mit sich, die es bei Einzelbildern nicht gibt. Speicher: Eine lange Aufzeichnung lässt sich nicht vollständig im RAM halten. Identität: Ein Detektor erkennt dieselbe Person in 60 Bildern und meldet 60 Personen.
In dieser Lektion verarbeitest du Videos Bild für Bild im Predict-Modus, ergänzt Objektverfolgung, um jede Person nur einmal zu zählen, schreibst eine eigene Kameraschleife und misst, ob dein Modell mithalten kann.
Praxisnah
Beispiel: Vorhersagen auf einer Videodatei#
Videos werden wie Bilder im selben Predict-Modus verarbeitet. Dieser Clip mit 62 Bildern zeigt Menschen, die ein Atrium durchqueren:
yolo predict model=yolo26n.pt source=https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4video 1/1 (frame 1/62) solutions_ci_demo.mp4: 384x640 22 persons, 27.3ms
...
video 1/1 (frame 62/62) solutions_ci_demo.mp4: 384x640 22 persons, 54.8ms
Results saved to runs/detect/predictframe 1/62: Ultralytics dekodiert das Video und verarbeitet jedes Bild wie ein Einzelbild.22 persons: Erkennungen in diesem Bild. Dieselben Passanten werden in jedem Bild erneut gezählt.27.3ms...54.8ms: Die Zeit pro Bild variiert je nachdem, womit der Rechner sonst beschäftigt ist.
Das annotierte Video ist runs/detect/predict/solutions_ci_demo.mp4. Dein eigenes Modell funktioniert genauso: Ersetze yolo26n.pt durch runs/detect/pills_v1/weights/best.pt.
Lange und Live-Quellen streamen#
Wenn dein Code mit Erkennungen arbeitet, durchlaufe einen Stream. Bei jeder Iteration wird das Results eines Bildes geliefert und anschließend verworfen:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
frames, people = 0, 0
for result in model(source, stream=True, classes=[0], verbose=False): # one Results object per frame
frames += 1
people += len(result.boxes)
print(f"{frames} frames, {people / frames:.1f} people per frame")62 frames, 22.2 people per frameDieselbe Schleife akzeptiert einen Webcam-Index (source=0) oder eine Kamera-URL wie rtsp://camera.local/stream und läuft, bis der Stream endet oder du ihn stoppst. Füge vid_stride=2 hinzu, um nur jedes zweite Bild zu verarbeiten. Der Leitfaden zur Live-Inferenz mit Streamlit verpackt diese Schleife in eine App für eine Browseroberfläche.
Beispiel: Jede Person nur einmal zählen#
„22 Personen pro Bild“ ist nicht die Zahl, die jemand wissen möchte; gefragt ist: „Wie viele Personen sind hindurchgegangen?“ Multi-Objekt-Verfolgung verknüpft Boxen über mehrere Bilder hinweg, und der Track-Modus weist jedem Objekt in boxes.id eine ID zu:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
seen = set()
for result in model.track(source, stream=True, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False):
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique people tracked")32 unique people trackedis_track ist False für Bilder, bevor ein Track bestätigt wurde, wenn boxes.id None ist. Verwende die IDs zum Zählen, für Trajektorien oder für Logik wie „Dieses Objekt ist seit 3 Sekunden hier“.

| Tracker | Geschwindigkeit | Robustheit |
|---|---|---|
bytetrack.yaml | Schneller, einfacher | Verliert IDs häufiger, wenn Objekte kurzzeitig verschwinden |
botsort.yaml | Langsamer | Behält IDs bei Kamerabewegungen besser bei (Bewegungskompensation; ReID anhand des Erscheinungsbilds ist über with_reid optional) |
Wenn du tracker weglässt, verwendet Ultralytics tracktrack.yaml, die aktuelle Standardeinstellung; im Track-Modus sind außerdem ocsort.yaml, deepocsort.yaml und fasttrack.yaml enthalten. Die Auswahl und Feinabstimmung von Trackern sowie die darauf aufbauende Objektzählung, Heatmaps und Geschwindigkeitsschätzung werden in Objekte mit ByteTrack, BoT-SORT und TrackTrack verfolgen behandelt.
Beispiel: Deine eigene Kameraschleife#
Reale Anwendungen lesen Bilder oft selbst ein – etwa um sie zu skalieren, zuzuschneiden, mit Zeitstempeln zu versehen oder eine Kamera mit anderem Code gemeinsam zu nutzen – und übergeben sie dann einzeln an das Modell. persist=True hält den Tracker zwischen den Aufrufen am Leben:
import cv2
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
cap = cv2.VideoCapture("solutions_ci_demo.mp4") # saved locally by the commands above; or 0, or an rtsp:// URL
seen = set()
while cap.isOpened():
ok, frame = cap.read()
if not ok:
break
result = model.track(frame, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False)[0]
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
cap.release()
print(f"{len(seen)} unique people, highest ID {max(seen)}")32 unique people, highest ID 67Dieselben 32 Personen wie bei track.py. Beachte, dass die höchste ID 67 und nicht 32 ist: Der Tracker vergibt auch IDs für vorläufige Tracks, die nie bestätigt werden, sodass Lücken entstehen.
Mit der Quelle Schritt halten#
Eine 30-FPS-Kamera liefert alle 33 ms ein Bild, und deine effektive Rate entspricht der langsamsten Phase: Dekodierung, Inferenz oder Schreiben. Auf unserem Laptop mit CPU dauerte yolo26n je nach sonstiger Auslastung des Rechners bei verschiedenen Durchläufen 26 bis 46 ms pro Bild mit einer Auflösung von 384×640: Das liegt am oder über dem Zeitbudget, ohne Spielraum. Wenn dein System nicht mithalten kann, probiere diese Stellschrauben der Reihe nach aus:
| Stellschraube | Auswirkung |
|---|---|
Kleineres Modell (n statt s) | Oft 2–3× schneller |
Niedrigeres imgsz (480 statt 640) | Weniger Pixel, weniger Rechenaufwand; kleine Objekte leiden zuerst |
vid_stride=2 | Halbiert den Aufwand; geeignet für Szenen mit langsamen Bewegungen |
| Eine GPU oder ein optimierter Export | Die größten Leistungssteigerungen — eine TensorRT-Engine auf NVIDIA oder INT8; mehr dazu in der nächsten Lektion |
Mehrere Kameras gleichzeitig und die dafür nötige Thread-Verarbeitung werden in Multi-Stream-Inferenz behandelt.
Diese Fehler vermeiden#
Symptom: Bei einer langen Aufnahme steigt der Speicherverbrauch, bis der Prozess abstürzt, oder ein Aufruf mit einer Live-Kamera kehrt nie zurück. Ursache: Ohne diese Option sammelt der Python-Aufruf vor der Rückgabe für jedes Bild ein Results-Objekt. Lösung: Übergebe stream=True und durchlaufe den Generator – er tut nichts, bis du ihn durchläufst.
Symptom: In cv2_loop.py ohne persist=True sank die Anzahl auf 27 und die höchste ID war ebenfalls 27: Die IDs wurden bei jedem Bild neu gestartet, sodass die „eindeutige“ Anzahl nur dem Bild mit den meisten Objekten entsprach. Lösung: Übergebe persist=True, wenn du track einmal pro Bild aufrufst.
Symptom: 67 gezählte Personen bei tatsächlich 32 Personen. Ursache: Nicht bestätigte Tracks verursachen Lücken in den IDs. Lösung: Zähle die Anzahl eindeutiger IDs in einer Menge, wie in track.py.
Der Standard-Tracker kann sich zwischen Versionen ändern. Übergib tracker="bytetrack.yaml" (oder den Tracker deiner Wahl), damit die Anzahlen über verschiedene Versionen hinweg vergleichbar bleiben.
Lösung anzeigen
import sys
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
seen, times = set(), []
for result in model.track(sys.argv[1], stream=True, persist=True, tracker="bytetrack.yaml", verbose=False):
times.append(result.speed["inference"])
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique objects, {sum(times) / len(times):.1f} ms inference per frame")Führe es mit python track_any.py your_video.mp4 aus.
32 unique objects, 30.5 ms inference per frame (26-46 ms across runs on a laptop CPU)
Source is 30 FPS -> 33 ms budget: fits only on a quiet machine, with no headroom
First lever: export to OpenVINO or ONNX for this CPU, then vid_stride=2 if still short