案例目标:模型量化 → 打包成 ONNX → 编写 load_onnx.py 加载推理。ONNX(Open Neural Network Exchange)是模型界的"通用 PDF":训练框架各说各话,导出成 ONNX 后任何支持它的运行时(onnxruntime、OpenCV、TensorRT…)都能跑,是工业部署的标准格式。
# quantize_onnx.py —— 先导出再量化(INT8 动态量化对 CNN 检测模型几乎无损)
from ultralytics import YOLO
# ultralytics 一行导出 ONNX(也可视为步骤4-2的一部分)
model = YOLO("runs/sign/exp1/weights/best.pt")
model.export(format="onnx", imgsz=640) # 得到 best.onnx
# INT8 动态量化
from onnxruntime.quantization import quantize_dynamic, QuantType
quantize_dynamic(
model_input="best.onnx",
model_output="best_int8.onnx",
weight_type=QuantType.QUInt8) # 权重压成 8bit 整数
# load_onnx.py —— 纯 onnxruntime 推理:预处理 → session.run → 阈值过滤
import cv2, numpy as np, onnxruntime as ort
# 1. 创建会话;providers 指定优先用 CUDA,没有 GPU 自动退回 CPU
sess = ort.InferenceSession("best_int8.onnx",
providers=["CUDAExecutionProvider", "CPUExecutionProvider"])
inp = sess.get_inputs()[0] # 拿输入名和期望尺寸
IMG_SIZE = (inp.shape[2], inp.shape[3]) # 如 (640, 640)
CONF_TH, IOU_TH = 0.25, 0.45
def detect(img_path):
img0 = cv2.imread(img_path) # 原图 (BGR)
# 2. 预处理:letterbox 缩放 → BGR转RGB → HWC转CHW → 归一化0~1 → 加batch维
r = min(IMG_SIZE[0] / img0.shape[0], IMG_SIZE[1] / img0.shape[1])
img = cv2.resize(img0, (int(img0.shape[1]*r), int(img0.shape[0]*r)))
canvas = np.full((*IMG_SIZE, 3), 114, np.uint8) # 灰边补齐
canvas[:img.shape[0], :img.shape[1]] = img
blob = cv2.dnn.blobFromImage(canvas, 1/255.0, swapRB=True).astype(np.float32)
# 3. 推理:输入名从 sess 里取,别写死
pred = sess.run(None, {inp.name: blob})[0] # (1, 84, 8400) yolov8输出
pred = pred.squeeze().T # → (8400, 84):4框坐标 + 3类分数
boxes, scores, cls_ids = [], [], []
for p in pred:
cls_id = p[4:].argmax(); conf = p[4 + cls_id]
if conf > CONF_TH: # 置信度过滤
cx, cy, w, h = p[:4]
# 还原到原图坐标(去 letterbox 缩放)
boxes.append([int((cx-w/2)/r), int((cy-h/2)/r),
int(w/r), int(h/r)])
scores.append(float(conf)); cls_ids.append(int(cls_id))
# 4. NMS 去掉重叠框(OpenCV 自带现成实现)
idx = cv2.dnn.NMSBoxes(boxes, scores, CONF_TH, IOU_TH)
for i in idx.flatten():
x, y, w, h = boxes[i]
cv2.rectangle(img0, (x, y), (x+w, y+h), (0, 200, 0), 2)
cv2.putText(img0, f"cls{cls_ids[i]} {scores[i]:.2f}", (x, y-5),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 200, 0), 2)
return img0, cls_ids
out, labels = detect("test.jpg")
cv2.imwrite("result.jpg", out)
print("检出类别:", labels)
| 库 | 关键点 |
|---|---|
onnxruntime | 微软出的 ONNX 推理引擎。InferenceSession 加载模型、run(None, {输入名: blob}) 执行推理;子包 onnxruntime.quantization 提供 quantize_dynamic 一行量化。 |
ultralytics | YOLOv8 官方库,训练/验证/导出一条龙:model.train() / model.val() / model.export(format="onnx")。它内部也封装了 ONNX 推理(YOLO("best.onnx") 可直接加载),但工程上常需要自己提供 load_onnx.py,所以要会用裸 onnxruntime 写。 |
cv2.dnn.NMSBoxes | 非极大值抑制:多个框叠在同一个目标上时,只留置信度最高的那个。检测后处理必备。 |
— AI训练师技术交流教程 · 仅供学习交流 —