📢 公告:OpenCV 系列文章重構完成(75%)。專案實作篇仍在製作中,完成時間未定,敬請期待!→ 查看文章索引

Like Share Discussion Bookmark Smile

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

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

📚 前言

在上一篇 YOLOv8 資料集準備 中,我們完成了圖片蒐集、標註與資料集切分。
手動標記雖然精確,但對大量圖片來說非常耗時。

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

🔎 預標籤的原理與流程

YOLOv8 的 COCO 預訓練模型已經學會辨識 80 種常見物件(包含 cat、dog)。

🔸 如何確認 yolov8n.pt 是用 COCO 訓練的?只有 80 類?

你可以執行以下程式碼來驗證:

1
2
3
4
5
6
# check_coco_classes.py
from ultralytics import YOLO

model = YOLO("yolov8n.pt")
print("類別總數:", len(model.names))
print("類別對照表:", model.names)

執行後你會看到:

  • 類別總數為 80
  • 類別名稱包含 personcarcatdog 等常見物件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
類別總數: 80
類別對照表: {
0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus',
6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant',
11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat',
16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant',
21: 'bear', 22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella',
26: 'handbag', 27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis',
31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove',
36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle', 40: 'wine glass',
41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl',
46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli',
51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake',
56: 'chair', 57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table',
61: 'toilet', 62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote',
66: 'keyboard', 67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster',
71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase',
76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'
}

這就是官方 COCO 資料集的 80 個類別。因此只有這些類別才能使用預標籤功能。

🔸 原理說明

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

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


圖:pre_label.py 自動預標籤流程 ─ 用 YOLOv8 預訓練模型快速產生初始標註的 6 個步驟

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

🧠 函式與參數說明


圖:YOLOv8 偵測結果重要屬性 ─ box.xywhn(正規化座標)與 conf(信心度門檻)說明

💻 範例程式

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" # 原始圖片目錄(與 20260407 的 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 需要此檔案才能正確對應類別名稱,不需要手動建立。

🔄 後續步驟:完成資料集準備

預標籤只是取代了 YOLOv8 資料集準備 中的「步驟 2:手動標註」,完整的資料集流程到這裡還剩三個步驟尚未完成:

步驟 腳本 說明
步驟 3 split_dataset.py raw_images/raw_labels/ 隨機分割為訓練集(80%)與驗證集(20%)
步驟 4 create_yaml.py 產生 data.yaml,告訴 YOLOv8 資料集路徑與類別定義
步驟 5 verify_dataset.py 驗證所有圖片與標籤的格式、對應關係、class_id 範圍

這三個腳本的完整程式碼與說明請參考 YOLOv8 資料集準備 的步驟 3~5。

⚠️ 省略驗證步驟直接訓練,是訓練時「資料集格式錯誤」或「一直用舊資料」的最常見原因。

⚠️ 注意事項

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

📊 應用場景

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

🎯 結語

預標籤不是讓你省掉標記,而是把「從零畫框」變成「改錯」,後者快得多。
完成標籤修正後,別忘了回到 YOLOv8 資料集準備 完成剩餘三個步驟:用 split_dataset.py 切分資料集、用 create_yaml.py 產生 data.yaml、再用 verify_dataset.py 驗證格式無誤,才算真正備妥訓練資料。
下一步是 YOLOv8 模型訓練,正式把資料送入模型開始學習。

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

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