作品分享 | Anna 電腦視覺標註工具——以使用者為中心打造更輕量的內部工具

|by Hazel Shih

閱讀時間:約 7 分鐘

在日常工作中,我們團隊經常需要處理電腦視覺的資料標註任務。雖然 CVAT 提供了豐富的功能,但在實際使用時,複雜的操作流程和繁瑣的設定常造成團隊效率的低落。為了解決這個問題,我開發了一個團隊內部使用的標註工具——Anna,專注於提供核心的標註功能,簡化使用流程,讓團隊成員能夠更快速地完成標註工作,進而提升模型訓練效率。本文將分享設計與開發這個工具的經驗,如何根據使用者需求決定功能方向,最後有效解決了團隊的實際需求。

side-project-anna

Anna 標註工具的標註工作區頁面

一切的源頭都來自「為什麼這個工具這麼複雜?」

簡介電腦視覺與何謂標註

你有看過 TikTok 或 Instagram 上那些會跟著你舞動的可愛貼圖嗎?又或者玩過 Switch 體感遊戲時,電視總能精準追蹤你揮動手把的位置?這些都是電腦視覺中「人體姿態辨識」技術的應用。在我任職的前公司,我們也在開發類似的 AI 應用 —— 讓電腦自動辨識圖片或影片中的跌倒情況,以協助照護機構及時發現老人的跌倒事件。

要讓電腦學會這項技能,就像教導小孩認識世界一樣,需要給它大量的「範例」。我們會在圖片或影片中框出人的位置(這在電腦視覺領域中稱為「物件偵測」),接著標記出他們的姿態,告訴電腦「這個位置的人正在跌倒」、「這裡的人是正常走路的樣子」。透過這樣標註大量資料來教導電腦的方式,在 AI 領域中稱為「監督式學習」。

而在這個過程中,第一步就是要有個好用的標註工具,讓標註人員能夠在圖片或影片中完成兩個重要的標註工作:用框框(bounding box)標示出人的精確位置,並且記錄下他們的姿態狀態。這樣的標註資料才能讓電腦同時學會「這是人」以及「這個人正在跌倒」。

多功能的工具不代表好用

CVAT interface

CVAT 的標註工作區頁面

在圖片標註這個領域中,最有名的莫過於開源工具CVAT(Computer Vision Annotation Tool)。它的功能非常多,光是標註類型就有 bounding box(矩形)、Polygon(多邊形)、Polyline(折線)、Points(關鍵點)、Cuboid(三維立方體)等。

不過對我們團隊來說,日常工作只需要兩個核心功能:在圖影片中框選出人的位置,以及使用關鍵點標記他們的姿態。

這落落長如同 photoshop 的工具列讓標註人員們感到困擾,過多的選項和設定讓介面變得複雜,我觀察到他們每次要開始標註時,都需要在滿滿的功能列表中尋找工具,找到工具後開始標註,標完一個物件卻又自動跳回預設的箭頭狀態。這樣的設計完全不符合標註人員們習慣的「標完馬上接著標下一個」的狂標節奏,種種不便讓原本應該順暢的標註工作變得斷斷續續,大大降低了作業效率,也影響到了模型訓練資料的品質。

評估是否要開發一個內部工具

我的主管也發現了這個問題,在和他討論這個問題時,我們評估了幾個面向,像是團隊的標註需求其實很聚焦,不是所有專案都需要 CVAT 那麼多樣的功能,我們主要在做三種標註工作:一般物件的框選(bounding box)、車牌的框選(公司有個產品是車牌辨識系統),以及人體關鍵點的標記。另外,標註效率對我們來說極其重要,因為標註品質會直接影響到模型的訓練成果。

主管提出了一個大膽的想法:與其讓標註人員繼續使用對他們而言很複雜的 CVAT,不如打造一個完全符合內部需求的輕量化工具。這個工具不求功能多,但需要把這幾個核心功能做到極致好用。

對,然後我就被 assign 了設計與開發這個內部工具的重責大任,心情跟 CVAT 一樣複雜,但很興奮可以擔任這個主導產品的角色 (⁎⁍̴̛ᴗ⁍̴̛⁎)

一段以使用者為中心的開發歷程

經過一連串的前期準備工作:親自體驗標註流程、實際觀察標註人員的工作情形、訪談他們的使用心得,以及了解主管(aka 甲方)對工具的期待,以下我想分享這個標註工具 Anna 的幾個從使用者體驗出發,所開發的重點優化核心功能。 (順帶一提,Anna 這個名字連結了 Annotation 標註的開頭字母,也有一種好朋友的親民感 XD,故以此名稱之)

此工具前端選用的技術為 React、Redux、Typescript、D3.js,以Material UI為元件基底並以emotion css去客製元件樣式。

讓專案狀態一目瞭然的專案列表

Anna project list

Anna 的專案列表頁

內部標註流程為標註者匯入圖片創建專案後(New),開始進行圖片標註(Annotating),標註完成後需讓另一個標註人員檢視標註成果(Reviewing),修正問題後完成整個專案的標註(Complete),而完成標註的專案才能將標註結果匯出成模型需要的訓練資料。在專案列表除了會顯示上述提及的專案狀態,也顯示最後更新時間讓管理者知道此專案的標註進度是否持續被更新。

快捷鍵

// 定義快捷鍵設定的介面
interface HotKeyConfig {
  key: string; // 觸發按鍵
  modifiers?: Modifier[]; // 輔助按鍵(Ctrl、Alt 等)
  description?: string; // 功能描述
  ios?: {
    // iOS 專用設定
    key?: string;
    modifiers?: Modifier[];
  };
  action: (context: ActionContext) => void; // 觸發行為
}
 
// 快捷鍵設定範例
export const TOOL_HOT_KEYS = {
  Cursor: {
    key: "C",
    description: "切換到箭頭工具",
    action: ({ dispatch }) => {
      dispatch(setCurrentTool(Tools.Cursor));
    },
  },
  // 其他工具的快捷鍵設定...
};
 
// 實作快捷鍵 Hook
const useHotkeys = () => {
  const dispatch = useAppDispatch();
  const actionContext = useMemo(
    () => ({
      dispatch,
      // 其他需要的 context...
    }),
    [dispatch]
  );
 
  // 處理按鍵事件
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      Object.entries(TOOL_HOT_KEYS).forEach(([tool, config]) => {
        if (isHotKeyPressed(event, config)) {
          config.action(actionContext);
        }
      });
    },
    [actionContext]
  );
 
  // 註冊/移除事件監聽
  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [handleKeyDown]);
};
 
// 使用方式
function AnnotationPage() {
  useHotkeys(); // 啟用快捷鍵功能
  return <>標註頁面內容</>;
}

在標註過程中,操作的流暢性與保持工作節奏是最重要的考量。所以我設計了快捷鍵功能,將箭頭、標框工具、鎖定目標框等常用工具都整合進去。這樣的設計讓標註者可以用左手操作快捷鍵切換工具,右手進行標註,達到類似電玩遊戲中使用 W-A-S-D 鍵操控角色般的流暢體驗 😎

這個快捷鍵系統的核心是 useHotkeys 這個 custom hook,它封裝了各種快捷鍵的管理邏輯。透過定義 TOOL_HOT_KEYS 設定檔,可以找到按鍵組合的對應功能。同時也支援多個修飾鍵(如 Ctrl、Alt、Shift),並能自動適應不同作業系統(如 macOS 的 Command 鍵)。除此之外也加入了幾個防護機制,例如:阻止在輸入框中觸發快捷鍵、防止按鍵衝突,以及其他錯誤處理。

根據選取意圖來優化標註框的選取

crowded boxes

用 mock data 示意 50 個框交疊在一起的情形,選取特定的框變得很困難

當圖片中的物件太多(尤其是小物件),許多的標註框會互相交疊在一起,造成選取目標框的困難。

根據觀察,標註者會傾向以游標靠近框的四個角落或中心點來選取到框,因此在處理多個重疊的標註框時,我採用了一個直覺的距離判定方法:當游標同時進入多個重疊的標註框時,系統會計算游標位置到每個框的五個關鍵點(四個角落和中心點)的距離。

透過比較這些最短距離,系統會選擇距離最近的標註框作為使用者想要操作的目標。以此方式優化後,即使許多框交疊在一起,標註者仍可以輕鬆地選到想要編輯的框。

避免標註超出圖片之外的防呆

over image bounding - 1

over image bounding - 2

當標註者的標註範圍或是拉動標註框的編輯點超出圖片時,系統會自動修正將框的範圍修正至圖片中。

這個修正機制主要透過計算標註框的新位置來實現:首先計算游標的移動距離(dx, dy),再根據標註框的寬度和高度,確保框的邊界不會低於 0 或超過圖片的邊界,透過限制標註點的座標值,讓標註範圍始終保持在圖片範圍內。這樣的設計不僅能防止標註框超出可視範圍,也能讓標註過程更精確。

圖片縮放(zoom in & zoom out)功能

zoom in

zoom out

為了讓使用者能夠精確地標註不同尺寸的物件,我實作了縮放圖片的功能。使用者可以透過滑鼠滾輪來放大或縮小畫面,方便處理圖片中的大型物件和細節,此外只要雙擊畫面就能立即回到圖片原始尺寸。

在技術實現上,使用 D3.js 的縮放行為(zoom behavior)來處理複雜的縮放邏輯。使用 useZoom hook 來管理縮放狀態,它同時控制了圖片畫布(Canvas)和標註層(SVG)的縮放同步。為了確保效能,也使用了requestAnimationFrame來處理變形更新,並加入了 debounce 機制來減少不必要的狀態更新。

其他零星功能

上述提及的功能都是根據使用者回饋後,持續改進與優化的結果。當然,標註工具還包含了許多基礎功能,例如標註框的拖曳與尺寸調整、操作歷史紀錄、車牌辨識與人體關鍵點標註等等。

讓內部工具發揮最大效用

這個標註工具目前正被團隊積極使用中。除了協助產出模型訓練所需的資料外,我們也特別針對模型表現不佳的案例進行標註收集。這些具有針對性的標註資料,讓我們能夠有效地進行模型微調(fine-tuning),不斷提升模型的辨識效能。

我很開心參與了這個工具的發想、功能規劃,以及前端開發。這個過程讓我不只擔任開發者的角色,更體驗到擔任類似 PM 的角色,去蒐集使用者的實際回饋、平衡不同角色對工具的期待,各方仔細權衡後才能決定工具的發展方向。

不過最開心的莫過於看到這個工具確實為團隊帶來幫助。能夠開發出對他人有實質幫助的工具,讓工作流程更加順暢,我想這就是身為開發者最大的成就感了 —— 看到自己開發的工具為他人帶來正向的影響,並且持續創造價值 😎💪🏻