Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Get Started
Lezioneprincipiante

Prepara un dataset personalizzato

Organizza immagini ed etichette nel formato Ultralytics YOLO, converti i riquadri in pixel in righe di etichette normalizzate e individua le etichette non valide prima dell'addestramento.

Una cartella con un nome errato o un'etichetta non normalizzata non blocca l'addestramento. Ultralytics salta le immagini non valide e continua, quindi addestri il modello solo su una parte dei dati, ottieni un modello mediocre e perdi un pomeriggio a cercare la causa nel posto sbagliato.

Questa lezione tratta la parte pratica di un dataset di rilevamento: cartelle, righe di etichette, conversione e controlli. Lavorerai con il vero dataset di pillole medicinali di 115 immagini, usato per l'addestramento nel resto del corso. La decisione su cosa raccogliere e come annotarlo è trattata nelle Migliori pratiche di annotazione.

Esito

Puoi organizzare un dataset nel formato Ultralytics YOLO, convertire i riquadri in pixel in righe di etichette normalizzate e individuare etichette mancanti o corrotte dalla riga di scansione prima dell'addestramento.

Percorso rapido
Se sai già come muoverti, ecco la versione breve.
  1. Crea images/{train,val} e labels/{train,val} con nomi di file corrispondenti.

  2. Scrivi una riga class x_center y_center width height per oggetto, con tutti i valori compresi tra 0 e 1.

  3. Converti i riquadri in pixel dividendo per la larghezza e l'altezza dell'immagine.

  4. Visualizza un file di etichette sulla relativa immagine e verifica che la riga di scansione riporti 0 corrupt.

Pratico

Ottieni il dataset di esercitazione#

Finestra Nuovo dataset di Ultralytics Platform: un'area per trascinare immagini, video o dataset YOLO, COCO e NDJSON, poi nome, URL, descrizione e tipo di attività

La struttura riportata di seguito è accettata anche come file zip dalla finestra Nuovo dataset di Ultralytics Platform, quindi il dataset che prepari qui può essere caricato senza modifiche. Scarica 92 fotogrammi di addestramento e 23 di convalida di pillole in blister, quindi estraili in my_dataset:

curl -L -o medical-pills.zip https://github.com/ultralytics/assets/releases/download/v0.0.0/medical-pills.zip
unzip -q medical-pills.zip -d my_dataset
my_dataset/
├── images/
│   ├── train/   Frame_0.jpg, Frame_100.jpg, ... (92 images)
│   └── val/     Frame_144.jpg, ... (23 images)
└── labels/
    ├── train/   Frame_0.txt, Frame_100.txt, ... (92 files)
    └── val/     Frame_144.txt, ... (23 files)

Non c'è un file manifest. Ultralytics trova ogni etichetta sostituendo /images/ con /labels/ nel percorso dell'immagine e sostituendo l'estensione con .txt, quindi images/val/Frame_144.jpg legge labels/val/Frame_144.txt. Ne conseguono due cose:

  • Le cartelle devono chiamarsi esattamente images e labels ed essere affiancate.
  • Un'immagine con un file di etichette vuoto o mancante è un'immagine di sfondo: è valida e utile per insegnare al modello cosa non rilevare, ma solo se è quello che intendevi.

Leggi una riga di etichetta#

File di etichette YOLO per zidane.jpg, una riga per oggetto: indice della classe, poi centro x, centro y, larghezza e altezza normalizzati

Ogni riga rappresenta un oggetto: un indice di classe intero, poi il centro e le dimensioni del riquadro di delimitazione come frazioni della larghezza e dell'altezza dell'immagine. Una riga reale da labels/train/Frame_0.txt:

0 0.330729 0.816204 0.103125 0.121296
  • 0: indice di classe 0, che nel file YAML corrisponderà al nome pill.
  • 0.330729 0.816204: il centro del riquadro si trova al 33% della larghezza e all'82% dell'altezza.
  • 0.103125 0.121296: il riquadro è largo circa il 10% dell'immagine e alto il 12%.

Esempio pratico: converti un riquadro in pixel#

Gli strumenti di annotazione spesso esportano le coordinate degli angoli in pixel (x1, y1, x2, y2). Dividile per le dimensioni dell'immagine. La persona più a sinistra nell'immagine bus.jpg da 810×1080 dell'ultima lezione si estende da (49, 398) a (240, 902):

CampoFormulaValore
x_center(x1 + x2) / 2 / larghezza(49 + 240) / 2 / 810 = 0.178395
y_center(y1 + y2) / 2 / altezza(398 + 902) / 2 / 1080 = 0.601852
width(x2 − x1) / larghezza191 / 810 = 0.235802
height(y2 − y1) / altezza504 / 1080 = 0.466667

La maggior parte degli strumenti di annotazione, e strumenti come Roboflow, possono esportare direttamente nel formato YOLO. Per COCO JSON, segui la guida all'addestramento con COCO JSON; il repository JSON2YOLO tratta altri formati. Per i file XML Pascal VOC, la formula qui sopra si presta a uno script breve:

import xml.etree.ElementTree as ET
from pathlib import Path

CLASSES = ["person", "bus"]  # index = class id; must match names in data.yaml

def voc_to_yolo(xml_file: Path, out_dir: Path) -> None:
    root = ET.parse(xml_file).getroot()
    w, h = int(root.find("size/width").text), int(root.find("size/height").text)
    lines = []
    for obj in root.iter("object"):
        name = obj.find("name").text
        if name not in CLASSES:
            continue
        box = obj.find("bndbox")
        x1, y1, x2, y2 = (float(box.find(k).text) for k in ("xmin", "ymin", "xmax", "ymax"))
        xc, yc, bw, bh = (x1 + x2) / 2 / w, (y1 + y2) / 2 / h, (x2 - x1) / w, (y2 - y1) / h
        lines.append(f"{CLASSES.index(name)} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}")
    out_dir.mkdir(parents=True, exist_ok=True)
    (out_dir / f"{xml_file.stem}.txt").write_text("\n".join(lines) + "\n")

voc_to_yolo(Path("bus.xml"), Path("labels"))
print(Path("labels/bus.txt").read_text())

Eseguito su un bus.xml che contiene i riquadri della persona e dell'autobus della lezione precedente, stampa l'esempio pratico e quello dell'autobus:

0 0.178395 0.601852 0.235802 0.466667
1 0.495679 0.454167 0.991358 0.482407

Controlla prima di addestrare#

Visualizza alcuni file di etichette sulle relative immagini. Una classe spostata, le coordinate x e y scambiate o riquadri attorno alle ombre sono evidenti a occhio, ma invisibili nelle metriche:

from ultralytics.data.utils import visualize_image_annotations

visualize_image_annotations(
    "my_dataset/images/train/Frame_0.jpg",
    "my_dataset/labels/train/Frame_0.txt",
    {0: "pill"},
)

Poi lascia che Ultralytics controlli ogni file. La prima volta che legge un dataset, analizza le etichette e decide riga per riga se ogni immagine è utilizzabile:

La riga di scansione riporta il risultato: 23 images, 0 backgrounds, 0 corrupt indica un dataset in buono stato. Qualsiasi altro risultato corrisponde a uno degli errori qui sotto.

Evita questi errori#

Normalizzazione dimenticata

Sintomo: ignoring corrupt image/label: non-normalized or out of bounds coordinates [634. 881. 198. 163.] e un conteggio corrupt diverso da zero. Causa: hai usato i valori dei pixel anziché le frazioni. Soluzione: dividi per la larghezza e l'altezza dell'immagine. Qualsiasi valore dell'etichetta superiore a 1 indica che il riquadro non è mai stato normalizzato.

Cartella delle etichette con nome errato

Sintomo: yolo val esamina 0 images, 23 backgrounds e avvisa No labels found, poi l'addestramento si interrompe con ValueError: train: No labels found — in questo caso perché la cartella delle etichette si chiamava annotations. Soluzione: assegna esattamente alle cartelle i nomi images e labels, mantenendo corrispondenti i nomi dei file.

Gli indici delle classi partono da 1

Sintomo: Label class 1 exceeds dataset class count 1. Possible class labels are 0-0. Causa: lo strumento di esportazione ha numerato le classi a partire da 1. Soluzione: le classi YOLO partono da 0; sottrai 1 nello script di conversione oppure correggi l'impostazione di esportazione.

Angoli e centri

Se i riquadri risultano spostati di mezzo riquadro verso il basso e a destra, hai scritto x1 y1 w h invece di x_center y_center w h. Disegnare un singolo file permette di accorgersene in pochi secondi; nessun controllo di scansione può farlo.

Per controlli sistematici su un intero dataset, consulta Controllo qualità dei dataset. I dataset integrati come coco8, coco128 e african-wildlife sono buoni esempi di struttura da copiare; la panoramica dei dataset li elenca tutti. Il trainer applica l'aumento dei dati alle tue etichette, quindi una rapida pulizia dei dati in questa fase è utile a ogni epoca.

Provalo

Scarica il dataset di pillole in my_dataset. Fornisci tre verifiche: il numero di immagini ed etichette per ogni suddivisione, l'output di uno script che stampa qualsiasi valore di etichetta fuori dall'intervallo 0–1 (non dovrebbe stampare nulla) e un file di etichette visualizzato sulla relativa immagine con visualize_image_annotations. Se hai immagini annotate tue, convertili nello stesso formato e visualizzane una.

Criteri di completamento
La lezione è completata quando tutte le seguenti condizioni sono soddisfatte.
  • my_dataset contiene images/train, images/val, labels/train e labels/val, con nomi di file e conteggi corrispondenti.

  • Lo script di controllo non rileva valori di etichetta fuori dall'intervallo 0–1.

  • Hai visualizzato almeno un file di etichette sulla relativa immagine e i riquadri corrispondono alle pillole.

Mostra la soluzione
for s in train val; do
  echo "$s: $(ls my_dataset/images/$s | wc -l) images, $(ls my_dataset/labels/$s | wc -l) labels"
done
# train: 92 images, 92 labels
# val:   23 images, 23 labels
from pathlib import Path

for txt in Path("my_dataset/labels").rglob("*.txt"):
    for line in txt.read_text().splitlines():
        values = [float(v) for v in line.split()[1:]]
        if any(v < 0 or v > 1 for v in values):
            print(txt, line)

Se lo script non produce output, tutte le coordinate sono normalizzate. Conteggi uguali per ogni suddivisione indicano che ogni immagine ha un file di etichette; la riga di scansione della prossima lezione confermerà che non ce ne sono di corrotti.

Prossimi passi

Le cartelle sono pronte. Ora scrivi l'unico file YAML che indica a Ultralytics dove si trovano e cosa significano le classi.

Accedi per salvare i progressi