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

Like Share Discussion Bookmark Smile

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

Python | OpenCV YOLOv8 推論與匯出

📚 前言

在上一篇 YOLOv8 訓練結果分析 中,我們確認了模型的訓練品質。
恭喜你!已經完成從資料集準備、預標籤、訓練,到結果分析的完整流程。

現在來到最後一步 —— 把訓練好的模型實際應用起來

這一篇會教你:

  • 如何對單張圖片、影片、即時攝影機進行推論
  • 如何自訂繪製偵測結果
  • 如何把模型匯出成 ONNX 格式(方便後續與 OpenCV 深度整合)

本篇所有範例都會用到前一篇訓練好的最佳模型:

1
runs/detect/custom_detector/weights/best.pt

若檔案不存在,請先確認 YOLOv8 訓練進階設定train_full.py 是否正常跑完。

🎨 範例圖片/影片

這裡我們使用 Pexels 提供的免費圖片素材:Cat Image
下載後將檔名改為 test_cat.jpg,放在 assets/,即可用於以下各範例。

影片範例同樣使用 Pexels 提供的免費素材:Cat And Dogs Video
下載後將檔名改為 test_cat_and_dog.mp4,放在 assets/,即可用於影片推論範例。

💻 靜態圖片推論

說明
conf=0.5 是信心度門檻,建議從 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
# inference_image.py
from ultralytics import YOLO
import cv2

model = YOLO("runs/detect/custom_detector/weights/best.pt")

# 推論
results = model("assets/test_cat.jpg", conf=0.5, save=False)

# 取得第一張結果(單張圖片通常只有一個)
result = results[0]

# 印出偵測資訊
for box in result.boxes:
cls_id = int(box.cls)
conf = float(box.conf)
x1, y1, x2, y2 = map(int, box.xyxy[0])
label = f"{model.names[cls_id]}: {conf:.2f}"
print(f"偵測到:{label},座標:({x1},{y1}) - ({x2},{y2})")

# ========== 顯示圖片(推薦寫法) ==========
img = result.plot() # 產生帶框的圖片 (BGR格式)
cv2.imshow("YOLOv8 Detection", img) # 自訂視窗名稱
cv2.waitKey(0) # 按任意鍵關閉視窗
cv2.destroyAllWindows() # 關閉所有 OpenCV 視窗

# 儲存結果
result.save(filename="output/result.jpg")
print("已儲存到 output/result.jpg")


圖:載入訓練好的 YOLOv8 模型對靜態圖片推論,取得邊界框座標、類別與信心度並儲存結果

💻 批次圖片推論

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
# inference_batch.py
from ultralytics import YOLO
import os

model = YOLO("runs/detect/custom_detector/weights/best.pt")
img_dir = "assets/"
out_dir = "output/" # 輸出目錄:output/
os.makedirs(out_dir, exist_ok=True)

image_paths = [os.path.join(img_dir, f)
for f in os.listdir(img_dir)
if f.lower().endswith((".jpg", ".png"))]

results = model(image_paths, conf=0.5, batch=8)

for i, r in enumerate(results):
print(f"\n圖片 {image_paths[i]}:")
for box in r.boxes:
cls_id = int(box.cls)
conf = float(box.conf)
print(f" {model.names[cls_id]}: {conf:.2f}")

fname = os.path.basename(image_paths[i])
r.save(filename=os.path.join(out_dir, fname)) # 保留原檔名,存入 output/

print(f"\n完成:結果儲存至 {out_dir}")


圖:批次讀取目錄中的所有圖片一次送入模型推論,輸出各圖片的偵測類別並儲存標註結果

💻 影片推論

1
2
3
4
5
6
7
8
9
10
11
# inference_video.py
from ultralytics import YOLO

model = YOLO("runs/detect/custom_detector/weights/best.pt")

# 對影片推論,結果自動儲存
results = model(
"assets/test_cat_and_dog.mp4",
conf=0.5,
save=True, # 儲存標註後的影片,預設輸出在 runs/detect/predict/
)


圖:對影片檔案執行 YOLOv8 推論,自動儲存標註後的輸出影片

💻 即時攝影機推論

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# inference_camera.py
from ultralytics import YOLO
import cv2

model = YOLO("runs/detect/custom_detector/weights/best.pt")

cap = cv2.VideoCapture(0)
print("按 q 離開")

while True:
ret, frame = cap.read()
if not ret:
break

results = model(frame, conf=0.5, verbose=False)
annotated = results[0].plot()

cv2.imshow("YOLOv8 Detection", annotated)

if cv2.waitKey(1) & 0xFF == ord("q"):
break

cap.release()
cv2.destroyAllWindows()

📝 註:由於本身沒有攝影鏡頭,所以無法示範效果。

💻 手動繪製偵測結果(自訂樣式)

若需要自訂邊界框顏色或字型,可不使用 .plot() 而自行繪製:

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
# inference_camera_custom.py
from ultralytics import YOLO
import cv2

model = YOLO("runs/detect/custom_detector/weights/best.pt")

COLORS = [(0,255,0), (255,0,0), (0,0,255), (255,255,0)] # 每個類別一個顏色

cap = cv2.VideoCapture(0)

while True:
ret, frame = cap.read()
if not ret:
break

results = model(frame, conf=0.5, verbose=False)

for box in results[0].boxes:
cls_id = int(box.cls)
conf = float(box.conf)
x1,y1,x2,y2 = map(int, box.xyxy[0])
color = COLORS[cls_id % len(COLORS)]
label = f"{model.names[cls_id]} {conf:.2f}"

cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
cv2.putText(frame, label, (x1, y1 - 8),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)

cv2.imshow("YOLOv8", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break

cap.release()
cv2.destroyAllWindows()

📝 註:由於本身沒有攝影鏡頭,所以無法示範效果。

💻 匯出為 ONNX

匯出 ONNX 後可用 cv2.dnnonnxruntime 推論,不依賴 ultralytics:

1
2
3
4
5
6
7
8
# export_onnx.py
from ultralytics import YOLO

model = YOLO("runs/detect/custom_detector/weights/best.pt")

# 匯出為 ONNX
model.export(format="onnx", imgsz=640, dynamic=False, simplify=True)
# 匯出後產生:runs/detect/custom_detector/weights/best.onnx


圖:將訓練好的 YOLOv8 模型匯出為 ONNX 格式,供跨平台部署使用

使用 onnxruntime 推論:

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
# inference_onnx.py
import onnxruntime as ort
import numpy as np
import cv2

session = ort.InferenceSession("runs/detect/custom_detector/weights/best.onnx")
input_name = session.get_inputs()[0].name

def preprocess(img, imgsz=640):
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_rsz = cv2.resize(img_rgb, (imgsz, imgsz))
blob = img_rsz.astype(np.float32) / 255.0
return np.expand_dims(blob.transpose(2, 0, 1), axis=0)

img = cv2.imread("assets/test_cat.jpg")
blob = preprocess(img)

outputs = session.run(None, {input_name: blob})
print(f"輸出形狀:{outputs[0].shape}")
# 輸出形狀為 (1, 6, 8400)
# 意義說明:
# - 第一維 1 → batch size
# - 第二維 6 → 每個候選框包含的資訊數量
# = 4(邊界框:x_center, y_center, width, height)
# + 1(objectness / confidence)
# + 1(你的自訂類別數,目前應該是 2 類:cat 和 dog?)
# - 第三維 8400 → 候選框總數量(YOLOv8 在 640x640 輸入時通常為 8400)
#
# 注意:
# YOLOv8 的 ONNX 輸出格式與 YOLOv5 不同,已經把 class confidence 與 objectness 合併處理。
# 你必須自行實作:
# 1. 過濾低信心度
# 2. 還原座標 (從 center+wh → xyxy)
# 3. Non-Maximum Suppression (NMS)


圖:使用 onnxruntime 載入 ONNX 模型,對圖片進行前處理並執行推論取得原始輸出張量

💡 ONNX 輸出的後處理(NMS、座標還原)較複雜,實際部署建議直接使用 ultralytics 的 Python API,或使用 cv2.dnn.readNetFromONNX 搭配 YOLOv8 的後處理邏輯。

💻 其他匯出格式

各格式有平台限制,請依環境選擇:

格式 需求 適用場景
engine(TensorRT) NVIDIA GPU + TensorRT 安裝 伺服器端高速推論
coreml macOS 環境 iPhone / iPad 部署
tflite 無特殊需求 Android / 嵌入式裝置

⚠️ 注意事項

  • conf 閾值的設定:預設為 0.25,太低會有很多誤報,太高會漏掉低信心的正確偵測,需根據應用場景調整。
  • iou 閾值(NMS):預設為 0.7,控制重疊邊界框的過濾,物件密集的場景建議調低(如 0.5)。
  • verbose=False:在即時推論的迴圈中必須設定,否則每幀都會輸出推論資訊,嚴重影響效能。
  • ONNX 的後處理:YOLOv8 的 ONNX 輸出格式在不同版本間可能略有差異,建議以 ultralytics 的 Python API 為主,ONNX 用於需要脫離 Python 環境的部署場景。

📊 應用場景

  • 工廠自動品管:用訓練好的瑕疵偵測模型,對生產線即時攝影機畫面進行偵測。
  • 倉庫商品辨識:偵測並定位貨架上的商品,輔助自動化盤點。
  • 安全監控:偵測特定人員或行為,即時發出警報。

🎯 結語

至此,完整的 YOLOv8 自訓練物件偵測流程全部走完:

  • 環境安裝 → 資料集準備 → 模型訓練 → 結果分析 → 推論與匯出

掌握這個流程,就能針對任何你想偵測的物件,從零開始訓練出專屬的 YOLOv8 模型。

下一篇是 YOLOv8 常見問題 Q&A,整理學完整個流程後最常遇到的問題,包含增加新類別、遷移學習策略與獨立模型的優缺點。

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

註:以上參考了
Ultralytics YOLOv8 官方文件 — Predict
Ultralytics YOLOv8 官方文件 — Export
Ultralytics YOLOv8 官方文件 — Python Usage
ONNX Runtime 官方文件