Python | OpenCV 資料標註
📚 前言
在上一篇 資料蒐集 中,我們蒐集好了訓練所需的圖片。
接下來要進行的是 資料標註 (Data Annotation),也就是為每張圖片建立「正確答案」,讓模型知道圖片裡有什麼。
標註的品質直接影響模型的學習成效,錯誤或不一致的標註會讓模型學到錯誤的規則。
🔎 標註類型
依照任務不同,標註方式也不同:
| 任務類型 | 標註方式 | 說明 |
|---|---|---|
| 圖片分類 | 類別標籤 | 為整張圖片標記一個類別 |
| 物件偵測 | 邊界框 (Bounding Box) | 框出物件位置並標記類別 |
| 語義分割 | 像素遮罩 (Mask) | 逐像素標記所屬類別 |
| 實例分割 | 個別物件遮罩 | 為每個物件實例建立獨立遮罩 |
| 關鍵點偵測 | 座標點 | 標記特定部位的座標(如人體骨架) |
🧠 標註格式說明
不同框架使用不同的標註格式,常見格式如下:
YOLO 格式
每張圖片對應一個 .txt 檔案,每行代表一個物件:
1 | <class_id> <x_center> <y_center> <width> <height> |
- 所有數值皆為相對圖片寬高的比例(0.0 ~ 1.0)
- 範例:
0 0.5 0.4 0.3 0.2
COCO 格式
使用單一 JSON 檔案描述所有圖片與標註:
1 | { |
Pascal VOC 格式
每張圖片對應一個 .xml 檔案:
1 | <annotation> |
💻 標註工具介紹
LabelImg
輕量的本地端標註工具,支援 YOLO 與 Pascal VOC 格式。
1 | pip install labelImg |

操作方式:
- Open Dir:開啟
collect_from_video.py的輸出目錄(例如dataset/toy_car/) - Change Save Dir:設定為相同目錄,標籤
.txt將存放於此 - 選擇儲存格式(YOLO 或 Pascal VOC)
- 按
W開始畫邊界框 - 輸入類別名稱後儲存

⌨️ 核心常用快捷鍵
| 快捷鍵 | 功能 |
|---|---|
W |
畫邊界框(Create RectBox) |
D |
下一張圖片 |
A |
上一張圖片 |
Ctrl + S |
儲存當前標註 |
Del |
刪除選取的邊界框 |
Space |
標記為已驗證(Verified) |
Ctrl + D |
複製選取的邊界框 |
Ctrl + Shift + D |
刪除當前圖片 |
Ctrl + 滾輪 |
縮放圖片 |
⚠️ 已知問題:按 W 標記時崩潰
labelImg的原始 repo 已被封存(archived),不再維護,與新版 PyQt5(5.15+)存在相容性問題。
新版 PyQt5 改為嚴格型別模式,QPointF.x() 回傳 float,但 drawLine、drawRect 等方法要求 int,導致 crash。舊版 PyQt5 會自動做型別轉換,所以不會出現這個問題。





有三種處理方式:
| 方式 | 說明 | 缺點 |
|---|---|---|
| 降版 PyQt5 到 5.14 以下 | pip install PyQt5==5.14.2 |
可能影響其他套件 |
改用 labelme |
pip install labelme |
預設輸出 JSON,需另行轉換為 YOLO 格式 |
| 直接修原始碼 | 修 canvas.py 與 labelImg.py 共兩處 |
重裝套件後須重修 |
若選擇直接修,需修改兩個檔案:
canvas.py:找到以下三行:
1 | p.drawRect(left_top.x(), left_top.y(), rect_width, rect_height) |
改為:
1 | p.drawRect(int(left_top.x()), int(left_top.y()), int(rect_width), int(rect_height)) |
labelImg.py(修改一):找到 scroll_request 方法中的這行:
1 | bar.setValue(bar.value() + bar.singleStep() * units) |
改為:
1 | bar.setValue(int(bar.value() + bar.singleStep() * units)) |
labelImg.py(修改二):找到 zoom_request 方法,共有三行需要修改:
1 | self.add_zoom(scale * units) |
改為:
1 | self.add_zoom(int(scale * units)) |
💡 三處 crash 原因相同:Python 3 的除法與乘法結果為 float,但
setValue與add_zoom只接受 int,加上int()即可。scroll_request修的是滾輪平移,zoom_request修的是滾輪縮放(縮放量 + 視窗位移),共四處都需要補上int()。
⚠️ 已知問題:存檔後 classes.txt 遺失類別

LabelImg 每次存檔時,只把這張圖用到的類別寫進 classes.txt,原本已有的其他類別會被清掉。例如你標了一張只有 cat 的圖後存檔,classes.txt 就只剩 cat,下一張有 dog(class_id=1)的圖開啟時會 crash:
1 | IndexError: list index out of range |
這是 LabelImg 設計上的缺陷,repo 已封存不會修復。直接修 libs/yolo_io.py 的 save() 方法,在開檔寫入前先讀取現有類別:
找到以下段落:
1 | if target_file is None: |
改為:
1 | if target_file is None: |
CVAT (Computer Vision Annotation Tool)
功能完整的網頁標註平台,支援邊界框、多邊形、分割遮罩等多種標註類型。
- 可自架或使用 app.cvat.ai 線上版
- 支援多人協作標註
- 匯出格式:YOLO、COCO、Pascal VOC 等
Roboflow
整合資料管理、標註、增強與匯出的雲端平台。
- 可直接在瀏覽器標註並管理資料集版本
- 支援自動標註(Auto-Label)輔助加速
- 可直接匯出為 YOLOv5、YOLOv8、COCO 等訓練格式
✂️ 訓練集與驗證集切分
標註完成後,需要將資料分為訓練集與驗證集。有兩種做法:
做法一:拍兩支影片(建議)
用不同背景或光線各拍兩段,分別執行 collect_from_video.py 收集後各自標註,自然形成訓練集與驗證集的資料分離:
toy_car_A.mp4(桌面背景、自然光):SAVE_DIR = "dataset/raw_train/"→ LabelImg 標註 → 整理至images/train/與labels/train/toy_car_B.mp4(地板背景、室內燈):SAVE_DIR = "dataset/raw_val/"→ LabelImg 標註 → 整理至images/val/與labels/val/
這樣驗證集場景與訓練集不同,能真正測試模型是否學到物件本身的特徵,而不是背景。
做法二:只有一支影片,按比例切分
標註完成後,圖片(.jpg)與標籤(.txt)存放在同一目錄,以下腳本將前 80% 分給訓練集、後 20% 分給驗證集,圖片與標籤同步搬移:
1 | # split_dataset.py |

圖:split_dataset.py 將圖片與標籤同步切分為訓練集與驗證集
⚠️ 只有一支影片時,驗證集與訓練集來自同一場景、同一光線,泛化測試效果較有限,建議後續補拍第二支影片替換。
🗃️ 資料目錄結構
標註並切分完成後,資料目錄結構依任務類型如下:
分類任務:
1 | dataset/ |
PyTorch ImageFolder 與 Keras image_dataset_from_directory 都能自動讀取這個結構,資料夾名稱即為類別標籤。
物件偵測任務(YOLO 格式):
1 | dataset/ |
圖片與標註檔案分開存放,例如 images/train/0001.jpg 對應 labels/train/0001.txt。
💻 範例程式 — 以 Python 驗證標註結果
標註並切分完成後,可用以下程式將標註框繪製在圖片上,確認標註是否正確。
驗證 YOLO 格式標註
1 | # verify_annotation.py |

圖:讀取 YOLO 格式標註檔並將邊界框繪製在圖片上,驗證標註位置是否正確
批次統計標註數量
1 | # count_labels.py |

圖:批次掃描標籤目錄統計各類別的標註數量並輸出結果
💡 class ID 對應的類別名稱記錄在 LabelImg 產生的
classes.txt(與圖片存放於同一目錄),可對照查詢。
⚠️ 注意事項
- 標註一致性:同一個類別的邊界框應涵蓋範圍一致,不要有時框緊、有時框鬆。
- 遮擋物件:被遮擋超過 50% 以上的物件,可考慮不標註,避免干擾訓練。
- 類別命名:整個資料集的類別名稱與 ID 對應必須統一,避免混淆。
- 定期備份:標註結果是耗時的人工成果,務必做好版本備份。
📊 應用場景
- 工廠瑕疵偵測:標註良品與瑕疵位置,訓練自動品管模型。
- 醫學影像分析:標註病灶區域,協助輔助診斷模型訓練。
- 自駕車感知:標註車輛、行人、號誌等物件,建立環境感知模型。
🎯 結語
資料標註是整個訓練流程中最耗費人力的環節,但也是品質的關鍵所在。
善用標註工具並建立一致的標註規範,能大幅提升後續訓練的效果。
下一步是進入 模型選擇與訓練,將標註好的資料送入模型進行學習。
📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。
註:以上參考了
OpenCV 官方文件 — Tutorials
LabelImg GitHub
CVAT 官方網站
Roboflow 官方網站
COCO Dataset 格式說明
