Skip to content

Anotação de Imagens

Configure a anotação de imagens no Potato com caixas delimitadoras, polígonos, máscaras e landmarks. Exiba imagens com instance_display e exporte para COCO ou YOLO.

O Potato oferece suporte à anotação de imagens para tarefas de classificação, detecção de objetos, segmentação e keypoints.

Exibindo uma imagem

Exibir uma imagem e coletar uma anotação são duas configurações separadas. instance_display define o que o anotador vê, e annotation_schemes define o que ele responde. Mantê-las separadas permite combinar qualquer tipo de conteúdo com qualquer tipo de pergunta:

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

O esquema image_annotation serve para desenhar sobre uma imagem, não para exibi-la. Uma tarefa de classificação precisa apenas do campo de exibição acima mais um esquema radio ou multiselect.

Opções de exibição

OpçãoDescrição
max_widthLargura máxima renderizada, em pixels
max_heightAltura máxima renderizada, em pixels
zoomableAtiva o zoom com clique
object_fitComo a imagem preenche sua caixa
alt_textTexto alternativo para leitores de tela

Um nome de opção que o Potato não reconhece é um erro de configuração, e não uma chave ignorada em silêncio, e a mensagem sugere a opção real mais próxima.

Formato dos dados

Referencie as imagens no seu arquivo de dados:

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

data_files é uma lista de caminhos, e item_properties associa os nomes dos seus campos aos que o Potato lê:

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

Classificação de imagens

Classifique imagens inteiras:

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

Classificação multirrótulo

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

Avaliação da qualidade da imagem

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

Desenhando sobre imagens

O esquema image_annotation exige tanto tools quanto labels. Vale a pena dar a cada rótulo uma cor e um key_value, mesmo com as linhas extras, porque os anotadores atribuem rótulos pelo teclado muito mais rápido do que clicando:

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 precisa ser hexadecimal (#rgb, #rrggbb ou #rrggbbaa). Nomes de cores CSS e rgb() não são lidos. As formas pareceriam corretas, mas as máscaras são pintadas pixel a pixel e caem no vermelho.

Ferramentas disponíveis

FerramentaDescrição
bboxCaixas delimitadoras retangulares
polygonPolígonos fechados com vários pontos
polylineCaminhos abertos com vários pontos, para marcações de faixa, vasos, rachaduras, linhas costeiras
ellipseElipses e círculos, para células, núcleos, rodas, rostos
keypoint_setEsqueletos ordenados, para pose humana ou animal e landmarks faciais
cuboid_2dCaixas 3D projetadas na imagem, no estilo KITTI
samVarinha mágica: clique em um objeto e um modelo o segmenta
freeformDesenho à mão livre
landmarkMarcadores de ponto único
brushPincel de segmentação para máscaras em nível de pixel
eraserRemove regiões da máscara
fillPreenchimento de regiões fechadas

Um polígono é fechado e delimita uma área; uma polilinha é aberta e tem comprimento, mas não tem interior. A distinção importa na exportação, onde uma polilinha é gravada com area: 0 e nunca é tratada como região.

Anotação com polígonos

Para regiões não retangulares:

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

Máscaras de segmentação

Para trabalho em nível de pixel, ative as ferramentas de pintura. As máscaras são armazenadas com codificação run-length em vez de arrays por pixel, e é isso que mantém pequena uma máscara da imagem inteira:

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 junta todos os traços de uma classe em uma única região. Use instance quando dois objetos da mesma classe precisarem ficar separados.

Formato de saída

As anotações são armazenadas como um array JSON plano, com todas as formas e máscaras na mesma lista. As coordenadas são normalizadas no intervalo de 0 a 1 em relação à imagem, de modo que as anotações continuam corretas quando a imagem é servida em outro tamanho:

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

A chave da geometria varia conforme o tipo:

TipoChave da geometriaForma
bboxcoordinates{x, y, width, height}, normalizado
polygoncoordinateslista de {x, y}, normalizada
landmarkcoordinates{x, y}, normalizado
freeformcoordinates{path, left, top, scaleX, scaleY}
maskrle{counts: [ints], size: [height, width]}

rle.size é [height, width], nessa ordem. Para converter de e para essas formas em Python, use normalize_annotation_object() e to_client_object() de potato.export.cv_utils em vez de ler os campos diretamente.

De onde veio uma forma

Depois de armazenadas, uma detecção de modelo aceita e uma caixa desenhada à mão são idênticas em todo o resto, por isso cada forma registra a própria origem. Sem isso, um projeto que pré-rotula com um modelo não consegue calcular a própria taxa de aceitação a partir dos próprios dados:

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
}
ChaveSignificado
sourcehuman (desenhada no navegador), ai (um modelo a propôs e o anotador a aceitou), import (chegou junto com os dados)
ai_modelQual modelo, quando o endpoint informa um
confidenceA pontuação do próprio detector para esta forma
editedO anotador moveu, redimensionou ou rerrotulou depois uma forma que não era dele
carried_overCopiada da imagem anterior em vez de criada nesta

edited é o que separa aceitar uma caixa como está de aceitá-la e depois corrigi-la. Só o primeiro caso é concordância com o modelo.

Revisando anotações existentes

Para revisar formas que já existem, importe-as em vez de adicioná-las a um campo dos dados. potato import transforma um arquivo COCO em um projeto executável e marca cada forma com 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

Os anotadores então corrigem as formas importadas no próprio lugar, e a exportação preserva a separação entre humano e modelo ao longo de todo o ciclo.

Comparação de imagens

Compare duas imagens com o esquema pairwise. items_key indica o campo dos dados que contém o par:

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"

Legendagem de imagens

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

Revisão da qualidade das legendas

Exiba a imagem e a legenda gerada lado a lado e depois avalie a legenda:

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

Moderação de conteúdo

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

Formatos de intercâmbio

O Potato lê COCO JSON, incluindo todas as codificações de segmentação e as regiões crowd, e grava COCO, YOLO, Pascal VOC e PNGs de máscara por rótulo:

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

YOLO e Pascal VOC contêm apenas caixas delimitadoras, por isso as outras formas são reduzidas à caixa que as envolve.

Exemplo completo: revisão de detecção de objetos

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

Inicie o servidor:

bash
potato start config.yaml -p 8000

Dicas de desempenho

  1. Redimensione antes de anotar: imagens de origem grandes deixam o carregamento mais lento sem melhorar a anotação
  2. Use JPEG para fotos: arquivos menores, carregamento mais rápido
  3. Use PNG para gráficos: melhor qualidade para diagramas e capturas de tela
  4. Limite o tamanho renderizado: defina max_width para que o navegador não precise redimensionar uma imagem enorme a cada instância
  5. Pré-processe de forma consistente: normalize tamanhos e formatos em todo o conjunto de dados