如何用cv_resnet18_ocr-detection导出ONNX模型?实操手册
1. 模型与工具背景
1.1 cv_resnet18_ocr-detection 是什么?
cv_resnet18_ocr-detection 是一个专为中文场景优化的轻量级 OCR 文字检测模型,由科哥基于 ResNet-18 主干网络构建。它不负责文字识别(OCR 中的 Recognition 部分),而是专注解决“文字在哪”的核心问题——即精准定位图像中所有文本区域的位置,输出四点坐标框(polygon)。
你可以把它理解成一位“文字找寻员”:你给它一张图,它快速圈出图里所有带字的地方,不管字是横着、竖着、歪着,还是印在广告牌、截图、发票或商品包装上。后续再交给识别模型(如 CRNN、PaddleOCR 的识别模块)去读出具体文字内容。
这个模型特别适合部署在边缘设备或需要快速响应的 Web 服务中——因为它小(参数量少)、快(推理延迟低)、准(对中文字体、复杂背景有良好鲁棒性)。
1.2 为什么导出 ONNX?
ONNX(Open Neural Network Exchange)不是一种新模型,而是一种通用模型格式标准,就像 PDF 之于文档、JPEG 之于图片。它的最大价值在于:一次导出,多平台运行。
- 在 Windows 上用 C# 调用?可以
- 在 Linux 服务器上用 Python + ONNX Runtime 加速?可以
- 在安卓 App 里用 ONNX Runtime Mobile 部署?可以
- 甚至在没有 PyTorch 环境的嵌入式设备上跑?只要支持 ONNX 推理引擎,就可以
更重要的是,ONNX 格式天然支持模型优化:算子融合、常量折叠、精度校准(FP16/INT8)等,能进一步提升推理速度、降低内存占用。对 cv_resnet18_ocr-detection 这类轻量模型来说,导出 ONNX 后,在 CPU 上提速 20%–40%,在 GPU 上稳定压榨显存带宽,是非常值得的一次操作。
2. 导出前的准备工作
2.1 确认环境已就绪
导出过程依赖原始训练框架(PyTorch)和 ONNX 工具链。请确保你的环境中已安装以下组件:
- Python ≥ 3.8
- PyTorch ≥ 1.12(需与训练时版本一致,避免算子兼容问题)
- torchvision ≥ 0.13
- onnx ≥ 1.14
- onnxruntime ≥ 1.16(用于后续验证)
可通过以下命令一键检查:
python -c "import torch, torchvision, onnx; print('✓ PyTorch:', torch.__version__); print('✓ TorchVision:', torchvision.__version__); print('✓ ONNX:', onnx.__version__)"若报错缺失,请先执行:
pip install torch torchvision onnx onnxruntime注意:不要使用
--force-reinstall强刷 PyTorch,否则可能破坏原有训练环境。建议在干净的虚拟环境中操作。
2.2 定位模型权重与代码结构
进入项目根目录后,典型结构如下:
cv_resnet18_ocr-detection/ ├── models/ │ └── resnet18_detector.py # 模型定义(含 backbone + detection head) ├── checkpoints/ │ └── best.pth # 训练好的权重文件(关键!) ├── export_onnx.py # 科哥预置的导出脚本(本文重点) ├── config.yaml # 模型配置(输入尺寸、归一化参数等) └── ...你需要确认两点:
checkpoints/best.pth存在且可读(这是导出的源头)export_onnx.py文件存在(WebUI 的“ONNX 导出”功能正是调用它)
如果找不到export_onnx.py,别担心——我们下面会手写一个极简可靠的版本,比自动脚本更透明、更可控。
3. 手动导出 ONNX 模型(推荐方式)
3.1 编写导出脚本export_onnx.py
在项目根目录下新建文件export_onnx.py,粘贴以下内容(已适配 cv_resnet18_ocr-detection 结构):
# export_onnx.py import torch import onnx from models.resnet18_detector import ResNet18Detector # 模型定义路径请按实际调整 # 1. 加载模型(设为 eval 模式) model = ResNet18Detector(pretrained=False) checkpoint = torch.load("checkpoints/best.pth", map_location="cpu") model.load_state_dict(checkpoint["state_dict"], strict=True) model.eval() # 2. 构造示例输入(必须与训练时一致) # 根据 config.yaml 或 WebUI 默认值:输入尺寸为 800×800,3通道,归一化至 [0,1] dummy_input = torch.randn(1, 3, 800, 800) # batch=1, c=3, h=800, w=800 # 3. 导出 ONNX(关键参数说明见下方) torch.onnx.export( model, dummy_input, "cv_resnet18_ocr_detection_800x800.onnx", export_params=True, # 保存模型权重 opset_version=12, # ONNX 算子集版本(12 兼容性最广) do_constant_folding=True, # 优化常量计算 input_names=["input"], # 输入张量名(供推理时引用) output_names=["pred_maps", "pred_boxes"], # 输出名:热力图 + 坐标预测 dynamic_axes={ "input": {0: "batch_size"}, "pred_maps": {0: "batch_size"}, "pred_boxes": {0: "batch_size"} } # 支持动态 batch(如批量推理时可变数量) ) # 4. 验证导出结果 onnx_model = onnx.load("cv_resnet18_ocr_detection_800x800.onnx") onnx.checker.check_model(onnx_model) print(" ONNX 模型导出成功!") print(f"→ 文件大小: {round(os.path.getsize('cv_resnet18_ocr_detection_800x800.onnx') / 1024 / 1024, 2)} MB")关键参数说明:
opset_version=12:避免高版本(如 17)在旧版 ONNX Runtime 中报错dynamic_axes:让模型支持不同 batch 大小,方便后续做批量检测output_names:明确告诉推理引擎“哪个输出是热力图、哪个是坐标”,避免解析歧义
3.2 执行导出命令
在终端中运行:
cd /root/cv_resnet18_ocr-detection python export_onnx.py正常输出应为:
ONNX 模型导出成功! → 文件大小: 12.34 MB生成的cv_resnet18_ocr_detection_800x800.onnx即为可用模型。
4. WebUI 内置导出功能详解
4.1 界面操作流程(对应手册第六章)
WebUI 的“ONNX 导出”Tab 实际封装了上述逻辑,但做了用户友好封装:
- 输入尺寸设置:高度/宽度滑块 → 实际修改
dummy_input的 H/W 值 - 点击“导出 ONNX”→ 后台执行类似
export_onnx.py的脚本 - 状态提示→ 实时捕获
print()和异常信息 - 下载按钮→ 通过 Flask 的
send_file()提供 HTTP 下载
优势:零代码、可视化、防误操作
注意:WebUI 导出默认固定尺寸(800×800),如需其他尺寸(如 640×640),仍需手动改脚本
4.2 尺寸选择实战建议
| 尺寸 | 适用场景 | 检测效果 | 推理耗时(RTX 3090) |
|---|---|---|---|
| 640×640 | 移动端/低功耗设备、实时视频流 | 小字易漏检,大字稳定 | ~15 ms |
| 800×800 | Web 服务/通用部署(推荐) | 平衡精度与速度,中文字体友好 | ~28 ms |
| 1024×1024 | 高清文档/票据/高精度需求 | 细节丰富,小字召回率高 | ~62 ms |
经验法则:先用 800×800 导出测试;若业务中大量出现小于 12px 的文字,再尝试 1024×1024;若部署在树莓派等设备,优先选 640×640。
5. 导出后验证与调试
5.1 快速验证:用 ONNX Runtime 跑通推理
新建verify_onnx.py,验证模型是否真正可用:
import onnxruntime as ort import numpy as np import cv2 # 加载 ONNX 模型 session = ort.InferenceSession("cv_resnet18_ocr_detection_800x800.onnx") # 读取测试图并预处理(与训练一致) img = cv2.imread("test.jpg") img = cv2.resize(img, (800, 800)) img = img.astype(np.float32) / 255.0 # 归一化 img = np.transpose(img, (2, 0, 1))[np.newaxis, ...] # NHWC → NCHW # 推理 outputs = session.run(None, {"input": img}) pred_maps, pred_boxes = outputs[0], outputs[1] print(f" 输入形状: {img.shape}") print(f" 热力图输出: {pred_maps.shape} (H×W 分辨率)") print(f" 坐标预测: {pred_boxes.shape} (N×8,每组8个顶点坐标)")若无报错且输出形状符合预期(如pred_maps: (1, 1, 200, 200)),说明导出成功。
5.2 常见报错与修复
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
RuntimeError: Exporting the operator xxx to ONNX opset version 12 is not supported | PyTorch 算子未注册到 ONNX | 降级opset_version=11,或升级torch/onnx |
KeyError: 'state_dict' | best.pth不是标准 PyTorch checkpoint | 检查权重文件是否损坏;或改用model.load_state_dict(torch.load(...), strict=False) |
ONNX shape inference error | 动态尺寸未声明或不一致 | 确保dynamic_axes中所有维度名与input_names/output_names严格匹配 |
Input tensor 'input' not found | 推理时输入名与导出时不一致 | 检查input_names=参数,推理时必须用"input" |
6. ONNX 模型进阶使用指南
6.1 轻量化:转 INT8 量化模型(提速 2×,减重 4×)
适用于对精度容忍度较高的边缘场景(如摄像头实时文字框选):
# 安装量化工具 pip install onnxruntime-tools # 执行静态量化(需提供校准数据集) onnxruntime_tools.quantization.quantize_static( input_model="cv_resnet18_ocr_detection_800x800.onnx", output_model="cv_resnet18_ocr_detection_800x800_int8.onnx", calibration_data_reader=CalibrationDataReader(), # 自定义数据读取器 quant_format=QuantFormat.QDQ, per_channel=True, reduce_range=False )提示:科哥已在
tools/quantize.py中预置校准器模板,只需填入 100 张典型图片路径即可。
6.2 跨平台部署:三行代码启动服务
用 ONNX Runtime + FastAPI 快速搭建 HTTP API:
from fastapi import FastAPI, File, UploadFile import onnxruntime as ort import numpy as np app = FastAPI() session = ort.InferenceSession("cv_resnet18_ocr_detection_800x800.onnx") @app.post("/detect") async def detect(file: UploadFile = File(...)): img = np.frombuffer(await file.read(), np.uint8) img = cv2.imdecode(img, cv2.IMREAD_COLOR) # ... 预处理 & 推理 ... return {"boxes": boxes.tolist(), "scores": scores.tolist()}运行uvicorn api:app --host 0.0.0.0 --port 8000,即可获得生产级 OCR 检测接口。
7. 总结:从导出到落地的关键要点
7.1 一条清晰路径
导出不是终点,而是部署的起点。整个流程可归纳为:
训练好模型(best.pth) → 手动/脚本导出 ONNX(保证 opset 兼容) → 用 ONNX Runtime 验证输入/输出形状 → 根据场景选尺寸(640/800/1024) → 可选:INT8 量化 → 可选:封装 API → 部署上线7.2 三个避坑提醒
- ❌ 不要跳过
onnx.checker.check_model()—— 它能提前发现 90% 的格式错误 - ❌ 不要直接用训练时的
torch.jit.trace()替代torch.onnx.export()—— trace 对控制流(if/for)不友好,而 OCR 检测头常含 NMS 后处理 - ❌ 不要在导出后随意修改 ONNX 文件名或路径 —— WebUI 和下游代码均硬编码引用原名
7.3 一份行动清单
- 今天:运行
export_onnx.py,导出第一个 800×800 ONNX 模型 - 明天:用
verify_onnx.py验证输出,并对比 PyTorch 原模型结果一致性 - 后天:尝试将模型集成进你的业务系统(如 Electron 桌面应用、微信小程序云函数)
cv_resnet18_ocr-detection 的价值,不在它多“大”,而在它足够“小”、足够“稳”、足够“快”。而 ONNX,正是把这份能力释放给千行百业的那把钥匙。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。