Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Get Started
Addestra il tuo primo modello YOLO·Distribuisci·Lezione 9/10
Lezioneprincipiante

Esegui l'inferenza sui video

Esegui YOLO26 su file video e telecamere in diretta con memoria limitata, traccia gli oggetti per contarli una sola volta e verifica che il modello riesca a tenere il passo con la frequenza dei fotogrammi.

La maggior parte dei sistemi di visione distribuiti analizza video: telecamere sopra nastri trasportatori, porte e strade. I video presentano due problemi che le singole immagini non hanno. Memoria: una registrazione lunga non può essere mantenuta nella RAM. Identità: un rilevatore vede la stessa persona in 60 fotogrammi e segnala 60 persone.

In questa lezione trasmetterai il video in streaming, un fotogramma alla volta, con la modalità Predict, aggiungerai il tracciamento degli oggetti per contare ogni persona una sola volta, scriverai un ciclo personalizzato per la telecamera e misurerai se il modello riesce a tenere il passo.

Esito

Puoi trasmettere in streaming un video o il flusso di una telecamera con YOLO26 usando una quantità di memoria limitata, contare gli oggetti unici con il tracking e decidere, in base ai millisecondi misurati per fotogramma, se il modello riesce a tenere il passo con la sorgente.

Percorso rapido
Se sai già come muoverti, ecco la versione breve.
  1. model(video, stream=True) genera un Results per fotogramma, usando una quantità di memoria limitata.

  2. model.track(video, stream=True, persist=True, tracker='bytetrack.yaml') aggiunge boxes.id.

  3. Conta gli oggetti unici usando un insieme di ID, mai l'ID più alto.

  4. Budget = 1000 ÷ FPS della sorgente; confrontalo con result.speed['inference'].

Pratico

Esempio svolto: eseguire Predict su un file video#

I video vengono elaborati con la stessa modalità Predict delle immagini. Questa clip di 62 fotogrammi mostra persone che attraversano un atrio:

yolo predict model=yolo26n.pt source=https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4
video 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/predict
  • frame 1/62: Ultralytics decodifica il video ed elabora ogni fotogramma come un'immagine.
  • 22 persons: rilevamenti in quel fotogramma. Le stesse persone che camminano vengono conteggiate di nuovo in ogni fotogramma.
  • 27.3ms ... 54.8ms: il tempo per fotogramma varia in base alle altre attività in corso sulla macchina.

Il video annotato è runs/detect/predict/solutions_ci_demo.mp4. Il tuo modello funziona allo stesso modo: sostituisci yolo26n.pt con runs/detect/pills_v1/weights/best.pt.

Trasmetti in streaming sorgenti lunghe e dal vivo#

Per eseguire codice che agisce sui rilevamenti, usa un ciclo sul flusso. A ogni iterazione ottieni i Results di un fotogramma, che poi vengono scartati:

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 frame

Lo stesso ciclo accetta l'indice di una webcam (source=0) o un URL della telecamera, ad esempio rtsp://camera.local/stream, e continua finché il flusso non termina o non lo interrompi. Aggiungi vid_stride=2 per elaborare un fotogramma ogni due. Per un'interfaccia browser basata su questo ciclo, la guida Inferenza dal vivo con Streamlit lo integra in un'app.

Esempio svolto: contare ogni persona una sola volta#

«22 persone per fotogramma» non è il dato che interessa; la domanda è «quante persone sono passate?». Il tracking multi-oggetto collega i riquadri tra i fotogrammi e la modalità Track assegna a ogni oggetto un ID in boxes.id:

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 tracked

is_track è False nei fotogrammi precedenti alla conferma di una traccia, quando boxes.id è None. Usa gli ID per contare, tracciare traiettorie o implementare logiche come «questo oggetto è qui da 3 secondi».

Tracking di Ultralytics YOLO su un'autostrada: ogni auto, autobus e camion è contrassegnato da un'etichetta ID persistente e da una traccia del movimento

TrackerVelocitàRobustezza
bytetrack.yamlPiù veloce e semplicePerde gli ID più spesso quando gli oggetti scompaiono brevemente
botsort.yamlPiù lentoMantiene meglio gli ID quando la telecamera si muove (compensazione del movimento; ReID basato sull'aspetto attivabile facoltativamente tramite with_reid)

Se ometti tracker, Ultralytics usa tracktrack.yaml, l'impostazione predefinita attuale; la modalità Track include anche ocsort.yaml, deepocsort.yaml e fasttrack.yaml. La scelta e la configurazione dei tracker, oltre alla realizzazione di contatori di oggetti, mappe di calore e stima della velocità, sono trattate nella guida Traccia gli oggetti con ByteTrack, BoT-SORT e TrackTrack.

Esempio svolto: il tuo ciclo personalizzato per la telecamera#

Spesso le applicazioni reali leggono direttamente i fotogrammi — per ridimensionarli, ritagliarli, aggiungere timestamp o condividere una telecamera con altro codice — e passano ciascun fotogramma al modello. In questo caso, persist=True mantiene attivo il tracker tra una chiamata e l'altra:

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 67

Lo stesso conteggio di 32 persone di track.py. Nota che l'ID più alto è 67, non 32: il tracker assegna ID anche alle tracce provvisorie che non vengono mai confermate, quindi ci sono dei salti nella sequenza degli ID.

Tieni il passo con la sorgente#

Una telecamera a 30 FPS fornisce un fotogramma ogni 33 ms; la frequenza effettiva è determinata dall'operazione più lenta tra decodifica, inferenza e scrittura. Sulla CPU del nostro laptop, yolo26n ha impiegato da 26 a 46 ms per fotogramma da 384×640 nelle varie esecuzioni, a seconda delle altre attività in corso sulla macchina: il tempo era pari o superiore al budget, senza margine. Se il tuo sistema non riesce a tenere il passo, prova queste soluzioni nell'ordine indicato:

SoluzioneEffetto
Modello più piccolo (n invece di s)Spesso da 2 a 3 volte più veloce
Riduci imgsz (480 invece di 640)Meno pixel e meno calcolo; gli oggetti piccoli sono i primi a risentirne
vid_stride=2Dimezza il lavoro; adatto alle scene con movimenti lenti
Una GPU o un'esportazione ottimizzataI miglioramenti maggiori: un motore TensorRT su NVIDIA oppure INT8; consulta la prossima lezione

La guida Inferenza multi-stream tratta l'uso simultaneo di più telecamere e il threading necessario.

Evita questi errori#

Dimenticare stream=True

Sintomo: la memoria aumenta finché il processo non si interrompe durante una registrazione lunga, oppure una chiamata alla videocamera in diretta non termina mai. Causa: senza questo parametro, la chiamata Python raccoglie un oggetto Results per ogni frame prima di restituire i risultati. Soluzione: passa stream=True e itera sul generatore: non fa nulla finché non lo iteri.

Dimenticare persist=True nel proprio ciclo

Sintomo: in cv2_loop.py senza persist=True, il conteggio è sceso a 27 e anche l'ID più alto era 27: gli ID ripartivano a ogni frame, quindi il conteggio «univoco» rappresentava solo il frame più affollato. Soluzione: passa persist=True ogni volta che chiami track una volta per frame.

Contare in base all'ID più alto

Sintomo: un conteggio di 67 per 32 persone. Causa: gli ID presentano lacune dovute alle tracce non confermate. Soluzione: conta il numero di elementi di un insieme di ID, come in track.py.

Specifica esplicitamente il tracker

Il tracker predefinito può cambiare da una versione all'altra. Passa tracker="bytetrack.yaml" (o il tracker che preferisci) per mantenere confrontabili i conteggi tra versioni.

Provalo

Esegui track_any.py (nella soluzione) sulla clip dimostrativa, poi su un breve video girato da te. Consegna un rapporto di tre righe: il conteggio degli oggetti unici, il tempo medio di inferenza in ms per fotogramma e se rientra nell'intervallo tra i fotogrammi della sorgente, indicando la prima soluzione che proveresti in caso contrario. Salva un output annotato con yolo track ... save=True e annota se gli ID restano stabili durante le occlusioni; se cambiano frequentemente, prova tracker=botsort.yaml.

Criteri di completamento
La lezione è completata quando tutte le seguenti condizioni sono soddisfatte.
  • Hai salvato un video annotato da yolo predict o yolo track.

  • Lo script di streaming stampa il conteggio degli oggetti unici ricavato da un insieme di valori boxes.id.

  • Hai confrontato i millisecondi misurati per fotogramma con l'intervallo tra i fotogrammi della sorgente e hai indicato la prima soluzione per aumentare la velocità.

Mostra la soluzione
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")

Eseguilo con python track_any.py your_video.mp4.

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
Prossimi passi

Il tuo modello funziona con immagini e video in Python. Ultimo passaggio: esportalo in un formato caricabile da un runtime di produzione.

Accedi per salvare i progressi