news 2026/3/12 7:52:14

如何用cv_resnet18_ocr-detection导出ONNX模型?实操手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用cv_resnet18_ocr-detection导出ONNX模型?实操手册

如何用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 实际封装了上述逻辑,但做了用户友好封装:

  1. 输入尺寸设置:高度/宽度滑块 → 实际修改dummy_input的 H/W 值
  2. 点击“导出 ONNX”→ 后台执行类似export_onnx.py的脚本
  3. 状态提示→ 实时捕获print()和异常信息
  4. 下载按钮→ 通过 Flask 的send_file()提供 HTTP 下载

优势:零代码、可视化、防误操作
注意:WebUI 导出默认固定尺寸(800×800),如需其他尺寸(如 640×640),仍需手动改脚本

4.2 尺寸选择实战建议

尺寸适用场景检测效果推理耗时(RTX 3090)
640×640移动端/低功耗设备、实时视频流小字易漏检,大字稳定~15 ms
800×800Web 服务/通用部署(推荐)平衡精度与速度,中文字体友好~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 supportedPyTorch 算子未注册到 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星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/12 0:31:06

企业级低代码开发平台:创新开发范式探索指南

企业级低代码开发平台:创新开发范式探索指南 【免费下载链接】jeecg-boot jeecgboot/jeecg-boot 是一个基于 Spring Boot 的 Java 框架,用于快速开发企业级应用。适合在 Java 应用开发中使用,提高开发效率和代码质量。特点是提供了丰富的组件…

作者头像 李华
网站建设 2026/3/10 5:14:07

FancyZones窗口管理大师:重塑多显示器工作流

FancyZones窗口管理大师:重塑多显示器工作流 【免费下载链接】PowerToys Windows 系统实用工具,用于最大化生产力。 项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys 核心价值与适用人群 在信息爆炸的数字时代,屏幕空间…

作者头像 李华
网站建设 2026/3/8 22:15:34

reboot后没生效?测试开机启动脚本常见问题解答

reboot后没生效?测试开机启动脚本常见问题解答 你写好了启动脚本,加了软链接,也执行了reboot,但系统起来后——脚本压根没跑。日志里找不到痕迹,进程列表里没有,连临时文件都没生成。这不是个例&#xff0…

作者头像 李华
网站建设 2026/3/8 22:16:03

YOLOv9实战体验:预装环境让模型训练不再难

YOLOv9实战体验:预装环境让模型训练不再难 你有没有经历过这样的深夜: 对着报错信息反复刷新页面,conda install 卡在 solving environment,CUDA 版本和 PyTorch 死活对不上,ModuleNotFoundError: No module named to…

作者头像 李华
网站建设 2026/3/11 1:39:36

如何让笔记本安静又凉爽?智能散热工具全攻略

如何让笔记本安静又凉爽?智能散热工具全攻略 【免费下载链接】nbfc NoteBook FanControl 项目地址: https://gitcode.com/gh_mirrors/nb/nbfc 笔记本过热解决方案:当你正在专注工作时,笔记本突然发出"直升机"般的噪音&#…

作者头像 李华
网站建设 2026/3/9 6:47:57

FSMN VAD音乐过滤能力:区分歌声与说话场景测试

FSMN VAD音乐过滤能力:区分歌声与说话场景测试 1. 为什么需要“听懂”歌声和人声的区别? 你有没有遇到过这样的问题: 想从一段带背景音乐的播客里,只提取主持人说话的部分,结果模型把副歌也当成了“语音”&#xff1…

作者头像 李华