Skip to content

Bildannotation

Bildannotation in Potato mit Bounding Boxes, Polygonen, Masken und Landmarken konfigurieren. Bilder mit instance_display anzeigen und nach COCO oder YOLO exportieren.

Potato unterstützt Bildannotation für Klassifikation, Objekterkennung, Segmentierung und Keypoint-Aufgaben.

Ein Bild anzeigen

Ein Bild anzeigen und eine Annotation erfassen sind zwei getrennte Einstellungen. instance_display legt fest, was Annotatoren sehen, und annotation_schemes, worauf sie antworten. Weil beides getrennt bleibt, lässt sich jeder Inhaltstyp mit jedem Fragetyp kombinieren:

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

Das Schema image_annotation dient zum Zeichnen auf einem Bild, nicht zum Anzeigen. Eine Klassifikationsaufgabe braucht nur das Anzeigefeld oben und dazu ein radio- oder multiselect-Schema.

Anzeigeoptionen

OptionBeschreibung
max_widthMaximale dargestellte Breite in Pixeln
max_heightMaximale dargestellte Höhe in Pixeln
zoomableZoom per Klick aktivieren
object_fitWie das Bild seinen Rahmen füllt
alt_textAlternativtext für Screenreader

Ein Optionsname, den Potato nicht kennt, ist ein Konfigurationsfehler und kein stillschweigend ignorierter Schlüssel, und die Meldung schlägt die nächstliegende echte Option vor.

Datenformat

Bilder in Ihrer Datendatei referenzieren:

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

data_files ist eine Liste von Pfaden, und item_properties ordnet Ihre Feldnamen den Feldern zu, die Potato liest:

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

Bildklassifikation

Ganze Bilder klassifizieren:

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

Multi-Label-Klassifikation

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

Bildqualitätsbewertung

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

Auf Bildern zeichnen

Das Schema image_annotation benötigt sowohl tools als auch labels. Jedem Label eine Farbe und einen key_value zu geben lohnt die zusätzlichen Zeilen, denn Annotatoren vergeben Labels per Tastendruck weit schneller als per Klick:

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 muss hexadezimal sein (#rgb, #rrggbb oder #rrggbbaa). Benannte CSS-Farben und rgb() werden nicht gelesen. Formen sähen zwar richtig aus, aber Masken werden Pixel für Pixel gemalt und fallen auf Rot zurück.

Verfügbare Werkzeuge

WerkzeugBeschreibung
bboxRechteckige Bounding Boxes
polygonGeschlossene Polygone aus mehreren Punkten
polylineOffene Pfade aus mehreren Punkten, für Fahrbahnmarkierungen, Gefäße, Risse, Küstenlinien
ellipseEllipsen und Kreise, für Zellen, Zellkerne, Räder, Gesichter
keypoint_setGeordnete Skelette, für menschliche oder tierische Posen und Gesichtslandmarken
cuboid_2dIn das Bild projizierte 3D-Boxen im KITTI-Stil
samZauberstab: ein Objekt anklicken, und ein Modell segmentiert es
freeformFreihandzeichnen
landmarkEinzelpunkt-Markierungen
brushSegmentierungspinsel für Masken auf Pixelebene
eraserMaskenbereiche entfernen
fillFlutfüllung für umschlossene Bereiche

Ein Polygon ist geschlossen und umschließt eine Fläche. Eine Polylinie ist offen und hat eine Länge, aber kein Inneres. Der Unterschied zählt beim Export, wo eine Polylinie mit area: 0 geschrieben und nie als Region behandelt wird.

Polygon-Annotation

Für nicht rechteckige Regionen:

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

Segmentierungsmasken

Für Arbeit auf Pixelebene aktivieren Sie die Malwerkzeuge. Masken werden als Lauflängenkodierung (run-length encoding) statt als Arrays pro Pixel gespeichert, und genau das hält eine Maske über das ganze Bild klein:

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 fasst alle Striche einer Klasse zu einer Region zusammen. Verwenden Sie instance, wenn zwei Objekte derselben Klasse getrennt bleiben müssen.

Ausgabeformat

Annotationen werden als flaches JSON-Array gespeichert, mit allen Formen und Masken in derselben Liste. Die Koordinaten sind relativ zum Bild auf den Bereich 0 bis 1 normalisiert, sodass Annotationen korrekt bleiben, wenn das Bild in einer anderen Größe ausgeliefert wird:

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]}
  }
]

Der Geometrieschlüssel hängt vom Typ ab:

TypGeometrieschlüsselForm
bboxcoordinates{x, y, width, height}, normalisiert
polygoncoordinatesListe von {x, y}, normalisiert
landmarkcoordinates{x, y}, normalisiert
freeformcoordinates{path, left, top, scaleX, scaleY}
maskrle{counts: [ints], size: [height, width]}

rle.size ist [height, width], in dieser Reihenfolge. Um in Python in diese Formen und aus ihnen zu konvertieren, verwenden Sie normalize_annotation_object() und to_client_object() aus potato.export.cv_utils, statt die Felder direkt zu lesen.

Woher eine Form stammt

Eine übernommene Modelldetektion und eine von Hand gezeichnete Box sind nach dem Speichern sonst identisch, deshalb hält jede Form ihre eigene Herkunft fest. Ohne diese Angabe kann ein Projekt, das mit einem Modell vorannotiert, seine Übernahmequote nicht aus den eigenen Daten ermitteln:

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
}
SchlüsselBedeutung
sourcehuman (im Browser gezeichnet), ai (von einem Modell vorgeschlagen und vom Annotator übernommen), import (mit den Daten eingegangen)
ai_modelWelches Modell, sofern der Endpunkt eines meldet
confidenceDer eigene Score des Detektors für diese Form
editedDer Annotator hat eine Form, die nicht von ihm stammte, nachträglich verschoben, in der Größe geändert oder neu gelabelt
carried_overVom vorherigen Bild übernommen statt auf diesem erstellt

edited unterscheidet, ob eine Box unverändert übernommen oder übernommen und dann korrigiert wurde. Nur das Erste ist Übereinstimmung mit dem Modell.

Vorhandene Annotationen überprüfen

Um bereits vorhandene Formen zu überprüfen, importieren Sie sie, statt sie einem Datenfeld hinzuzufügen. potato import macht aus einer COCO-Datei ein lauffähiges Projekt und versieht jede Form mit 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

Annotatoren korrigieren die importierten Formen dann direkt, und der Export bewahrt die Aufteilung zwischen Mensch und Modell über den gesamten Hin- und Rückweg.

Bildvergleich

Zwei Bilder mit dem Schema pairwise vergleichen. items_key benennt das Datenfeld, das das Paar enthält:

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"

Bildbeschreibung

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

Qualitätsprüfung von Bildbeschreibungen

Bild und generierte Beschreibung nebeneinander anzeigen und dann die Beschreibung bewerten:

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

Inhaltsmoderation

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

Austauschformate

Potato liest COCO-JSON, einschließlich aller Segmentierungskodierungen und Crowd-Regionen, und schreibt COCO, YOLO, Pascal VOC sowie Masken-PNGs pro Label:

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

YOLO und Pascal VOC enthalten nur Bounding Boxes, daher werden andere Formen auf ihre umschließende Box reduziert.

Vollständiges Beispiel: Überprüfung einer Objekterkennung

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

Server starten:

bash
potato start config.yaml -p 8000

Leistungstipps

  1. Vor dem Annotieren verkleinern: Große Quellbilder verlangsamen das Laden, ohne die Annotation zu verbessern
  2. JPEG für Fotos verwenden: Kleinere Dateien, schnelleres Laden
  3. PNG für Grafiken verwenden: Bessere Qualität für Diagramme und Screenshots
  4. Die dargestellte Größe begrenzen: max_width setzen, damit der Browser nicht bei jeder Instanz ein riesiges Bild skalieren muss
  5. Einheitlich vorverarbeiten: Größen und Formate über den gesamten Datensatz normalisieren