Skip to content

이미지 주석

Potato에서 경계 상자, 다각형, 마스크, 랜드마크로 이미지 주석을 설정합니다. instance_display로 이미지를 표시하고 COCO 또는 YOLO로 내보냅니다.

Potato는 분류, 객체 탐지, 분할, 키포인트 작업을 위한 이미지 주석을 지원합니다.

이미지 표시하기

이미지를 표시하는 것과 주석을 수집하는 것은 별개의 설정입니다. instance_display는 주석자가 무엇을 보는지를, annotation_schemes는 주석자가 무엇에 답하는지를 정합니다. 둘을 분리해 두면 어떤 콘텐츠 유형이든 어떤 질문 유형과도 함께 쓸 수 있습니다.

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

image_annotation 스킴은 이미지 위에 그리기 위한 것이지, 이미지를 보여 주기 위한 것이 아닙니다. 분류 작업에는 위의 표시 필드와 radio 또는 multiselect 스킴만 있으면 됩니다.

표시 옵션

옵션설명
max_width렌더링되는 최대 너비(픽셀)
max_height렌더링되는 최대 높이(픽셀)
zoomable클릭하여 확대 기능 사용
object_fit이미지가 상자를 채우는 방식
alt_text화면 낭독기용 대체 텍스트

Potato가 인식하지 못하는 옵션 이름은 조용히 무시되는 키가 아니라 설정 오류로 처리되며, 오류 메시지는 가장 가까운 실제 옵션 이름을 제안합니다.

데이터 형식

데이터 파일에서 이미지를 참조합니다.

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

data_files는 경로 목록이고, item_properties는 사용자의 필드 이름을 Potato가 읽는 필드 이름에 연결합니다.

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

이미지 분류

이미지 전체를 분류합니다.

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

다중 레이블 분류

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

이미지 품질 평가

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

이미지 위에 그리기

image_annotation 스킴에는 tools와 labels가 모두 필요합니다. 각 레이블에 색상과 key_value를 지정하면 몇 줄이 늘어나지만 그만한 가치가 있습니다. 주석자는 클릭보다 키 입력으로 레이블을 훨씬 빠르게 지정하기 때문입니다.

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는 16진수(#rgb, #rrggbb, #rrggbbaa)여야 합니다. CSS 색상 이름과 rgb()는 읽히지 않습니다. 도형은 제대로 보이지만, 마스크는 픽셀 단위로 칠해지기 때문에 빨간색으로 대체됩니다.

사용 가능한 도구

도구설명
bbox직사각형 경계 상자
polygon여러 점으로 이루어진 닫힌 다각형
polyline여러 점으로 이루어진 열린 경로. 차선, 혈관, 균열, 해안선에 사용
ellipse타원과 원. 세포, 세포핵, 바퀴, 얼굴에 사용
keypoint_set순서가 있는 골격. 사람이나 동물의 자세, 얼굴 랜드마크에 사용
cuboid_2d이미지에 투영된 3D 상자(KITTI 방식)
sam마법봉. 객체를 클릭하면 모델이 해당 객체를 분할
freeform자유 그리기
landmark단일 점 마커
brush픽셀 수준 마스크를 위한 분할 브러시
eraser마스크 영역 지우기
fill닫힌 영역을 채우는 플러드 필

다각형은 닫혀 있어 면적을 둘러싸고, 폴리라인은 열려 있어 길이는 있지만 내부가 없습니다. 이 차이는 내보내기에서 중요합니다. 폴리라인은 area: 0으로 기록되며 절대 영역으로 취급되지 않습니다.

다각형 주석

직사각형이 아닌 영역의 경우:

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

분할 마스크

픽셀 수준 작업에는 페인팅 도구를 활성화합니다. 마스크는 픽셀별 배열이 아니라 런렝스 인코딩으로 저장되며, 이 덕분에 이미지 전체를 덮는 마스크도 작게 유지됩니다.

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은 한 클래스의 모든 획을 하나의 영역으로 합칩니다. 같은 클래스의 두 객체를 서로 구분해야 한다면 instance를 사용하세요.

출력 형식

주석은 평평한 JSON 배열로 저장되며, 모든 도형과 마스크가 같은 목록에 들어갑니다. 좌표는 이미지를 기준으로 0에서 1 사이로 정규화되므로, 이미지가 다른 크기로 제공되어도 주석은 정확하게 유지됩니다.

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

기하 정보 키는 유형에 따라 다릅니다.

유형기하 정보 키형태
bboxcoordinates{x, y, width, height}, 정규화됨
polygoncoordinates{x, y}의 목록, 정규화됨
landmarkcoordinates{x, y}, 정규화됨
freeformcoordinates{path, left, top, scaleX, scaleY}
maskrle{counts: [ints], size: [height, width]}

rle.size는 [height, width] 순서입니다. Python에서 이 형태로 변환하거나 이 형태에서 변환하려면 필드를 직접 읽지 말고 potato.export.cv_utils의 normalize_annotation_object()와 to_client_object()를 사용하세요.

도형의 출처

모델 탐지 결과를 수락한 것과 손으로 그린 상자는 저장되고 나면 구별되지 않으므로, 모든 도형은 자신의 출처를 기록합니다. 이 기록이 없으면 모델로 사전 레이블링하는 프로젝트가 자체 데이터에서 자체 수락률을 보고할 수 없습니다.

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
}
키의미
sourcehuman(브라우저에서 그림), ai(모델이 제안하고 주석자가 수락함), import(데이터와 함께 들어옴)
ai_model엔드포인트가 모델을 보고하는 경우, 어떤 모델인지
confidence이 도형에 대한 탐지기 자체의 점수
edited주석자가 자신이 만들지 않은 도형을 이후에 이동, 크기 조정 또는 레이블 변경함
carried_over이 이미지에서 만든 것이 아니라 이전 이미지에서 복사해 옴

edited는 상자를 그대로 수락한 경우와 수락한 뒤 수정한 경우를 구분합니다. 모델과 일치한 것은 앞의 경우뿐입니다.

기존 주석 검토

이미 존재하는 도형을 검토하려면 데이터 필드에 추가하지 말고 가져오세요. potato import는 COCO 파일을 실행 가능한 프로젝트로 바꾸고, 각 도형에 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

그러면 주석자는 가져온 도형을 그 자리에서 수정하며, 내보내기는 이 왕복 과정 전체에서 사람과 모델의 구분을 유지합니다.

이미지 비교

pairwise 스킴으로 두 이미지를 비교합니다. items_key는 이미지 쌍을 담은 데이터 필드의 이름을 지정합니다.

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"

이미지 캡셔닝

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

캡션 품질 검토

이미지와 생성된 캡션을 나란히 표시한 뒤 캡션을 평가합니다.

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

콘텐츠 검수

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

교환 형식

Potato는 모든 분할 인코딩과 crowd 영역을 포함한 COCO JSON을 읽고, COCO, YOLO, Pascal VOC, 레이블별 마스크 PNG로 씁니다.

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

YOLO와 Pascal VOC는 경계 상자만 담으므로, 다른 도형은 이를 둘러싸는 상자로 축소됩니다.

전체 예제: 객체 탐지 검토

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

서버를 시작합니다.

bash
potato start config.yaml -p 8000

성능 팁

  1. 주석 작업 전에 크기 조정 - 큰 원본 이미지는 주석 품질을 높이지 않으면서 로딩만 느리게 합니다
  2. 사진에는 JPEG 사용 - 파일 크기가 작고 로딩이 빠릅니다
  3. 그래픽에는 PNG 사용 - 다이어그램과 스크린샷에 더 나은 품질을 제공합니다
  4. 렌더링 크기 제한 - 브라우저가 인스턴스마다 거대한 이미지의 크기를 조정하지 않도록 max_width를 설정합니다
  5. 일관된 전처리 - 데이터셋 전체에서 크기와 형식을 정규화합니다