ONNX Runtime 推理说明
1. 为什么使用 ONNX Runtime
在训练阶段,目标检测模型通常使用 PyTorch / Ultralytics YOLOv8 完成。 但在生产环境(Java 服务端、Android 等)无法直接运行 Python 推理,因此需要:
将训练好的模型导出为 ONNX → 使用 ONNX Runtime 执行推理
ONNX Runtime 是微软维护的高性能跨平台推理引擎,特点:
- 不依赖 Python
- 内存占用低
- 启动速度快
- 多线程推理稳定
- 支持 CPU / CUDA / TensorRT
- 可部署服务端和移动端
因此 Java 项目中,深度学习推理的标准方案就是:
PyTorch 训练 → 导出 .onnx → Java 使用 ONNX Runtime 推理
2. YoloV8推理整体流程
完整的检测流程如下:
图片字节
↓
OpenCV 解码
↓
预处理 (Resize + Letterbox + Normalize)
↓
构造 Tensor (OnnxTensor)
↓
ONNX Runtime 推理 (session.run)
↓
原始输出矩阵
↓
后处理 (Sigmoid + 阈值过滤 + NMS)
↓
映射回原图坐标
↓
DetectionResult
3. ONNX Runtime 核心组件
3.1 OrtEnvironment —— 推理引擎环境
OrtEnvironment env = OrtEnvironment.getEnvironment();
作用:
创建 ONNX Runtime 全局运行环境
理解方式: 类似 JVM 是 Java 程序的运行基础,OrtEnvironment 是 AI 推理的运行基础。
特点:
- 全局唯一
- 生命周期贯穿整个服务
- 管理线程池、算子库、内存分配
3.2 OrtSession —— 已加载的模型
OrtSession session = env.createSession(modelPath, sessionOptions);
作用:
将
.onnx模型加载到内存并构建计算图
可以理解为:
磁盘模型 → 神经网络结构 → 可执行推理图
它等价于 Python 中:
model = YOLO("model.onnx")
注意:
- Session 创建成本很高
- 必须复用
- 不允许每次请求重新加载模型
3.3 OnnxTensor —— 输入数据容器
OnnxTensor tensor = OnnxTensor.createTensor(env, FloatBuffer.wrap(pixels), shape);
作用:
将 Java 数组转换为神经网络输入张量
深度学习模型不接收图片对象,而是接收 Tensor(多维浮点矩阵)
YOLOv8 输入格式:
[batch, channel, height, width]
= [1, 3, 640, 640]
因此需要:
Mat → float[] → FloatBuffer → OnnxTensor
3.4 session.run() —— 执行推理
OrtSession.Result outputs = session.run(inputs);
作用:
真正执行神经网络计算
过程:
CPU/GPU 执行卷积网络→ 输出候选框矩阵
返回的并不是最终检测框,而是 原始预测张量
YOLOv8 输出通常为:
[1, 84, 8400] 或 [1, 8400, 84]
含义:
| 位置 | 含义 |
|---|---|
| 8400 | 候选检测框数量 |
| 4 | x,y,w,h |
| 1 | objectness |
| nc | 分类概率 |
4. 推理后的后处理
ONNX Runtime 只负责神经网络计算,不负责目标检测逻辑。 YOLO 的真正结果需要自行解析。
后处理步骤:
4.1 转置输出
模型输出是按通道排列,需要转为按候选框排列:
[C][N] → [N][C]
4.2 Sigmoid 处理
部分 ONNX 导出模型输出的是 logits,需要:
score = sigmoid(score)
4.3 置信度过滤
confidence > confThreshold
剔除低概率框,减少 NMS 计算量。
4.4 坐标转换
YOLO 输出:
xywh (中心点 + 宽高)
需要转换为:
xyxy (左上角 + 右下角)
4.5 NMS 非极大值抑制
目的:
去掉重复检测框
保留重叠度最低的一组目标。
4.6 映射回原图坐标
由于推理使用了 letterbox:
640x640 模型坐标 → 原始图片坐标
需要反变换:
(x - padding) / scale
5. 生命周期管理
初始化(应用启动)
创建 OrtEnvironment
加载 OrtSession
创建线程池
推理(每次请求)
构造 Tensor
session.run()
解析输出
关闭(服务退出)
session.close()
env.close()
6. 设计原则
- 模型只加载一次
- Session 必须复用
- 推理必须并发控制
- Tensor 使用后必须释放
- 推理必须设置超时
- 后处理必须在 Java 侧完成
7. 一句话理解
ONNX Runtime 的职责只有一个:执行神经网络计算。
| 组件 | 职责 |
|---|---|
| OrtEnvironment | AI 引擎运行环境 |
| OrtSession | 已加载的模型 |
| OnnxTensor | 输入数据 |
| session.run() | 执行推理 |
| 后处理代码 | 解析 YOLO 输出 |
这套结构本质上就是:
用 Java 实现一套不依赖 Python 的 YOLO 推理服务。
