📢 公告:OpenCV 系列文章目前正在重構整理中(進度約 55%),部分文章已暫時下架,後續會陸續補上,完成時間待定。感謝耐心等候!

Like Share Discussion Bookmark Smile

J.J. Huang   2026-03-25   Python OpenCV 07.物件偵測與辨識篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV LabelImg 標註工具實戰

📚 前言

在上一篇 資料標註 中,我們介紹了常見的標註格式與工具概覽。
本篇介紹 LabelImg 的安裝、問題修正,以及基本操作。

💻 安裝與開啟

1
2
pip install labelImg
labelImg


圖:LabelImg 啟動後的主介面

🔎 相容性問題說明

LabelImg 已停止維護,與新版 PyQt5(5.15+)有相容性問題,會在按 W 畫框或存檔時 crash。

先確認目前的 PyQt5 版本:

1
pip show PyQt5

Version5.15 以上,需要手動修正原始碼(見下方)。

不想改原始碼,可以選擇:降版 pip install PyQt5==5.14.2,或改用 labelme(但預設輸出 JSON,需額外轉換格式)。

🗂️ 找到要修改的檔案

1
pip show labelImg

查看 Location 欄位取得安裝路徑,需修改的三個檔案位於:

1
2
3
4
5
<Location>/labelImg/
├── labelImg.py
└── libs/
├── canvas.py
└── yolo_io.py

⚠️ 已知問題與修正

問題一:按 W 畫框時崩潰





canvas.py

1
2
3
4
# canvas.py(修改前)
p.drawRect(left_top.x(), left_top.y(), rect_width, rect_height)
p.drawLine(self.prev_point.x(), 0, self.prev_point.x(), self.pixmap.height())
p.drawLine(0, self.prev_point.y(), self.pixmap.width(), self.prev_point.y())
1
2
3
4
# canvas.py(修改後)
p.drawRect(int(left_top.x()), int(left_top.y()), int(rect_width), int(rect_height))
p.drawLine(int(self.prev_point.x()), 0, int(self.prev_point.x()), self.pixmap.height())
p.drawLine(0, int(self.prev_point.y()), self.pixmap.width(), int(self.prev_point.y()))

labelImg.pyscroll_request 方法:

1
2
# labelImg.py(修改前)
bar.setValue(bar.value() + bar.singleStep() * units)
1
2
# labelImg.py(修改後)
bar.setValue(int(bar.value() + bar.singleStep() * units))

labelImg.pyzoom_request 方法:

1
2
3
4
# labelImg.py(修改前)
self.add_zoom(scale * units)
h_bar.setValue(new_h_bar_value)
v_bar.setValue(new_v_bar_value)
1
2
3
4
# labelImg.py(修改後)
self.add_zoom(int(scale * units))
h_bar.setValue(int(new_h_bar_value))
v_bar.setValue(int(new_v_bar_value))

問題二:存檔後 classes.txt 遺失類別

每次存檔只保留該張圖用到的類別,其餘類別會被清掉,導致下一張圖開啟時 crash。

libs/yolo_io.py

1
2
3
4
5
6
7
8
9
10
# libs/yolo_io.py(修改前)
if target_file is None:
out_file = open(
self.filename + TXT_EXT, 'w', encoding=ENCODE_METHOD)
classes_file = os.path.join(os.path.dirname(os.path.abspath(self.filename)), "classes.txt")
out_class_file = open(classes_file, 'w')
else:
out_file = codecs.open(target_file, 'w', encoding=ENCODE_METHOD)
classes_file = os.path.join(os.path.dirname(os.path.abspath(target_file)), "classes.txt")
out_class_file = open(classes_file, 'w')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# libs/yolo_io.py(修改後)
if target_file is None:
out_file = open(
self.filename + TXT_EXT, 'w', encoding=ENCODE_METHOD)
classes_file = os.path.join(os.path.dirname(os.path.abspath(self.filename)), "classes.txt")
else:
out_file = codecs.open(target_file, 'w', encoding=ENCODE_METHOD)
classes_file = os.path.join(os.path.dirname(os.path.abspath(target_file)), "classes.txt")

if os.path.exists(classes_file):
with open(classes_file, 'r') as cf:
for line in cf:
c = line.strip()
if c and c not in class_list:
class_list.append(c)

out_class_file = open(classes_file, 'w')

💡 基本操作

修正完成後,重新執行 labelImg 開始標註:

  1. Open Dir:開啟圖片目錄(例如 dataset/toy_car/
  2. Change Save Dir:設定標籤存放目錄(建議與圖片同目錄)
  3. 選擇儲存格式(YOLO 或 Pascal VOC)
  4. W 畫邊界框,輸入類別名稱後儲存

每張圖片存檔後,會在 Change Save Dir 設定的目錄下產生同名的 .txt 標籤檔(YOLO 格式)與 classes.txt,記錄所有使用過的類別名稱。


圖:使用 LabelImg 對圖片畫邊界框並標記類別

📦 範例資料集:

  • 載點:toy_car_labeled.zip
  • 內容:已完成 LabelImg 標註的玩具車圖片,包含 .jpg 圖片與對應的 .txt 標籤檔(YOLO 格式)及 classes.txt
  • 解壓縮後可直接用於後續的資料集切分與模型訓練。

⌨️ 核心快捷鍵

快捷鍵 功能
W 畫邊界框
D / A 下 / 上一張圖片
Ctrl + S 儲存
Del 刪除選取的框
Space 標記為已驗證
Ctrl + D 複製選取的框
Ctrl + 滾輪 縮放

⚠️ 注意事項

  • 標註一致性:同類別的框涵蓋範圍要一致,不要時框緊、時框鬆。
  • 遮擋物件:被遮擋超過 50% 可考慮不標,避免干擾訓練。
  • 類別命名:類別名稱與 ID 對應必須全程統一。
  • 定期備份:標註是耗時的人工成果,務必備份。

🎯 結語

修正兩個已知問題後,LabelImg 仍可穩定用於個人資料集的標註。
下一篇進入 資料集整理與驗證,介紹標註完成後如何切分訓練集與驗證集,以及如何用程式確認標註是否正確。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
LabelImg GitHub