Raccogli dati rappresentativi e di alta qualità
Acquisisci immagini in condizioni reali di deployment, inserisci i metadati di acquisizione in ogni nome file, monitora la copertura rispetto alla specifica e campiona i video senza sovraccaricare il dataset.
La maggior parte dei problemi dei dataset deriva dalla raccolta. Un team acquisisce esempi puliti con una sola telecamera in una sola settimana, la validazione sembra ottima e il modello fallisce completamente nel secondo sito. La raccolta determina il limite massimo: nessuna qualità delle etichette, tecnica di data augmentation o iperparametro può insegnare al modello una scena che non è mai comparsa nel dataset.
Pratico
La variabilità vale più del volume#
Confronta due dataset destinati allo stesso deployment:
| Dataset | Risultato della validazione | In produzione |
|---|---|---|
| 10.000 fotogrammi quasi identici, una telecamera, solo a mezzogiorno | Alto: i fotogrammi di validazione somigliano a quelli di training | Peggiora con una telecamera diversa e al tramonto |
| 1.500 fotogrammi distribuiti tra 12 scenari della specifica | Più contenuto | Regge, perché la produzione somiglia ai dati |
Il punteggio di validazione del primo dataset è alto solo perché la validazione misura l'unica condizione che copre. In produzione, un modello è valido solo quanto lo scenario meno coperto che incontra. Dai la priorità alla copertura della specifica e solo dopo al volume.
Scegli le fonti nel giusto ordine#
La maggior parte del dataset dovrebbe provenire dalla configurazione di produzione reale. La guida alla raccolta e all'annotazione dei dati approfondisce ciascuna fonte:
| Fonte | Quando è utile | Quando è problematico |
|---|---|---|
| Telecamere di produzione, in diretta | Più vicine al deployment | Lente; potrebbero servire accordi per i dati |
| Telecamere di produzione, archiviati | Molte varianti in poco tempo | I vecchi filmati potrebbero non corrispondere alla configurazione attuale |
| Dataset pubblici (COCO, Open Images, VOC) | Avvio con classi comuni | Differenze di dominio rispetto alle tue scene |
| Acquisizioni messe in scena | Casi limite specifici su richiesta | Troppo pulite; è facile farci eccessivo affidamento |
| Immagini sintetiche o generate | Pericoli e guasti rari che non puoi aspettare che si verifichino | Il modello potrebbe apprendere lo stile del generatore |
| Raccolta dal web | Varietà a basso costo | Qualità incostante e rischi legati alle licenze |
Usa immagini messe in scena, pubbliche e sintetiche per colmare lacune specifiche indicate nella specifica e monitora la loro quota nel dataset, così da poter valutare se sono utili. Su Ultralytics Platform, Genera immagini simili aggiunge a un dataset varianti generate di un'immagine esistente, senza etichette e pronte per l'annotazione.
Inserisci i metadati nel nome file#
Ogni immagine deve includere almeno un ID della telecamera, il giorno di acquisizione e il numero del fotogramma o della clip. Senza questi dati non puoi suddividere il dataset per gruppo in seguito, risalire alla fonte di una regressione o raccogliere altri dati di uno scenario sottorappresentato. Il modo più duraturo per conservarli è il nome file: cam2_2026-05-01_000124.jpg è compatibile con qualsiasi strumento, esportazione e caricamento. La ricerca nei dataset di Ultralytics Platform supporta i nomi file e i metadati personalizzati, così queste chiavi restano ricercabili anche dopo il caricamento.
Questo script crea il dataset di esercitazione usato nel resto del corso. Copia le immagini etichettate di COCO128 e le rinomina come se quattro telecamere le avessero acquisite nell'arco di quattro giorni, sovracampionando cam1 come spesso accade con la telecamera più comoda:
import shutil
from pathlib import Path
from ultralytics.data.utils import check_det_dataset, img2label_paths
data = check_det_dataset("coco128.yaml") # 128 COCO images stand in for your camera captures
out = Path("datasets/practice")
(out / "images").mkdir(parents=True, exist_ok=True)
(out / "labels").mkdir(parents=True, exist_ok=True)
for i, image in enumerate(sorted(Path(data["train"]).glob("*.jpg"))):
camera = ("cam1", "cam1", "cam2", "cam3", "cam4")[i % 5] # cam1 over-collected, like a real site
name = f"{camera}_2026-05-0{i // 32 + 1}_{i:06d}" # camera, capture day, frame number
shutil.copy(image, out / "images" / f"{name}.jpg")
label = Path(img2label_paths([str(image)])[0])
if label.exists():
shutil.copy(label, out / "labels" / f"{name}.txt")
print(len(list((out / "images").glob("*.jpg"))), "images written to", out)128 images written to datasets/practice
Il caricamento su Ultralytics Platform mantiene questi nomi file. La finestra di caricamento accetta anche video e interi dataset; tra le impostazioni è inclusa la sfocatura dei volti per la privacy.
Monitora la copertura rispetto alla specifica#
Con i metadati nei nomi file, la copertura si misura contando. Definisci le quote in base alla tua specifica e lascia che lo script indichi cosa raccogliere in seguito:
from collections import Counter
from pathlib import Path
QUOTA = {"cam1": 30, "cam2": 30, "cam3": 30, "cam4": 30} # images per camera, from your spec
images = sorted(Path("datasets/practice/images").glob("*.jpg"))
cameras = Counter(p.stem.split("_")[0] for p in images)
days = Counter(p.stem.split("_")[1] for p in images)
for camera, quota in QUOTA.items():
gap = quota - cameras[camera]
print(f"{camera}: {cameras[camera]:3d} / {quota} {'ok' if gap <= 0 else f'collect {gap} more'}")
print("days:", dict(sorted(days.items())))cam1: 52 / 30 ok
cam2: 26 / 30 collect 4 more
cam3: 25 / 30 collect 5 more
cam4: 25 / 30 collect 5 more
days: {'2026-05-01': 32, '2026-05-02': 32, '2026-05-03': 32, '2026-05-04': 32}La regola decisionale: smetti di raccogliere da qualsiasi fonte che abbia superato la quota e concentra gli sforzi sulle lacune. In questo caso, cam1 copre già il 40% delle immagini. Un'altra settimana di filmati da questa fonte aumenterebbe il volume, ma non la copertura.
Campiona i video senza sovraccaricare il dataset#
Il video è la fonte meno costosa e la più facile da usare male. A 30 fotogrammi al secondo, un minuto produce 1.800 fotogrammi quasi identici; etichettare due volte lo stesso momento costa e gonfia le metriche. Conserva un fotogramma solo quando la scena è cambiata rispetto all'ultimo fotogramma mantenuto:
from pathlib import Path
import cv2
from ultralytics.utils.downloads import safe_download
video = "solutions_ci_demo.mp4" # a short public demo clip; swap in your own footage
safe_download(f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{video}")
Path("frames").mkdir(exist_ok=True)
cap = cv2.VideoCapture(video)
fps = cap.get(cv2.CAP_PROP_FPS)
read = kept = 0
last = None
while True:
ok, frame = cap.read()
if not ok:
break
thumb = cv2.cvtColor(cv2.resize(frame, (64, 64)), cv2.COLOR_BGR2GRAY).astype(float)
if last is None or abs(thumb - last).mean() > 10: # keep a frame only when the scene has changed
cv2.imwrite(f"frames/clip01_{read:06d}.jpg", frame) # the clip ID stays in the filename
kept, last = kept + 1, thumb
read += 1
print(f"{read} frames at {fps:.0f} FPS -> {kept} kept")62 frames at 30 FPS -> 6 keptLa clip di due secondi contiene 62 fotogrammi, ma solo 6 momenti visivamente distinti. Lo script confronta piccole miniature in scala di grigi, quindi elabora rapidamente anche ore di filmati. Aumenta la soglia di 10 per conservare meno fotogrammi dalle telecamere statiche; abbassala per le scene in rapido movimento. Distribuisci il budget anche tra le clip: 20 fotogrammi da ciascuna di 50 clip sono meglio di 1.000 fotogrammi da una sola.
Due fotogrammi separati da un secondo condividono l'illuminazione, lo sfondo e di solito gli stessi oggetti. Se finiscono sia nell'addestramento sia nella validazione, il modello viene valutato su immagini che ha già visto in pratica. Includi l'ID del video in ogni nome di file, così Suddividere correttamente il dataset può mantenere uniti i fotogrammi dello stesso video.
Evita le insidie nella raccolta#
| Insidia | Sintomo | Soluzione |
|---|---|---|
| Raccolta concentrata in una sola settimana | mAP di validazione elevata, ma mancate rilevazioni in altre stagioni o nei turni | Distribuisci le acquisizioni su più settimane o mesi |
| Una sola videocamera | Non funziona con la seconda videocamera | Acquisisci immagini da ogni tipo di videocamera che prevedi di usare |
| Solo dati messi in scena | Non funziona in presenza di disordine reale | Mantieni le immagini messe in scena come minoranza limitata e monitorata |
| Fotogrammi duplicati | Metriche gonfiate, tempo di etichettatura sprecato | Campiona in base ai cambiamenti della scena; Ultralytics Platform salta anche le copie esatte durante il caricamento |
| Un solo operatore o turno | Aspetto non previsto e squilibrio tra le classi | Campiona immagini di turni, sedi e persone diversi |
| Casi rari mancanti | Non rileva gli eventi di sicurezza più importanti | Acquisizione mirata, messa in scena o integrazione con dati sintetici |
Distorsioni e consenso#
La distorsione è un problema di raccolta, non di modellazione: nessun iperparametro può correggere l'assenza di un gruppo mai incluso nei dati. La guida alla raccolta dei dati elenca quattro leve: fonti diversificate, rappresentazione equilibrata, verifiche regolari della copertura e misure di mitigazione come il sovracampionamento dei gruppi sottorappresentati.
Se le immagini contengono volti, targhe o altri dati personali, devi ottenere il consenso e definire una policy di conservazione prima di iniziare la raccolta. La voce del glossario sulla privacy dei dati è un buon punto di partenza, mentre Privacy, aree geografiche e conformità spiega come conservare i dati nella giurisdizione corretta con dataRegion.
Mostra la soluzione
Per il set di esercitazione, il rapporto sulla copertura fornisce un piano diretto:
| Fonte | Conteggio / quota | Azione |
|---|---|---|
cam1 | 52 / 30 | Interrompi la raccolta: rappresenta già il 40% di tutte le immagini |
cam2 | 26 / 30 | Raccogline altre 4 |
cam3 | 25 / 30 | Raccogline altre 5 |
cam4 | 25 / 30 | Raccogline altre 5 |
Ogni videocamera copre tutti e quattro i giorni, quindi le lacune riguardano le videocamere, non i giorni. Distribuisci le 14 nuove immagini su almeno due nuovi giorni, in modo che introducano una nuova condizione invece di aggiungere altre immagini dello stesso pomeriggio. Se una videocamera non può colmare la propria lacuna (una videocamera che riprende solo di notte), aggiungi una riga alle specifiche per la condizione mancante e indica se la colmano immagini messe in scena o generate, così da poterne misurare l'effetto in seguito.