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 from ultralytics import YOLOimport cv2model = 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:.2 f} " print(f"偵測到:{label} ,座標:({x1} ,{y1} ) - ({x2} ,{y2} )" ) img = result.plot() cv2.imshow("YOLOv8 Detection" , img) cv2.waitKey(0 ) cv2.destroyAllWindows() 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 from ultralytics import YOLOimport osmodel = YOLO("runs/detect/custom_detector/weights/best.pt" ) img_dir = "assets/" out_dir = "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:.2 f} " ) fname = os.path.basename(image_paths[i]) r.save(filename=os.path.join(out_dir, fname)) print(f"\n完成:結果儲存至 {out_dir} " )
圖:批次讀取目錄中的所有圖片一次送入模型推論,輸出各圖片的偵測類別並儲存標註結果
💻 影片推論 1 2 3 4 5 6 7 8 9 10 11 from ultralytics import YOLOmodel = YOLO("runs/detect/custom_detector/weights/best.pt" ) results = model( "assets/test_cat_and_dog.mp4" , conf=0.5 , save=True , )
圖:對影片檔案執行 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 from ultralytics import YOLOimport cv2model = 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 from ultralytics import YOLOimport cv2model = 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:.2 f} " 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.dnn 或 onnxruntime 推論,不依賴 ultralytics:
1 2 3 4 5 6 7 8 from ultralytics import YOLOmodel = YOLO("runs/detect/custom_detector/weights/best.pt" ) model.export(format="onnx" , imgsz=640 , dynamic=False , simplify=True )
圖:將訓練好的 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 import onnxruntime as ortimport numpy as npimport cv2session = 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} " )
圖:使用 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 官方文件