Skip to content
指南閱讀約需 11 分鐘

用視覺 AI 加速影像和影片標註

在 Potato 中配置 YOLO、Ollama、OpenAI 和 Claude 視覺端點,讓模型提出邊界框和標籤,由標註者接受或拒絕。

Potato Team

用檢測模型畫框,用視覺語言模型做判斷,再讓標註者接受或拒絕模型提出的結果,而不是手工畫出每一個區域。

Potato 2.1 加入了視覺 AI 支援,把模型建議放進影像和影片標註介面。YOLO 這類檢測器找出目標並畫出候選框供稽核。GPT-4o、Claude 或本地 Ollama 模型這類視覺語言模型對整張影像或某個區域分類,並解釋分類的依據。模型提出的任何結果,在標註者接受之前都不會成為標註。

本指南介紹四種視覺端點、每種端點支援的輔助模式,以及如何在同一個項目裡搭配使用視覺端點和文本端點。完整的 API 參考見視覺 AI 源文件。

需要準備的東西

視覺 AI 需要 Potato 2.1.0 或更高版本:

bash
pip install --upgrade potato-annotation

選哪個端點決定了其餘的設定:

  • YOLO 在本地執行:pip install ultralytics opencv-python
  • Ollama 在本地執行:從 ollama.ai 安裝並拉取一個視覺模型
  • OpenAI 需要一個能訪問 GPT-4o 的 API 金鑰
  • Anthropic 需要一個能訪問 Claude 視覺模型的 API 金鑰

用 YOLO 做目標檢測

任務是給常見物體畫邊界框、而且影像不該離開本機時,選 YOLO。它每張圖只花幾毫秒就能檢測出人、車、動物和傢俱,返回的是座標而不是文字,這正是畫框任務需要的。

方案級的 ai_support 塊決定標註者看到哪些按鈕,項目級的塊決定由哪個模型來回應。把兩者分開,一個項目才能只在檢測方案上啟用 AI,其餘方案保持不動。

yaml
annotation_task_name: "Object Detection with YOLO"
task_dir: "."
 
data_files:
  - data/images.json
 
item_properties:
  id_key: id
  text_key: image_url
 
instance_display:
  fields:
    - key: image_url
      type: image
      display_options:
        max_width: 800
        zoomable: true
 
annotation_schemes:
  - annotation_type: image_annotation
    name: objects
    description: "Draw a box around every object and label it"
    source_field: "image_url"
    tools:
      - bbox
    labels:
      - name: "person"
        color: "#FF6B6B"
      - name: "car"
        color: "#4ECDC4"
      - name: "dog"
        color: "#45B7D1"
      - name: "cat"
        color: "#96CEB4"
 
    ai_support:
      enabled: true
      features:
        detection: true
        pre_annotate: true
        hint: true
 
ai_support:
  enabled: true
  endpoint_type: "yolo"
  ai_config:
    model: "yolov8m.pt"
    confidence_threshold: 0.5
 
output_annotation_dir: "annotation_output/"
user_config:
  allow_all_users: true

資料檔案每行一個 JSON 物件,影像路徑或 URL 放在 text_key 指定的欄位裡:

json
{"id": "img_001", "image_url": "images/street_scene_1.jpg"}
{"id": "img_002", "image_url": "images/park_photo.jpg"}
{"id": "img_003", "image_url": "https://example.com/images/office.jpg"}

挑選模型大小

模型大小是在延遲和召回之間取捨,而這個取捨的兩頭都要花標註者的時間。漏檢目標的模型會把預標註重新變回畫框任務,每張圖要跑幾秒的模型則讓標註者在條目之間乾等。中間幾檔是通常的選擇,不是因為它們在哪一頭勝出,而是因為它們把兩頭的代價都壓得比較小。

模型大小速度準確度適用場景
yolov8n.pt6 MB最快較低快速試做
yolov8s.pt22 MB快不錯均衡的工作量
yolov8m.pt50 MB中等更好通用
yolov8l.pt84 MB較慢高準確度要緊時
yolov8x.pt131 MB最慢最高追求最高精度

對於 YOLO 內建類別以外的物體,YOLO-World 做開放詞表檢測:

yaml
ai_config:
  model: "yolo-world"
  confidence_threshold: 0.3

設定置信度閾值

閾值決定你交給標註者的是哪一種活。閾值低,框就多,他們的時間花在拒絕誤報上。閾值高,框就少,時間花在補畫模型漏掉的目標上。從 0.5 開始,看第一批資料裡哪一種修正佔多數,再調:

yaml
ai_config:
  confidence_threshold: 0.3  # more detections, more false positives
yaml
ai_config:
  confidence_threshold: 0.7  # fewer detections, higher precision

用 Ollama 視覺模型做本地場景理解

Ollama 在你自己的硬體上跑視覺語言模型。與 YOLO 不同,這些模型讀的是整個場景並寫出解釋,這是分類任務需要、而檢測器給不了的。資料不離開本機,所以同一套設定也覆蓋那些不能送到託管 API 的資料集。

bash
curl -fsSL https://ollama.ai/install.sh | sh
ollama pull llava

下面這個項目用本地模型對場景類型分類。這裡沒有方案級的 ai_support 塊,因為分類功能在這裡是項目級的,而不是掛在某個畫圖工具上:

yaml
annotation_task_name: "Image Classification with Ollama Vision"
task_dir: "."
 
data_files:
  - data/images.json
 
item_properties:
  id_key: id
  text_key: image_url
 
instance_display:
  fields:
    - key: image_url
      type: image
      display_options:
        max_width: 600
        zoomable: true
 
annotation_schemes:
  - annotation_type: radio
    name: scene_type
    description: "What type of scene is shown?"
    labels:
      - indoor
      - outdoor_urban
      - outdoor_nature
      - aerial
      - underwater
 
ai_support:
  enabled: true
  endpoint_type: "ollama_vision"
  ai_config:
    model: "llava:latest"
    base_url: "http://localhost:11434"
    max_tokens: 500
    temperature: 0.1
 
output_annotation_dir: "annotation_output/"
user_config:
  allow_all_users: true

低 temperature 在這裡比在寫作任務裡更要緊。同一張影像出現兩次,應該得到同一個建議標籤,而在高溫度下采樣的模型有時會自相矛盾,標註者讀到的是工具的噪聲,而不是模型的不確定。

Potato 支援 LLaVA 的 7B、13B 和 34B 三種規模,還有 LLaVA-LLaMA3、BakLLaVA、11B 和 90B 的 Llama 3.2 Vision、Qwen2.5-VL 以及 Moondream。小模型回答得夠快,能讓標註者不停下來;標籤取決於細節時,大模型值得多等。

OpenAI 視覺

GPT-4o 通過同一個 ai_support 塊處理影像,其中 detail 設定控制送出影像的多少:

yaml
ai_support:
  enabled: true
  endpoint_type: "openai_vision"
  ai_config:
    api_key: "${OPENAI_API_KEY}"
    model: "gpt-4o"
    max_tokens: 1000
    detail: "auto"
bash
export OPENAI_API_KEY="sk-..."

low 送出縮小過的影像,更便宜,對場景級分類也夠快。high 送出完整解析度,找小物體需要它。auto 交給 API 自己選。這個設定按影像計費,所以值得在跑大批次之前就定好,而不是等賬單出來。

Anthropic 視覺

Claude 的視覺模型讀取影像上下文,並寫出分類背後的推理,所以在標註者需要的是解釋而不是一個框的任務裡很合適:

yaml
ai_support:
  enabled: true
  endpoint_type: "anthropic_vision"
  ai_config:
    api_key: "${ANTHROPIC_API_KEY}"
    model: "claude-sonnet-4-20250514"
    max_tokens: 1024
bash
export ANTHROPIC_API_KEY="sk-ant-..."

輔助模式

每種模式都會給標註者的工具欄加一個按鈕,也改變向模型提出的要求。只打開任務需要的那幾個,因為每多一個按鈕,標註者在每個條目上就多一個要做的決定。

檢測找出與你配置的標籤相符的物體,用虛線覆蓋層顯示出來。標註者逐張處理影像、希望每張圖都有個起點時,用這個模式:

yaml
ai_support:
  enabled: true
  features:
    detection: true

預標註一次性把檢測器跑遍所有資料,標註者開啟每個條目時建議已經在上面了。這是在大數據集上划算的模式,也是最需要校準好閾值的模式,因為這一遍跑完以後沒人會再去看設定:

yaml
ai_support:
  enabled: true
  features:
    pre_annotate: true

分類給選中的區域或整張影像打標籤,返回一個帶置信度分數的建議標籤。提示給出指引但不給答案,適合用在標註者培訓階段,在那裡把標籤直接給出去什麼也教不會:

yaml
ai_support:
  enabled: true
  features:
    classification: true
    hint: true

接受和拒絕建議

建議以虛線覆蓋層出現,在標註者動手之前一直只是建議。雙擊覆蓋層把它變成真正的標註,右鍵點選把它丟掉,工具欄上還有“全部接受”和“清除”,用在所有建議全對或者全錯的條目上。

接受這一步是標註檔案保持誠實的原因。匯出的是人接受過的東西,而不是模型提出的東西,所以調得不好的閾值只會費掉標註時間,不會悄悄把錯標籤寫進資料集。這也讓接受和拒絕的計數在試點期間值得盯著,因為標註者把大多數建議都拒絕掉的一輪,先告訴你的是閾值的事,之後才是模型的事。

影片:場景切分

影片方案有自己的一套功能,涵蓋場景邊界、幀分類、關鍵幀和跟蹤。max_frames 限制模型從片段裡取樣多少幀,這是同時影響準確度和等待時間的主要槓桿:

yaml
annotation_schemes:
  - annotation_type: video_annotation
    name: scenes
    description: "Segment this video into scenes"
    mode: segment
    labels:
      - name: "intro"
        color: "#4ECDC4"
      - name: "main_content"
        color: "#FF6B6B"
      - name: "outro"
        color: "#45B7D1"
 
    ai_support:
      enabled: true
      features:
        scene_detection: true
        pre_annotate: true
        hint: true
 
ai_support:
  enabled: true
  endpoint_type: "ollama_vision"
  ai_config:
    model: "llava:latest"
    max_frames: 10

文本一個端點,影像另一個

混用文本方案和影像方案的項目通常希望兩邊用不同的模型,因為畫框最好的模型不是寫提示最好的那個。visual_endpoint_type 和 visual_ai_config 設定第二個端點。把這個塊加到已經有 ai_support 段的配置裡:

yaml
ai_support:
  enabled: true
 
  endpoint_type: "ollama"
  ai_config:
    model: "llama3.2"
    include:
      all: true
 
  visual_endpoint_type: "yolo"
  visual_ai_config:
    model: "yolov8m.pt"
    confidence_threshold: 0.5

同樣的搭配也適用於託管視覺模型配本地文本模型:

yaml
ai_support:
  enabled: true
  endpoint_type: "ollama"
  visual_endpoint_type: "openai_vision"
  ai_config:
    model: "llama3.2"
  visual_ai_config:
    api_key: "${OPENAI_API_KEY}"
    model: "gpt-4o"

在 2.9.1 裡這一對有一個要注意的地方。AI 快取會讀這兩個鍵,第二個端點也確實能用,但 potato validate --strict 會把它們報成無法識別,所以用了它們的配置過不了嚴格校驗這一關。用 --strict 把關部署的項目,在上游把這件事理順之前,最好把視覺端點和文本端點放在不同的項目裡。

一個完整的例子:產品照片

這個項目讓標註者框出產品和瑕疵,判斷照片能不能釋出,並標出照片哪裡有問題。YOLO 提出邊界框,兩個判斷類方案仍然由人來做:

yaml
annotation_task_name: "Product Photo Annotation"
task_dir: "."
 
data_files:
  - data/product_photos.json
 
item_properties:
  id_key: sku
  text_key: photo_url
 
instance_display:
  layout:
    direction: horizontal
    gap: 24px
  fields:
    - key: photo_url
      type: image
      label: "Product Photo"
      display_options:
        max_width: 600
        zoomable: true
    - key: product_description
      type: text
      label: "Product Details"
 
annotation_schemes:
  - annotation_type: image_annotation
    name: product_regions
    description: "Draw boxes around products and defects"
    source_field: "photo_url"
    tools:
      - bbox
    labels:
      - name: "product"
        color: "#4ECDC4"
      - name: "defect"
        color: "#FF6B6B"
      - name: "label"
        color: "#45B7D1"
      - name: "packaging"
        color: "#96CEB4"
 
    ai_support:
      enabled: true
      features:
        detection: true
        pre_annotate: true
 
  - annotation_type: radio
    name: photo_quality
    description: "Is this photo suitable for the product listing?"
    labels:
      - Approved
      - Needs editing
      - Reshoot required
 
  - annotation_type: multiselect
    name: quality_issues
    description: "Select any issues present"
    labels:
      - Blurry
      - Poor lighting
      - Wrong angle
      - Background clutter
      - Color inaccurate
 
ai_support:
  enabled: true
  endpoint_type: "yolo"
  ai_config:
    model: "yolov8m.pt"
    confidence_threshold: 0.5
 
output_annotation_dir: "annotation_output/"
export_annotation_format: "jsonl"
user_config:
  allow_all_users: true

要給這兩個判斷方案加上文本提示,把上面那對 visual_endpoint_type 配置加進這個配置裡,文本模型作 endpoint_type,yolo 作視覺端點。影像方案的框仍舊來自 YOLO,單選和多選方案的提示來自文本模型。

示例資料(data/product_photos.json):

json
{"sku": "SKU-001", "photo_url": "images/products/laptop_front.jpg", "product_description": "15-inch laptop, silver finish"}
{"sku": "SKU-002", "photo_url": "images/products/headphones_side.jpg", "product_description": "Over-ear wireless headphones, black"}
{"sku": "SKU-003", "photo_url": "images/products/backpack_full.jpg", "product_description": "40L hiking backpack, navy blue"}

把設定做對

  • 在大數據集上讓標註者開工之前,先跑一遍預標註。 按條目算,稽核加修正比從頭畫要快,而且這份好處隨資料集規模增長,設定的成本不會。
  • 讓端點對上問題。 檢測器回答“它在哪”,視覺語言模型回答“這是什麼、為什麼”,讓其中一個去幹另一個的活,產生的建議標註者很快就學會不看。
  • 在試點批次上調閾值。 從 0.5 開始,按標註者更常做哪一種修正來調。
  • 培訓時用提示模式。 它給新標註者指個方向,但不把標籤遞過去,記錄下來的仍然是他們自己的判斷。
  • 把結果快取下來。 磁碟快取讓同一張影像不會被付費分析兩遍。

排查問題

“未配置視覺 AI 端點”

檢查 ai_support.enabled 是不是 true,以及 endpoint_type 指的是不是一個視覺端點:yolo、ollama_vision、openai_vision 或 anthropic_vision。在影像方案上用文本端點就會出這條訊息。

YOLO 檢測不到你的目標

YOLO 的內建類別覆蓋 80 個常見物體類別,所以這個集合之外的標籤,無論閾值怎麼設都匹配不上。換成 YOLO-World 拿到開放詞表。如果標籤確實落在 YOLO 的類別裡,只是檢測結果偏少,那就調低 confidence_threshold。

Ollama 報錯

檢查服務是不是在執行,以及你寫的那個模型是不是既裝好了、又支援視覺:

bash
curl http://localhost:11434/api/tags
ollama list

雲 API 呼叫很慢

開啟磁碟快取,同一張影像就不會跨會話被分析兩遍。路徑相對 task_dir 解析,而且必須待在它裡面:

yaml
ai_support:
  cache_config:
    disk_cache:
      enabled: true
      path: "ai_cache/visual_cache.json"

下一步