Skip to content

Annotazione di Immagini

Configura l'annotazione di immagini in Potato con bounding box, poligoni, maschere e landmark. Mostra le immagini con instance_display ed esporta in COCO o YOLO.

Potato supporta l'annotazione di immagini per compiti di classificazione, rilevamento oggetti, segmentazione e keypoint.

Mostrare un'immagine

Mostrare un'immagine e raccogliere un'annotazione sono due impostazioni separate. instance_display stabilisce cosa vede l'annotatore, e annotation_schemes stabilisce a cosa risponde. Tenerle separate permette di affiancare qualsiasi tipo di contenuto a qualsiasi tipo di domanda:

yaml
instance_display:
  fields:
    - key: image_url          # Field name in your data file
      type: image
      label: "Image to classify"
      display_options:
        max_width: 600
        zoomable: true

Lo schema image_annotation serve a disegnare su un'immagine, non a mostrarla. Un compito di classificazione richiede solo il campo di visualizzazione qui sopra più uno schema radio o multiselect.

Opzioni di visualizzazione

OpzioneDescrizione
max_widthLarghezza massima di rendering in pixel
max_heightAltezza massima di rendering in pixel
zoomableAbilita lo zoom al clic
object_fitCome l'immagine riempie il suo riquadro
alt_textTesto alternativo per i lettori di schermo

Un nome di opzione che Potato non riconosce è un errore di configurazione, non una chiave ignorata in silenzio, e il messaggio suggerisce l'opzione reale più vicina.

Formato dei dati

Fai riferimento alle immagini nel tuo file di dati:

json
{"id": "img_001", "image_url": "https://example.com/photo_001.jpg"}
{"id": "img_002", "image_url": "/static/images/photo_002.png"}

data_files è un elenco di percorsi, e item_properties associa i nomi dei tuoi campi a quelli che Potato legge:

yaml
data_files:
  - "data/image_tasks.json"
 
item_properties:
  id_key: id
  text_key: image_url   # The field holding the image URL

Classificazione delle immagini

Classifica intere immagini:

yaml
annotation_schemes:
  - annotation_type: radio
    name: category
    description: "What is shown in this image?"
    labels:
      - Cat
      - Dog
      - Bird
      - Other
 
  - annotation_type: multiselect
    name: attributes
    description: "Select all that apply"
    labels:
      - Indoor
      - Outdoor
      - Multiple animals
      - Human present

Classificazione multi-etichetta

yaml
annotation_schemes:
  - annotation_type: multiselect
    name: objects
    description: "What objects are visible?"
    labels:
      - Person
      - Car
      - Building
      - Tree
      - Animal
      - Furniture
      - Food
      - Electronic device

Valutazione della qualità dell'immagine

yaml
annotation_schemes:
  - annotation_type: likert
    name: quality
    description: "Overall image quality"
    size: 5
    min_label: "Very poor"
    max_label: "Excellent"
 
  - annotation_type: multiselect
    name: issues
    description: "Select any quality issues"
    labels:
      - Blurry
      - Overexposed
      - Underexposed
      - Noisy
      - Low resolution
      - Watermark visible

Disegnare sulle immagini

Lo schema image_annotation richiede sia tools sia labels. Assegnare a ogni etichetta un colore e un key_value vale le righe in più, perché gli annotatori assegnano le etichette da tastiera molto più velocemente che con il clic:

yaml
annotation_schemes:
  - annotation_type: image_annotation
    name: object_detection
    description: "Draw boxes around objects"
    tools:
      - bbox
      - polygon
    labels:
      - name: person
        color: "#FF6B6B"
        key_value: "1"
      - name: vehicle
        color: "#4ECDC4"
        key_value: "2"
      - name: animal
        color: "#45B7D1"
        key_value: "3"
    min_annotations: 1
    zoom_enabled: true
    pan_enabled: true

color deve essere esadecimale (#rgb, #rrggbb o #rrggbbaa). I nomi di colore CSS e rgb() non vengono letti. Le forme sembrerebbero corrette, ma le maschere vengono dipinte pixel per pixel e ricadono sul rosso.

Strumenti disponibili

StrumentoDescrizione
bboxBounding box rettangolari
polygonPoligoni chiusi a più punti
polylinePercorsi aperti a più punti, per segnaletica di corsia, vasi, crepe, linee costiere
ellipseEllissi e cerchi, per cellule, nuclei, ruote, volti
keypoint_setScheletri ordinati, per la posa umana o animale e i landmark facciali
cuboid_2dBox 3D proiettati nell'immagine, in stile KITTI
samBacchetta magica: fai clic su un oggetto e un modello lo segmenta
freeformDisegno a mano libera
landmarkMarcatori a punto singolo
brushPennello di segmentazione per maschere a livello di pixel
eraserRimuove regioni della maschera
fillRiempimento per regioni chiuse

Un poligono è chiuso e racchiude un'area; una polilinea è aperta e ha una lunghezza ma nessun interno. La distinzione conta in esportazione, dove una polilinea viene scritta con area: 0 e non viene mai trattata come una regione.

Annotazione con poligoni

Per regioni non rettangolari:

yaml
annotation_schemes:
  - annotation_type: image_annotation
    name: regions
    description: "Outline regions of interest"
    tools:
      - polygon
    labels:
      - name: Building
      - name: Road
      - name: Vegetation
      - name: Water

Maschere di segmentazione

Per il lavoro a livello di pixel, abilita gli strumenti di pittura. Le maschere vengono salvate con codifica run-length invece che come array per pixel, ed è questo che mantiene piccola una maschera sull'intera immagine:

yaml
annotation_schemes:
  - annotation_type: image_annotation
    name: segmentation
    description: "Paint regions using the brush tool"
    tools:
      - brush
      - eraser
      - fill
    labels:
      - name: road
        color: "#45B7D1"
      - name: sidewalk
        color: "#96CEB4"
    brush_size: 20
    mask_opacity: 0.5
    mask_mode: semantic

mask_mode: semantic unisce ogni tratto di una classe in un'unica regione. Usa instance quando due oggetti della stessa classe devono restare separati.

Formato di output

Le annotazioni vengono salvate come un array JSON piatto, con ogni forma e maschera nella stessa lista. Le coordinate sono normalizzate nell'intervallo da 0 a 1 rispetto all'immagine, così le annotazioni restano corrette quando l'immagine viene servita a una dimensione diversa:

json
[
  {
    "type": "bbox",
    "label": "person",
    "color": "#FF6B6B",
    "coordinates": {"x": 0.125, "y": 0.104, "width": 0.3125, "height": 0.625}
  },
  {
    "type": "polygon",
    "label": "vehicle",
    "color": "#4ECDC4",
    "coordinates": [
      {"x": 0.02, "y": 0.04}, {"x": 0.20, "y": 0.04},
      {"x": 0.20, "y": 0.21}, {"x": 0.02, "y": 0.21}
    ]
  },
  {
    "type": "mask",
    "label": "road",
    "color": "#45B7D1",
    "rle": {"counts": [12, 40, 8], "size": [480, 640]}
  }
]

La chiave della geometria varia in base al tipo:

TipoChiave della geometriaForma
bboxcoordinates{x, y, width, height}, normalizzato
polygoncoordinateslista di {x, y}, normalizzata
landmarkcoordinates{x, y}, normalizzato
freeformcoordinates{path, left, top, scaleX, scaleY}
maskrle{counts: [ints], size: [height, width]}

rle.size è [height, width], in quest'ordine. Per convertire da e verso queste forme in Python, usa normalize_annotation_object() e to_client_object() da potato.export.cv_utils invece di leggere direttamente i campi.

Da dove viene una forma

Una volta salvati, un rilevamento accettato da un modello e un box disegnato a mano sono per il resto identici, quindi ogni forma registra la propria origine. Senza questa informazione, un progetto che pre-etichetta con un modello non può calcolare il proprio tasso di accettazione dai propri dati:

json
{
  "type": "bbox",
  "label": "person",
  "coordinates": {"x": 0.125, "y": 0.104, "width": 0.3125, "height": 0.625},
  "source": "ai",
  "ai_model": "yolov8n",
  "confidence": 0.82,
  "edited": true
}
ChiaveSignificato
sourcehuman (disegnata nel browser), ai (proposta da un modello e accettata dall'annotatore), import (arrivata insieme ai dati)
ai_modelQuale modello, quando l'endpoint lo riporta
confidenceIl punteggio del rilevatore per questa forma
editedL'annotatore ha poi spostato, ridimensionato o rietichettato una forma che non era sua
carried_overCopiata dall'immagine precedente invece che creata su questa

edited è ciò che distingue l'accettare un box così com'è dall'accettarlo e poi correggerlo. Solo il primo caso è accordo con il modello.

Rivedere annotazioni esistenti

Per rivedere forme che esistono già, importale invece di aggiungerle a un campo dei dati. potato import trasforma un file COCO in un progetto eseguibile e marca ogni forma con source: import:

bash
potato import --input instances_val2017.json \
    --image-dir /data/val2017 \
    --image-url-prefix /files \
    --output-dir my-project/ \
    --schema-name object_detection
 
potato start my-project/config.yaml -p 8000

Gli annotatori correggono poi le forme importate sul posto, e l'esportazione mantiene la distinzione tra umano e modello lungo tutto il percorso.

Confronto di immagini

Confronta due immagini con lo schema pairwise. items_key indica il campo dei dati che contiene la coppia:

yaml
annotation_schemes:
  - annotation_type: pairwise
    name: preference
    description: "Which image looks better?"
    mode: binary
    items_key: images
    show_labels: true
    labels:
      - "Original"
      - "Edited"
    allow_tie: true
    tie_label: "About the same"

Didascalie per immagini

yaml
annotation_schemes:
  - annotation_type: text
    name: caption
    description: "Write a caption for this image"
    rows: 4
    placeholder: "Describe what you see..."

Revisione della qualità delle didascalie

Mostra l'immagine e la didascalia generata affiancate, poi valuta la didascalia:

yaml
instance_display:
  fields:
    - key: image_url
      type: image
      label: "Image"
    - key: generated_caption
      type: text
      label: "Generated caption"
 
annotation_schemes:
  - annotation_type: likert
    name: accuracy
    description: "How accurate is this caption?"
    size: 5
    min_label: "Very inaccurate"
    max_label: "Very accurate"
 
  - annotation_type: likert
    name: fluency
    description: "How natural is the language?"
    size: 5
    min_label: "Very awkward"
    max_label: "Very natural"
 
  - annotation_type: text
    name: improved_caption
    description: "Suggest a better caption (optional)"
    rows: 4
    label_requirement:
      required: false

Moderazione dei contenuti

yaml
annotation_schemes:
  - annotation_type: radio
    name: safe_for_work
    description: "Is this image safe for work?"
    labels:
      - Safe
      - Questionable
      - Not Safe
 
  - annotation_type: multiselect
    name: violation_types
    description: "Select all violations (if any)"
    labels:
      - Violence
      - Adult content
      - Hate symbols
      - Graphic content
      - Spam/advertisement

Formati di interscambio

Potato legge COCO JSON, incluse tutte le codifiche di segmentazione e le regioni crowd, e scrive COCO, YOLO, Pascal VOC e PNG di maschere per etichetta:

bash
python -m potato.export -c my-project/config.yaml -f coco -o ./export/

YOLO e Pascal VOC contengono solo bounding box, quindi le altre forme vengono ridotte al loro box contenitore.

Esempio completo: revisione del rilevamento oggetti

yaml
annotation_task_name: "Object Detection Verification"
task_dir: "."
 
data_files:
  - "data/detections.json"
 
item_properties:
  id_key: id
  text_key: image_url
 
instance_display:
  fields:
    - key: image_url
      type: image
      label: "Image"
      display_options:
        max_width: 1000
        zoomable: true
 
annotation_schemes:
  # Correct the boxes
  - annotation_type: image_annotation
    name: objects
    description: "Verify and correct object boxes"
    tools:
      - bbox
    labels:
      - name: Person
        key_value: "1"
      - name: Vehicle
        key_value: "2"
      - name: Animal
        key_value: "3"
      - name: Object
        key_value: "4"
    zoom_enabled: true
    pan_enabled: true
 
  # Overall assessment
  - annotation_type: radio
    name: prediction_quality
    description: "How accurate were the predictions?"
    labels:
      - All correct
      - Minor corrections needed
      - Major corrections needed
      - Mostly incorrect
 
  - annotation_type: number
    name: missed_objects
    description: "How many objects were missed?"
    min: 0
    max: 50
 
  - annotation_type: text
    name: notes
    description: "Any issues or comments?"
    rows: 4
    label_requirement:
      required: false
 
output_annotation_dir: "output/"
export_annotation_format: jsonl
 
user_config:
  allow_all_users: true

Avvia il server:

bash
potato start config.yaml -p 8000

Suggerimenti per le prestazioni

  1. Ridimensiona prima di annotare: le immagini sorgente grandi rallentano il caricamento senza migliorare l'annotazione
  2. Usa JPEG per le foto: file più piccoli, caricamento più rapido
  3. Usa PNG per la grafica: qualità migliore per diagrammi e screenshot
  4. Limita la dimensione di rendering: imposta max_width così il browser non deve ridimensionare un'immagine enorme a ogni istanza
  5. Pre-elabora in modo coerente: normalizza dimensioni e formati in tutto il dataset