Like Share Discussion Bookmark Smile

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

Python | OpenCV YOLOv8 預標籤(Pre-Label)

📚 前言

資料標註 篇中,我們介紹了用 LabelImg 手動畫邊界框的流程。
手動標記雖然精確,但對大量圖片來說非常耗時。

如果你要標記的類別(例如 catdog)剛好在 YOLOv8 預訓練模型支援的 COCO 80 類別內,可以先讓模型跑一遍推論,自動產生標籤草稿,再用 LabelImg 只修正錯誤的框,速度可以快上數倍。

🔎 原理說明

YOLOv8 的 COCO 預訓練模型能偵測 80 種物件,偵測結果包含:

  • 類別 ID(對應 COCO 80 類)
  • 邊界框座標(已是相對比例,可直接寫入 YOLO txt)

pre_label.py 的流程:

1
2
3
4
5
6
7
8
9
10
11
① 載入 YOLOv8 預訓練模型(yolov8n.pt)

② 對 raw_images/ 中的每張圖片推論

③ 過濾出我們需要的類別(cat、dog)

④ 將 COCO class_id 重新對應為我們的 0-based ID

⑤ 輸出 YOLO txt 標籤至 raw_labels/

⑥ 用 LabelImg 開啟圖片 + 標籤,修正錯誤的框

💡 COCO 資料集中 cat 的 class_id 是 15,dog 是 16,與我們 data.yaml 定義的 0、1 不同,必須重新對應,否則 class_id 會錯。

🧠 函式與參數說明

📌 box.xywhn

YOLOv8 偵測結果中,box.xywhn 直接回傳已正規化的座標(0.0~1.0),格式為 [x_center, y_center, width, height],可以不用手動換算,直接寫入 YOLO txt。

📌 conf 信心度門檻

推論時設定 conf=0.5 過濾低信心度的結果,避免把不確定的框也寫入標籤,減少後續手動刪除的工作量。值越高越嚴格,可依圖片品質調整。

💻 範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# pre_label.py
import os
from ultralytics import YOLO

# ── 設定 ────────────────────────────────────
model_path = "yolov8n.pt" # 預訓練模型,第一次執行會自動下載
src_dir = "raw_images" # 原始圖片目錄(與 20260331 的 download_images.py 輸出一致)
dst_dir = "raw_labels" # 標籤輸出目錄
conf_threshold = 0.5 # 信心度門檻,低於此值的偵測結果會被過濾
target_classes = {"cat": 0, "dog": 1} # 只保留這些類別,並重新對應為 0-based class_id
# ────────────────────────────────────────────

model = YOLO(model_path)
coco_names = model.names # COCO 80 類別名稱對照表(dict: id → name)

os.makedirs(dst_dir, exist_ok=True)

# 產生 classes.txt,LabelImg 需要此檔案才能正確對應類別名稱
classes_txt = os.path.join(dst_dir, "classes.txt")
with open(classes_txt, "w") as f:
for name in sorted(target_classes, key=target_classes.get):
f.write(name + "\n")

img_files = [f for f in os.listdir(src_dir)
if f.lower().endswith((".jpg", ".jpeg", ".png"))]

for fname in img_files:
img_path = os.path.join(src_dir, fname)
stem = os.path.splitext(fname)[0]
lbl_path = os.path.join(dst_dir, stem + ".txt")

results = model(img_path, conf=conf_threshold, verbose=False)[0]
lines = []

for box in results.boxes:
coco_cls_id = int(box.cls)
coco_name = coco_names[coco_cls_id]
if coco_name not in target_classes:
continue # 過濾不需要的類別

new_cls_id = target_classes[coco_name]
x, y, w, h = box.xywhn[0].tolist() # 已是相對比例,直接使用
lines.append(f"{new_cls_id} {x:.6f} {y:.6f} {w:.6f} {h:.6f}")

with open(lbl_path, "w") as f:
f.write("\n".join(lines))

status = f"{len(lines)} 個標籤" if lines else "無偵測結果(空標籤)"
print(f"{fname}: {status}")

print(f"\n完成:共處理 {len(img_files)} 張圖片,標籤輸出至 {dst_dir}/")


圖:對 raw_images/ 批次推論並輸出 YOLO txt 標籤至 raw_labels/,顯示每張圖片的偵測數量

💻 用 LabelImg 修正標籤

執行完 pre_label.py 後,raw_labels/ 已有自動產生的標籤草稿。接著用 LabelImg 開啟修正:

  1. Open Dir:選擇 raw_images/
  2. Change Save Dir:選擇 raw_labels/(LabelImg 會自動載入同名的 .txt
  3. 儲存格式切換為 YOLO
  4. 逐張檢查,刪除錯誤的框、補畫漏標的物件、修正類別
  5. Ctrl + S 儲存後按 D 切到下一張


圖:在 LabelImg 中載入自動產生的標籤草稿,修正偵測錯誤的邊界框

💡 pre_label.py 執行時會自動產生 raw_labels/classes.txt,LabelImg 需要此檔案才能正確對應類別名稱,不需要手動建立。

⚠️ 注意事項

  • 只適用於 COCO 80 類別內的物件:若你要標記的類別不在 COCO 80 類別內(例如特定商品、自訂符號),預標籤無法使用,只能全手動或先用少量資料訓練一個初版模型再回頭預標。
  • 預標籤不等於正確標籤:模型可能漏標、誤標,每張圖都必須人工確認,不能直接用於訓練。
  • 空標籤檔案需保留:模型未偵測到目標的圖片,pre_label.py 會輸出空的 .txt,這是正確的 YOLO 格式,不要刪除。
  • 信心度門檻影響標籤品質conf 設太低會產生大量誤標框,設太高會漏掉部分真實物件,建議先用 0.5 再依實際結果調整。

📊 應用場景

  • 大量圖片需要標記:100 張以上的資料集,預標籤可以省去大部分畫框時間,只需修正。
  • 新類別自訓練的冷啟動:先用 COCO 預標籤標出相近類別(例如用 person 預標人物),修正後訓練初版模型,再用初版模型回頭預標更多資料,形成正向循環。

🎯 結語

預標籤不是讓你省掉標記,而是把「從零畫框」變成「改錯」,後者快得多。
完成標籤修正後,依照 YOLOv8 資料集準備 篇的 split_dataset.py 切分資料集,即可進入訓練流程。

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

註:以上參考了
Ultralytics YOLOv8 官方文件 — Predict
Ultralytics YOLOv8 官方文件 — Results
COCO Dataset — Categories