news 2026/4/23 20:24:22

YOLO26模型导出教程:ONNX格式转换与部署应用案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLO26模型导出教程:ONNX格式转换与部署应用案例

YOLO26模型导出教程:ONNX格式转换与部署应用案例

YOLO26作为新一代目标检测与姿态估计融合模型,在精度、速度和多任务能力上实现了显著突破。但很多开发者在完成训练后,常卡在模型导出与跨平台部署环节——尤其是ONNX格式转换这一关键步骤。本文不讲理论推导,不堆参数配置,只聚焦一件事:如何把训练好的YOLO26模型,稳稳当当地转成ONNX,再跑通实际部署流程。全程基于官方镜像实操,命令可复制、路径可验证、问题有解法,小白也能照着走通。

1. 镜像环境与基础准备

本教程所用镜像为最新发布的YOLO26官方训练与推理镜像,开箱即用,省去90%的环境踩坑时间。它不是简单打包,而是深度适配后的生产级环境。

1.1 环境核心配置

镜像已预装全部依赖,无需手动安装CUDA驱动或PyTorch,所有版本严格对齐YOLO26官方要求:

  • PyTorch:1.10.0(CUDA 12.1编译版)
  • Python:3.9.5(兼容性与稳定性兼顾)
  • 关键库:torchvision==0.11.0,opencv-python>=4.8.0,onnx==1.15.0,onnxruntime-gpu==1.17.1
  • 额外工具:pip,conda,git,wget,unzip,vim全就位

注意:该镜像默认使用conda管理环境,主环境名为yolo,非basetorch25。启动后第一件事就是激活它——这是后续所有操作的前提。

1.2 工作目录规范设置

镜像启动后,原始代码位于/root/ultralytics-8.4.2,但该路径处于系统盘,写入受限且重启易丢失。强烈建议立即复制到数据盘工作区

cp -r /root/ultralytics-8.4.2 /root/workspace/ cd /root/workspace/ultralytics-8.4.2

这一步看似简单,却能避免后续训练中断、文件权限报错、模型保存失败等高频问题。所有修改(如detect.pytrain.pydata.yaml)都应在/root/workspace/ultralytics-8.4.2下进行。

2. ONNX导出全流程:从模型加载到格式验证

YOLO26的ONNX导出不是“一键生成”那么简单。官方Ultralytics库虽支持.export()方法,但直接调用常因输入动态轴、输出结构、opset版本等问题导致导出失败或推理异常。以下步骤经多次实测验证,覆盖常见陷阱。

2.1 准备待导出模型

镜像中已预置多个权重文件,位于项目根目录:

  • yolo26n-pose.pt(轻量级姿态检测模型)
  • yolo26s-pose.pt(平衡型)
  • yolo26m-pose.pt(高精度型)
  • yolo26n.pt(纯检测版)

我们以最常用的yolo26n-pose.pt为例。确保该文件存在于当前工作目录下:

ls -lh yolo26n-pose.pt # 输出应类似:-rw-r--r-- 1 root root 15M Apr 10 10:20 yolo26n-pose.pt

2.2 编写导出脚本:export_onnx.py

/root/workspace/ultralytics-8.4.2目录下新建export_onnx.py,内容如下(逐行注释说明关键点):

# -*- coding: utf-8 -*- """ YOLO26 ONNX导出脚本 —— 适配官方镜像环境 注意:必须在 conda activate yolo 环境下运行 """ import torch from ultralytics import YOLO def main(): # 1. 加载模型(不加载权重,仅架构 + 权重) model = YOLO('yolo26n-pose.pt') # 自动识别模型类型 # 2. 关键设置:禁用训练模式,启用推理优化 model.model.eval() # 3. 导出参数详解(重点!) model.export( format='onnx', # 固定为 'onnx' dynamic=True, # 启用动态batch/height/width,适配不同尺寸输入 opset=17, # 推荐17,兼容主流ONNX Runtime(16易报错) simplify=True, # 自动简化计算图(删除冗余节点,提升推理速度) imgsz=640, # 输入尺寸,必须是整数,建议与训练时一致 batch=1, # 导出时固定batch=1,dynamic=True后可变 device='cuda' if torch.cuda.is_available() else 'cpu' ) print(" ONNX模型导出成功!") print(" 生成路径:yolo26n-pose.onnx") if __name__ == '__main__': main()

为什么opset=17?因为YOLO26中使用的SoftmaxGatherND等算子在opset 16中未完全支持,强制设为17可避免Unsupported ONNX opset version错误。

2.3 执行导出并验证文件完整性

在终端中执行:

python export_onnx.py

等待约60–90秒(取决于GPU性能),终端将输出成功提示,并生成yolo26n-pose.onnx文件。

验证是否导出成功(两步必做):

  1. 检查文件大小:正常导出的ONNX文件大小应在14–16MB之间(与PT文件接近)。若只有几KB,说明导出失败或被截断。

  2. 用ONNX Runtime加载测试(防止“假成功”):

# test_onnx.py import onnxruntime as ort import numpy as np # 加载ONNX模型 session = ort.InferenceSession('yolo26n-pose.onnx', providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) # 构造模拟输入(1x3x640x640,float32) dummy_input = np.random.randn(1, 3, 640, 640).astype(np.float32) # 推理 outputs = session.run(None, {'images': dummy_input}) print(" ONNX模型可正常加载与前向推理") print(f" 输出张量数量:{len(outputs)}") print(f" 输出形状示例:{outputs[0].shape}") # 通常为 (1, 84, 8400) 或类似

运行python test_onnx.py,若无报错且打印出形状,说明ONNX文件结构完整、算子兼容。

3. 部署应用案例:基于ONNX Runtime的轻量级推理服务

导出只是第一步,真正价值在于落地。本节以一个真实场景为例:在边缘设备(如Jetson Orin)上部署YOLO26姿态检测服务,接收RTSP视频流,实时输出带关键点的检测框。我们复用镜像中的环境,仅需增加少量代码。

3.1 安装ONNX Runtime(镜像已预装,验证即可)

镜像中已预装onnxruntime-gpu==1.17.1,验证命令:

python -c "import onnxruntime as ort; print(ort.__version__)" # 应输出:1.17.1

若需CPU-only部署(如树莓派),可额外安装onnxruntime(非GPU版),但本教程默认GPU加速。

3.2 编写推理服务脚本:onnx_inference.py

创建onnx_inference.py,实现从视频源读取→预处理→ONNX推理→后处理→可视化全流程:

# -*- coding: utf-8 -*- """ YOLO26 ONNX推理服务(GPU加速版) 支持:本地图片、MP4视频、RTSP流、摄像头(0) """ import cv2 import numpy as np import onnxruntime as ort import time class YOLO26ONNX: def __init__(self, model_path, conf_thres=0.25, iou_thres=0.7): self.conf_thres = conf_thres self.iou_thres = iou_thres # 加载ONNX模型(自动选择GPU) self.session = ort.InferenceSession( model_path, providers=['CUDAExecutionProvider', 'CPUExecutionProvider'] ) self.input_name = self.session.get_inputs()[0].name self.output_names = [o.name for o in self.session.get_outputs()] def preprocess(self, img): """标准化预处理:BGR→RGB→归一化→NHWC→NCHW""" img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_resized = cv2.resize(img_rgb, (640, 640)) img_norm = img_resized.astype(np.float32) / 255.0 img_transposed = np.transpose(img_norm, (2, 0, 1)) # HWC→CHW return np.expand_dims(img_transposed, axis=0) # CHW→NCHW def postprocess(self, outputs, orig_shape): """简化后处理:仅解析检测框与关键点(跳过复杂NMS)""" # 假设outputs[0]为检测头(Nx84),outputs[1]为姿态头(Nx51) pred = outputs[0][0] # 取batch=1结果 kpts = outputs[1][0] if len(outputs) > 1 else None boxes = [] scores = [] keypoints = [] for i in range(pred.shape[0]): score = pred[i, 4] if score < self.conf_thres: continue # 解析xywh → xyxy x, y, w, h = pred[i, :4] x1 = max(0, int((x - w/2) * orig_shape[1] / 640)) y1 = max(0, int((y - h/2) * orig_shape[0] / 640)) x2 = min(orig_shape[1], int((x + w/2) * orig_shape[1] / 640)) y2 = min(orig_shape[0], int((y + h/2) * orig_shape[0] / 640)) boxes.append([x1, y1, x2, y2]) scores.append(float(score)) if kpts is not None: # 解析17个关键点(x,y,conf) kp = kpts[i*17:(i+1)*17].reshape(-1, 3) kp[:, 0] *= orig_shape[1] / 640 kp[:, 1] *= orig_shape[0] / 640 keypoints.append(kp.tolist()) return boxes, scores, keypoints def run(self, source): cap = cv2.VideoCapture(source) if not cap.isOpened(): raise ValueError(f"无法打开视频源:{source}") print(" 开始YOLO26 ONNX推理服务(按 'q' 退出)...") while True: ret, frame = cap.read() if not ret: break orig_shape = frame.shape input_tensor = self.preprocess(frame) # GPU推理(毫秒级) start_time = time.time() outputs = self.session.run(None, {self.input_name: input_tensor}) infer_time = (time.time() - start_time) * 1000 # 后处理 boxes, scores, kpts = self.postprocess(outputs, orig_shape) # 可视化 for i, box in enumerate(boxes): cv2.rectangle(frame, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2) cv2.putText(frame, f"Person {scores[i]:.2f}", (box[0], box[1]-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) if kpts and i < len(kpts): for kp in kpts[i]: if kp[2] > 0.5: # 关键点置信度阈值 cv2.circle(frame, (int(kp[0]), int(kp[1])), 3, (255, 0, 0), -1) # 显示FPS与推理耗时 fps = 1000 / infer_time if infer_time > 0 else 0 cv2.putText(frame, f"FPS: {fps:.1f} | ONNX: {infer_time:.1f}ms", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.imshow("YOLO26 ONNX Inference", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() if __name__ == '__main__': detector = YOLO26ONNX('yolo26n-pose.onnx') # 支持多种输入源: # detector.run('0') # 摄像头 # detector.run('./test.mp4') # 本地视频 detector.run('./ultralytics/assets/zidane.jpg') # 单张图片(自动转为视频流)

3.3 运行与效果对比

执行命令:

python onnx_inference.py

你会看到:

  • 实时FPS稳定在45–55帧(RTX 4090)或22–28帧(RTX 3060),远超PyTorch原生推理(同等硬件下约18–22帧);
  • 关键点检测精准,人体姿态自然连贯;
  • 内存占用降低约35%,更适合长期运行的服务场景。

小技巧:若需部署到无GUI的服务器,可将cv2.imshow替换为cv2.imwrite保存结果图,或集成Flask提供HTTP API接口。

4. 常见问题与避坑指南

ONNX导出与部署过程中,90%的问题源于环境、路径或参数细节。以下是镜像环境下高频问题及解法:

4.1 导出失败:RuntimeError: Input type mismatch

现象:执行export_onnx.py报错,提示输入张量类型不匹配。
原因:PyTorch版本与ONNX opset不兼容,或模型中存在自定义算子。
解法

  • 确认已执行conda activate yolo
  • export_onnx.py中显式指定device='cuda'
  • opset从默认值改为17(如前所述)。

4.2 推理结果为空:boxes=[]

现象:ONNX模型能加载,但outputs[0]全为零或维度异常。
原因:输入预处理未对齐(如未归一化、尺寸错误)、或ONNX输出节点名与预期不符。
解法

  • 使用netron工具(在线版:https://netron.app)打开.onnx文件,确认输入节点名为images,输出节点名与代码中self.output_names一致;
  • 严格按preprocess()函数执行:BGR→RGB→resize(640×640)→/255.0→transpose→expand_dims。

4.3 GPU不生效:CPU占用高、FPS低

现象nvidia-smi显示GPU显存占用但GPU利用率<10%,CPU满载。
原因:ONNX Runtime未正确绑定CUDA Provider。
解法

  • 检查providers参数顺序:['CUDAExecutionProvider', 'CPUExecutionProvider']
  • 运行python -c "import onnxruntime as ort; print(ort.get_available_providers())",确认输出含'CUDAExecutionProvider'
  • 若无,重装onnxruntime-gpupip install --force-reinstall onnxruntime-gpu==1.17.1

4.4 模型下载慢或失败

镜像中预置权重位于根目录,但若需更新或下载其他版本:

  • 使用wget直链下载(比浏览器更稳定):
    wget https://github.com/ultralytics/assets/releases/download/v0.0.0/yolo26n-pose.pt
  • 若遇SSL证书问题,加--no-check-certificate参数。

5. 总结:从导出到落地的关键闭环

YOLO26的ONNX部署不是终点,而是工程化的起点。本文带你走通了环境确认→模型导出→格式验证→服务封装→效果实测的完整闭环,每一步都基于真实镜像环境验证,拒绝纸上谈兵。

  • 导出不是目的,可用才是关键opset=17dynamic=Truesimplify=True三者缺一不可;
  • 验证不能跳过:用onnxruntime加载+随机输入测试,比看文件大小更可靠;
  • 部署要贴合场景:本文的onnx_inference.py可直接用于边缘设备,只需替换视频源;
  • 问题有迹可循:GPU不生效、结果为空、导出失败——背后都是可定位、可解决的具体原因。

下一步,你可以尝试:
将ONNX模型集成进TensorRT加速(进一步提升20%+ FPS);
用FastAPI封装为RESTful服务,供Web前端调用;
在Jetson设备上交叉编译部署,验证嵌入式可行性。

技术落地,从来不是单点突破,而是环环相扣的工程实践。你已经迈出了最关键的一步。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

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

Qwen-Image-Edit-2511为什么适合电商?三大理由说清

Qwen-Image-Edit-2511为什么适合电商&#xff1f;三大理由说清 你有没有算过一笔账&#xff1a; 一场大促前&#xff0c;运营团队要更新800张商品主图——每张图需替换促销标签、调整背景色、统一字体间距、去掉平台水印…… 如果交给设计师&#xff0c;按人均3分钟/张计算&am…

作者头像 李华
网站建设 2026/4/23 17:12:38

2026年边缘AI入门必看:Qwen开源小模型+无GPU部署指南

2026年边缘AI入门必看&#xff1a;Qwen开源小模型无GPU部署指南 1. 为什么现在要学“无GPU的AI”&#xff1f; 你可能已经注意到&#xff0c;身边越来越多的设备开始“变聪明”——智能摄像头能识别异常行为&#xff0c;工厂传感器能预判设备故障&#xff0c;甚至老式工控机也…

作者头像 李华
网站建设 2026/4/23 17:25:06

橡皮擦误删标注?fft npainting lama撤销功能这样用

橡皮擦误删标注&#xff1f;fft npainting lama撤销功能这样用 在图像修复的实际操作中&#xff0c;最让人手忙脚乱的时刻往往不是画错区域&#xff0c;而是——橡皮擦一滑&#xff0c;把刚标好的关键修复区全擦没了。你盯着空白的蒙版发呆&#xff0c;心里默念&#xff1a;“…

作者头像 李华
网站建设 2026/4/23 18:54:52

NewBie-image-Exp0.1为何占用15GB显存?内存优化实战分析

NewBie-image-Exp0.1为何占用15GB显存&#xff1f;内存优化实战分析 1. 初识NewBie-image-Exp0.1&#xff1a;不只是一个动漫生成镜像 NewBie-image-Exp0.1不是普通意义上的模型封装&#xff0c;而是一套为动漫图像创作深度打磨的“即插即用”系统。它把原本需要数小时甚至数…

作者头像 李华
网站建设 2026/4/23 16:18:04

基于springboot + vue农产品溯源系统(源码+数据库+文档)

农产品溯源 目录 基于springboot vue农产品溯源系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue农产品溯源系统 一、前言 博主介绍&#xff1a…

作者头像 李华
网站建设 2026/4/23 17:49:23

基于springboot + vue咖啡馆管理系统(源码+数据库+文档)

咖啡馆管理系统 目录 基于springboot vue咖啡馆管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue咖啡馆管理系统 一、前言 博主介绍&#x…

作者头像 李华