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.
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.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 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 frameLo 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 trackedis_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».

| Tracker | Velocità | Robustezza |
|---|---|---|
bytetrack.yaml | Più veloce e semplice | Perde gli ID più spesso quando gli oggetti scompaiono brevemente |
botsort.yaml | Più lento | Mantiene 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 67Lo 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:
| Soluzione | Effetto |
|---|---|
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=2 | Dimezza il lavoro; adatto alle scene con movimenti lenti |
| Una GPU o un'esportazione ottimizzata | I 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#
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.
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.
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.
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.
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