Disegnare bounding box per il rilevamento di oggetti
Crea in Potato un task di rilevamento di oggetti, da una configurazione iniziale con tre etichette a una da produzione per riprese di guida, poi esporta in COCO o YOLO.
Questo tutorial costruisce in Potato un task di annotazione per il rilevamento di oggetti, partendo da una configurazione con tre etichette fino all'esportazione COCO o YOLO su cui si addestra un rilevatore. Per l'elenco completo degli strumenti per immagini e delle loro opzioni, vedi la documentazione sull'annotazione di immagini.
Il file di dati
Ogni riga del file di dati è un'immagine. Potato ha bisogno di un identificativo e di un campo con l'URL o il percorso dell'immagine, e item_properties indica quale campo è quale:
{"id": "img_001", "image_url": "https://example.com/street_001.jpg"}
{"id": "img_002", "image_url": "/static/images/street_002.jpg"}Un percorso relativo viene risolto rispetto a media_directory, quindi le immagini locali non richiedono un file server in esecuzione.
Una configurazione minima
Lo schema image_annotation gestisce la superficie di disegno. Richiede un nome, una descrizione che gli annotatori leggono come istruzione, gli strumenti da attivare e l'insieme delle etichette:
annotation_task_name: "Object Detection Annotation"
task_dir: "."
output_annotation_dir: "annotation_output/"
data_files:
- "data/images.json"
item_properties:
id_key: id
text_key: image_url
annotation_schemes:
- annotation_type: image_annotation
name: objects
description: "Draw a box around every car, person, and bicycle"
tools:
- bbox
labels:
- name: car
color: "#FF6B6B"
- name: person
color: "#4ECDC4"
- name: bicycle
color: "#45B7D1"Tre etichette sono un punto di partenza voluto. Ogni etichetta in più è una decisione che l'annotatore deve prendere su ogni oggetto, e un caso limite su cui va istruito, quindi parti dalle classi di cui il modello ha davvero bisogno e aggiungi le altre quando le linee guida reggono.
Avvia il server e apri il task:
potato start config.yaml -p 8000Cosa fa l'annotatore
L'annotatore sceglie un'etichetta, poi trascina un rettangolo attorno a ogni oggetto, regolando gli angoli finché il riquadro non è aderente:
Lo strumento bounding box permette di disegnare ed etichettare regioni rettangolari sulle immagini
Zoom e spostamento sono attivi per impostazione predefinita, cosa che conta per gli oggetti piccoli o lontani. Puoi disattivarli entrambi con zoom_enabled: false e pan_enabled: false quando le immagini sono uniformi e i controlli in più sono solo d'intralcio.
Scorciatoie per le etichette
Con il profilo di tasti predefinito v7, gli strumenti usano tasti con lettere, quindi r seleziona lo strumento riquadro, p il poligono e b il pennello. Le scorciatoie si impostano per ogni etichetta con key_value, e le cifre sono la scelta sicura, perché un'etichetta il cui key_value coincide con un tasto di strumento attiva entrambe le azioni insieme:
annotation_schemes:
- annotation_type: image_annotation
name: objects
description: "Annotate all visible objects"
tools:
- bbox
labels:
- name: person
color: "#FF6B6B"
key_value: "1"
- name: car
color: "#4ECDC4"
key_value: "2"
- name: motorcycle
color: "#45B7D1"
key_value: "3"
- name: bicycle
color: "#96CEB4"
key_value: "4"
- name: traffic_light
color: "#FFEAA7"
key_value: "5"
- name: stop_sign
color: "#DDA0DD"
key_value: "6"Vale la pena scegliere i colori invece di accettare quelli predefiniti. Nelle scene di traffico dense l'annotatore scorre l'immagine cercando ciò che gli è sfuggito, e due colori simili su classi vicine rallentano questa ricerca. Imposta keybinding_profile: legacy se i tuoi annotatori hanno imparato i tasti di Potato precedenti alla 2.8 e preferisci non riaddestrarli.
Aggiungere attributi agli oggetti
Potato non ha un blocco di attributi per singolo riquadro. Di un'etichetta di image_annotation vengono letti name, color e key_value, e tutto il resto nel dizionario dell'etichetta viene scartato, quindi una lista annidata attributes: non ha alcun effetto e dopo aver disegnato un riquadro non compare nessuna domanda.
Ci sono due modi per raccogliere la stessa informazione. Puoi inserire la distinzione nell'insieme delle etichette, così l'attributo fa parte di ciò che l'annotatore sceglie:
annotation_schemes:
- annotation_type: image_annotation
name: objects
description: "Draw a box around each object"
tools:
- bbox
labels:
- name: person
color: "#FF6B6B"
- name: person_occluded
color: "#C44536"Oppure puoi chiedere dell'immagine nel suo complesso con un secondo schema. Questo si applica all'elemento e non a un singolo riquadro, ed è questo il compromesso. Sai che qualcosa nell'immagine era occluso, ma non quale riquadro fosse:
- annotation_type: multiselect
name: image_conditions
description: "Conditions affecting this image"
labels:
- Heavy occlusion
- Truncated objects
- Low lightL'importazione da VIA è l'unico caso in cui gli attributi si conservano. via_importer legge i region_attributes di ogni regione e li incorpora nell'etichetta. È un concetto legato all'importazione, non alla configurazione.
Richiedere almeno un riquadro
Un'immagine senza riquadri è ambigua, perché può voler dire che l'annotatore non ha trovato nulla oppure che ha saltato l'elemento. min_annotations impone la distinzione rifiutando un invio con meno forme del minimo, così un'immagine davvero vuota richiede un'etichetta negativa esplicita:
annotation_schemes:
- annotation_type: image_annotation
name: objects
description: "Draw a box around every traffic participant"
tools:
- bbox
labels: [...]
min_annotations: 1Controllare le dimensioni di visualizzazione dell'immagine
La superficie di disegno segue l'immagine visualizzata, quindi un'immagine mostrata in piccolo dà all'annotatore una tela piccola. instance_display imposta le dimensioni, e lo zoom resta disponibile per il lavoro di dettaglio:
instance_display:
fields:
- key: image_url
type: image
label: "Frame"
display_options:
max_width: 1200
max_height: 800
zoomable: trueUna configurazione da produzione
La configurazione di guida qui sotto contiene le cinque classi di cui ha bisogno un dataset di rilevamento. Le etichette mantengono le scorciatoie numeriche, così la mano sinistra dell'annotatore resta sulla fila dei numeri, e min_annotations: 1 regge perché ogni fotogramma di questo corpus contiene almeno un utente della strada:
annotation_task_name: "Autonomous Driving - Object Detection"
task_dir: "."
output_annotation_dir: "annotation_output/"
data_files:
- "data/driving_frames.json"
item_properties:
id_key: id
text_key: frame_path
annotation_schemes:
- annotation_type: image_annotation
name: objects
description: "Annotate all traffic participants and objects"
tools:
- bbox
min_annotations: 1
labels:
- name: vehicle
color: "#FF6B6B"
key_value: "1"
- name: pedestrian
color: "#4ECDC4"
key_value: "2"
- name: cyclist
color: "#45B7D1"
key_value: "3"
- name: traffic_sign
color: "#FFEAA7"
key_value: "4"
- name: traffic_light
color: "#DDA0DD"
key_value: "5"Cinque classi sono già al limite di ciò che le scorciatoie numeriche coprono comodamente. Oltre dieci l'annotatore cerca i tasti invece di leggere il fotogramma, ed è a quel punto che conviene dividere il task in due piuttosto che aggiungere un'altra etichetta.
Come appaiono le annotazioni
Potato salva tutte le forme di un'immagine in un array JSON piatto, qualunque sia lo strumento che le ha disegnate. Le coordinate sono normalizzate nell'intervallo da 0 a 1 rispetto all'immagine, così le annotazioni restano corrette anche se in seguito l'immagine viene servita a una dimensione diversa:
[
{
"type": "bbox",
"label": "vehicle",
"color": "#FF6B6B",
"coordinates": {"x": 0.234, "y": 0.352, "width": 0.120, "height": 0.130}
},
{
"type": "bbox",
"label": "pedestrian",
"color": "#4ECDC4",
"coordinates": {"x": 0.427, "y": 0.370, "width": 0.026, "height": 0.139}
}
]Un bbox porta la sua geometria sotto coordinates come {x, y, width, height}. I poligoni portano una lista di punti sotto la stessa chiave, mentre le maschere portano una codifica run-length sotto rle.
Esportare per l'addestramento
Il codice di addestramento dei rilevatori legge COCO o YOLO, e Potato li scrive entrambi:
python -m potato.export --config config.yaml --format coco --output ./export/
python -m potato.export --config config.yaml --format yolo --output ./export/Le due esportazioni differiscono per più della sintassi. COCO scrive un unico annotations.json con riquadri in pixel nella forma [x, y, width, height], e non copia le immagini, quindi i valori di file_name puntano a dove le immagini si trovano già. YOLO scrive un file di testo per immagine con coordinate del centro normalizzate, suddivide immagini ed etichette nelle directory train/ e val/, e aggiunge data.yaml e classes.txt, così un addestramento può leggere l'elenco delle classi senza che glielo si debba passare a parte.
Mantenere i riquadri coerenti
Disegna i riquadri aderenti all'oggetto, perché ogni pixel di sfondo dentro il riquadro è un pixel che il modello impara a chiamare primo piano. Metti per iscritto come trattare i casi difficili (occlusioni, oggetti tagliati dal bordo del fotogramma, riflessi) e rivedete insieme un gruppo di esempi nella prima settimana, finché cambiare la linea guida costa ancora poco. Tieni d'occhio il numero di riquadri e la distribuzione delle dimensioni per ciascun annotatore mentre lo studio procede, perché uno scarto improvviso di solito significa che una persona ha iniziato a interpretare una regola in modo diverso, non che le immagini siano cambiate.
Prossimi passi
- Aggiungi l'annotazione con poligoni quando i riquadri sono troppo grossolani per il task
- Usa i set di keypoint per la stima della posa
- Imposta il controllo di qualità prima che lo studio superi una manciata di annotatori
Per le altre opzioni sulle immagini, vedi Annotazione di Immagini.