CPU 上用 C++ 调用 ONNX 模型进行推理,对模型进行 INT8 量化
步骤操作1用导出标准模型(无 NMS)2准备校准数据(320x320 图像,numpy 格式)3用生成 INT8 ONNX4C++ 用 ONNX Runtime 加载int8.onnx模型推理这样你就能在环境下实现INT8 量化加速。
在 CPU 上用 C++ 调用 ONNX 模型进行推理,并希望对模型进行 INT8 量化以提升性能。
✅ 简短回答:
ONNX 本身不包含 INT8 量化能力,但你可以通过 ONNX Runtime(ONNX Runtime with quantization tools)对 ONNX 模型进行后训练量化(PTQ),生成 INT8 的 ONNX 模型,然后在 C++ 中用 ONNX Runtime CPU 执行它。
也就是说:可以做 INT8 量化,但不是在 yolo export 阶段完成,而是在导出 ONNX 后,用 ONNX Runtime 的量化工具进行。
🔧 具体步骤如下:
第一步:导出标准 ONNX 模型(你已经完成)
yolo export model=best31n.pt format=onnx imgsz=320 simplify=True opset=12 nms=False
⚠️ 注意:不要开启
nms=True,因为 ONNX Runtime 的量化工具不支持带自定义 NMS 算子的模型(NMS 通常是非标准 ONNX 算子)。建议在后处理阶段用 C++ 实现 NMS。
第二步:准备校准数据集
你需要一个代表实际输入分布的小数据集(比如 100~500 张图像),用于 INT8 校准。这些图像应:
- 尺寸为 320x320
- 归一化方式与训练一致(通常为
img / 255.0) - 保存为
.npy或通过脚本加载为 numpy 数组
第三步:使用 ONNX Runtime 的量化工具进行 INT8 量化
安装 ONNX Runtime(含量化工具):
pip install onnxruntime onnx onnxruntime-extensions
创建量化脚本 quantize_onnx.py:
import onnx
from onnxruntime.quantization import quantize_static, QuantType, CalibrationDataReader
class YoloCalibrationDataReader(CalibrationDataReader):
def __init__(self, data_loader):
self.data_loader = iter(data_loader)
self.enum_data = None
def get_next(self):
if self.enum_data is None:
self.enum_data = next(self.data_loader, None)
if self.enum_data is not None:
data = self.enum_data
self.enum_data = None
# 假设 data 是 (1, 3, 320, 320) numpy array
return {"images": data} # 注意:输入节点名需匹配你的 ONNX 模型
return None
# 示例:加载你的校准数据(这里简化为随机数据)
import numpy as np
calibration_data = [np.random.rand(1, 3, 320, 320).astype(np.float32) for _ in range(100)]
data_reader = YoloCalibrationDataReader(calibration_data)
quantize_static(
model_input="best31n.onnx",
model_output="best31n_int8.onnx",
calibration_data_reader=data_reader,
quant_format=QuantFormat.QDQ, # 或 QuantFormat.QOperator(更紧凑但兼容性略差)
activation_type=QuantType.QUInt8,
weight_type=QuantType.QUInt8,
op_types_to_quantize=['Conv', 'MatMul'], # 可选
per_channel=False,
reduce_range=False
)
print("INT8 quantization finished.")
🔍 关键点:
- 你需要知道 ONNX 模型的输入节点名(用 Netron 打开
.onnx文件查看,通常是"images"或"input")。quantize_static使用 静态校准(PTQ),适合 CPU 推理。- 输出的
best31n_int8.onnx是标准 ONNX 模型,包含 QuantizeLinear / DequantizeLinear 节点。
第四步:C++ 中使用 ONNX Runtime 推理 INT8 模型
ONNX Runtime 的 C++ API 完全支持量化模型(CPU 执行):
- 安装 ONNX Runtime C++ 库(https://github.com/microsoft/onnxruntime)
- 编译时链接
onnxruntime.lib - 推理代码与 FP32 几乎相同,无需额外处理量化逻辑
示例伪代码:
Ort::Env env;
Ort::Session session(env, L"best31n_int8.onnx", session_options);
// 输入数据:float32(0~1),ONNX Runtime 自动处理量化
auto output = session.Run(...);
✅ ONNX Runtime 会在 CPU 上自动将 FP32 输入转为 INT8(通过 QuantizeLinear),执行量化算子,再转回 FP32 输出(或保留 INT8,取决于模型结构)。
⚠️ 注意事项
- 不要在
yolo export时加int8=True→ 对 ONNX 无效。 - 避免
nms=True→ 自定义 NMS 会破坏量化兼容性。 - 校准数据质量影响精度 → 使用真实场景图像。
- INT8 量化可能轻微掉点 → 需验证 mAP 是否可接受。
- 性能提升依赖 CPU 指令集 → 支持 AVX2/AVX-512 的 CPU 效果更好。
✅ 总结
| 步骤 | 操作 |
|---|---|
| 1 | 用 yolo export format=onnx 导出标准模型(无 NMS) |
| 2 | 准备校准数据(320x320 图像,numpy 格式) |
| 3 | 用 onnxruntime.quantization.quantize_static 生成 INT8 ONNX |
| 4 | C++ 用 ONNX Runtime 加载 int8.onnx 模型推理 |
这样你就能在 CPU + C++ + ONNX 环境下实现 INT8 量化加速。
更多推荐


所有评论(0)