Annotation d'images
Configurez l'annotation d'images dans Potato avec boîtes englobantes, polygones, masques et points de repère. Affichez les images avec instance_display et exportez en COCO ou YOLO.
Potato prend en charge l'annotation d'images pour les tâches de classification, de détection d'objets, de segmentation et de points clés.
Afficher une image
Afficher une image et recueillir une annotation sont deux réglages distincts. instance_display décrit ce que voit l'annotateur, et annotation_schemes ce à quoi il répond. Comme les deux restent séparés, n'importe quel type de contenu peut accompagner n'importe quel type de question :
instance_display:
fields:
- key: image_url # Field name in your data file
type: image
label: "Image to classify"
display_options:
max_width: 600
zoomable: trueLe schéma image_annotation sert à dessiner sur une image, pas à l'afficher. Une tâche de classification n'a besoin que du champ d'affichage ci-dessus et d'un schéma radio ou multiselect.
Options d'affichage
| Option | Description |
|---|---|
max_width | Largeur d'affichage maximale en pixels |
max_height | Hauteur d'affichage maximale en pixels |
zoomable | Active le zoom au clic |
object_fit | Manière dont l'image remplit son cadre |
alt_text | Texte alternatif pour les lecteurs d'écran |
Un nom d'option que Potato ne reconnaît pas est une erreur de configuration et non une clé ignorée en silence, et le message propose l'option réelle la plus proche.
Format des données
Référencez les images dans votre fichier de données :
{"id": "img_001", "image_url": "https://example.com/photo_001.jpg"}
{"id": "img_002", "image_url": "/static/images/photo_002.png"}data_files est une liste de chemins, et item_properties fait correspondre vos noms de champs à ceux que lit Potato :
data_files:
- "data/image_tasks.json"
item_properties:
id_key: id
text_key: image_url # The field holding the image URLClassification d'images
Classer des images entières :
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 presentClassification multi-étiquettes
annotation_schemes:
- annotation_type: multiselect
name: objects
description: "What objects are visible?"
labels:
- Person
- Car
- Building
- Tree
- Animal
- Furniture
- Food
- Electronic deviceÉvaluation de la qualité d'image
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 visibleDessiner sur les images
Le schéma image_annotation exige à la fois tools et labels. Donner à chaque étiquette une couleur et une key_value vaut les quelques lignes de plus, car les annotateurs attribuent une étiquette au clavier bien plus vite qu'à la souris :
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: truecolor doit être en hexadécimal (#rgb, #rrggbb ou #rrggbbaa). Les noms de couleurs CSS et rgb() ne sont pas lus. Les formes auraient l'air correctes, mais les masques sont peints pixel par pixel et se rabattent sur le rouge.
Outils disponibles
| Outil | Description |
|---|---|
bbox | Boîtes englobantes rectangulaires |
polygon | Polygones fermés à plusieurs points |
polyline | Tracés ouverts à plusieurs points, pour les marquages de voie, les vaisseaux, les fissures, les traits de côte |
ellipse | Ellipses et cercles, pour les cellules, les noyaux, les roues, les visages |
keypoint_set | Squelettes ordonnés, pour la pose humaine ou animale et les points de repère du visage |
cuboid_2d | Boîtes 3D projetées dans l'image, à la manière de KITTI |
sam | Baguette magique : cliquez sur un objet et un modèle le segmente |
freeform | Dessin à main levée |
landmark | Marqueurs d'un seul point |
brush | Pinceau de segmentation pour les masques au niveau du pixel |
eraser | Supprime des zones du masque |
fill | Remplissage par diffusion des zones fermées |
Un polygone est fermé et délimite une surface. Une polyligne est ouverte et a une longueur mais pas d'intérieur. La distinction compte à l'export, où une polyligne est écrite avec area: 0 et n'est jamais traitée comme une région.
Annotation par polygones
Pour les régions non rectangulaires :
annotation_schemes:
- annotation_type: image_annotation
name: regions
description: "Outline regions of interest"
tools:
- polygon
labels:
- name: Building
- name: Road
- name: Vegetation
- name: WaterMasques de segmentation
Pour le travail au niveau du pixel, activez les outils de peinture. Les masques sont stockés en codage par plages (run-length encoding) plutôt qu'en tableaux par pixel, ce qui permet de garder petit un masque couvrant toute l'image :
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: semanticmask_mode: semantic fusionne tous les traits d'une même classe en une seule région. Utilisez instance lorsque deux objets de la même classe doivent rester distincts.
Format de sortie
Les annotations sont stockées dans un tableau JSON plat, avec toutes les formes et tous les masques dans la même liste. Les coordonnées sont normalisées entre 0 et 1 par rapport à l'image, si bien que les annotations restent justes lorsque l'image est servie à une autre taille :
[
{
"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 clé de géométrie dépend du type :
| Type | Clé de géométrie | Forme |
|---|---|---|
bbox | coordinates | {x, y, width, height}, normalisé |
polygon | coordinates | liste de {x, y}, normalisés |
landmark | coordinates | {x, y}, normalisé |
freeform | coordinates | {path, left, top, scaleX, scaleY} |
mask | rle | {counts: [ints], size: [height, width]} |
rle.size vaut [height, width], dans cet ordre. Pour convertir vers et depuis ces formes en Python, utilisez normalize_annotation_object() et to_client_object() de potato.export.cv_utils plutôt que de lire les champs directement.
Origine d'une forme
Une fois stockées, une détection acceptée d'un modèle et une boîte dessinée à la main sont identiques, c'est pourquoi chaque forme enregistre sa propre origine. Sans cela, un projet qui pré-étiquette avec un modèle ne peut pas calculer son taux d'acceptation à partir de ses propres données :
{
"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
}| Clé | Signification |
|---|---|
source | human (dessinée dans le navigateur), ai (proposée par un modèle et acceptée par l'annotateur), import (arrivée avec les données) |
ai_model | Le modèle concerné, lorsque l'endpoint l'indique |
confidence | Le score que le détecteur a lui-même attribué à cette forme |
edited | L'annotateur a depuis déplacé, redimensionné ou réétiqueté une forme qui n'était pas la sienne |
carried_over | Recopiée depuis l'image précédente plutôt que créée sur celle-ci |
edited distingue le fait d'accepter une boîte telle quelle de celui de l'accepter puis de la corriger. Seul le premier cas constitue un accord avec le modèle.
Relire des annotations existantes
Pour relire des formes qui existent déjà, importez-les plutôt que de les ajouter à un champ de données. potato import transforme un fichier COCO en projet prêt à lancer et marque chaque forme avec source: import :
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 8000Les annotateurs corrigent ensuite les formes importées sur place, et l'export conserve la répartition entre humain et modèle sur l'ensemble de l'aller-retour.
Comparaison d'images
Comparez deux images avec le schéma pairwise. items_key désigne le champ de données qui contient la paire :
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"Légendage d'images
annotation_schemes:
- annotation_type: text
name: caption
description: "Write a caption for this image"
rows: 4
placeholder: "Describe what you see..."Relecture de la qualité des légendes
Affichez l'image et la légende générée côte à côte, puis évaluez la légende :
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: falseModération de contenu
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/advertisementFormats d'échange
Potato lit le JSON COCO, y compris tous les encodages de segmentation et les régions de foule (crowd), et écrit du COCO, du YOLO, du Pascal VOC et des PNG de masque par étiquette :
python -m potato.export -c my-project/config.yaml -f coco -o ./export/YOLO et Pascal VOC ne transportent que des boîtes englobantes, donc les autres formes sont réduites à leur boîte englobante.
Exemple complet : relecture d'une détection d'objets
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: trueDémarrez le serveur :
potato start config.yaml -p 8000Conseils de performance
- Redimensionnez avant d'annoter : les grandes images sources ralentissent le chargement sans améliorer l'annotation
- JPEG pour les photos : fichiers plus légers, chargement plus rapide
- PNG pour les graphiques : meilleur rendu des schémas et des captures d'écran
- Plafonnez la taille d'affichage : définissez
max_widthpour que le navigateur n'ait pas à redimensionner une image énorme à chaque instance - Prétraitez de façon homogène : normalisez tailles et formats sur l'ensemble du jeu de données