
YOLO26 出来之后我身边不少做视觉的朋友第一反应都是“又出新版了”但真正上手跑完一两个项目之后态度基本都会变成“真香”。如果你是做边缘部署、摄像头端推理、安防人员入侵检测这类场景YOLO26 在精度和速度之间的平衡其实做得相当不错。不过模型再好不会导出也是白搭。训练完的 PyTorch 权重只是“半成品”真正要跑到 Jetson、RK3588、OpenVINO 甚至手机端必须走完模型导出这条链路。很多计算机视觉方向的同学和刚接触部署的工程师经常卡在这一步训练精度明明很好一导出到 TensorRT 或者 OpenVINO 之后要么报错要么推理结果对不上要么速度反而变慢。这篇就专门拆解 YOLO26 的模型导出全流程把 ONNX、TensorRT、OpenVINO 这几个主流格式从选型到实操一次性讲透顺便把我踩过的坑也一并列出来。1. 导出链路全景与方案选型1.1 YOLO26 权重文件里到底有什么很多初学者拿到一个yolo26n.pt或者自己训练好的best.pt第一反应就是“这玩意儿不就能直接部署了吗”其实不是。PyTorch 保存的权重不光包含网络参数还包括模型结构定义、训练状态epoch、optimizer 状态、类别名、训练配置等一堆元数据。这个文件适合继续训练、做迁移学习但不适合直接上线推理。原因有两方面。第一PyTorch 推理依赖 Python 环境和 torch 库线上服务或者边缘盒子不可能都给你配一套完整的 Python 环境更别说没有 GPU 的设备上跑 torch 的效率有多低。第二PyTorch 的动态图结构在推理时会有大量额外调度开销。做研究、调参没问题但部署场景追求的是毫秒级延迟和稳定吞吐必须把模型转换成静态图或者经过高度优化的引擎格式。所以模型导出本质上做的是两件事一是把训练好的网络结构和权重“冻结”成一个独立的推理文件二是针对目标硬件做尽可能多的图优化和算子融合。YOLO26 的导出逻辑和之前的 YOLO 系列一脉相承核心输出是多个尺度的预测头导出时需要把所有尺度统一规范化保证后续 NMS 后处理能拿到一致格式的输出。这一点在后面讲 ONNX 导出结构时我会再展开。1.2 五大主流导出格式怎么选YOLO26 的export接口支持很多格式但实际部署你会用到的其实就几种。我做了个选型表可以直接对着抄导出格式适用硬件工程推荐度说明ONNX通用中间格式必导几乎所有平台都能转是其他格式的跳板TensorRTNVIDIA GPU / Jetson强烈推荐延迟最低算子融合强但引擎绑定硬件OpenVINOIntel CPU / 集成显卡 / 部分VPU推荐CPU 场景性价比高IR 模型部署方便RKNN / NPU 专用格式瑞芯微等边缘 NPU按场景需要厂商工具链二次转换CoreMLApple 设备按场景iOS/macOS 端部署必须走它个人建议如果你不确定目标硬件第一优先导出 ONNX它是一切部署方案的“通用语言”。确定使用 NVIDIA 设备后再在 ONNX 基础上优化 TensorRT 引擎。2. 导出前环境准备2.1 YOLO26 官方权重获取与校验如果你只是想快速体验 YOLO26 的导出流程直接使用官方预训练权重是最省事的。官方权重文件命名规律一般是yolo26n.ptnano、yolo26s.ptsmall、yolo26m.ptmedium、yolo26l.ptlarge和yolo26x.ptxlarge。不同参数量的选择逻辑很明确边缘设备、实时要求高的场景选 n 或 s精度优先且硬件算力充足的场景选 m 或 l。我自己在安防人员入侵检测项目里常用的是 s 版本对比 n 精度能提升 3 到 5 个点推理速度在 Jetson Orin Nano 上依旧能跑实时。拿到权重文件后建议先做一个完整性校验不要直接拿去部署。最简单的办法是写一段脚本加载权重并跑一次推理确认类别数和输出 shape 符合预期import torch model torch.load(yolo26s.pt, map_locationcpu) # 查看类别数量和模型结构概览 print(model[model].yaml) # 常见 YOLO 权重内部格式如果发现类别数跟你项目预期不一致多半是权重文件下载不完整或者和代码库版本不匹配先解决版本问题再继续导出不然后面每一步都会连环报错。2.2 环境依赖的几个坑导出 YOLO26 模型环境依赖主要涉及三块深度学习框架、导出工具链、以及对应的运行时推理引擎。框架层面PyTorch 版本建议保持 2.0 以上torchvision 与 torch 版本需要配套。YOLO26 的训练代码和导出代码对版本是有要求的torch 太老会直接报算子不支持太新又可能跟 CUDA 版本冲突。我踩过的最典型的一个坑就是 torch 1.13 配 CUDA 11.7 导不出 TensorRT 的高版本引擎最终统一升级到 torch 2.1 才解决。工具链层面如果你的部署目标是 TensorRT就绕不开 NVIDIA 的 TensorRT 库版本建议 8.6 以上。目标平台是 CPU 场景就装 OpenVINO 工具套件如果是瑞芯微 NPU要去官方下载 RKNN-Toolkit2。另外强烈建议把onnx、onnxruntime、onnxsim这几个包一起装上并且升级到最新版。许多导出后的 ONNX 模型包含冗余节点用onnxsim做过一遍简化之后不仅体积变小后续转 TensorRT 时的成功率也会高很多。pip install onnx onnxruntime onnxsim还有一点容易被忽略不同导出格式之间是有依赖关系的。比如要导出 TensorRT 格式实际上会先自动导出 ONNX再用 TensorRT 的解析器把 ONNX 转成 engine。所以你的环境里必须同时具备onnx和 TensorRT 对应的 Python 包否则导出会在中间步骤静默失败。这类问题排查起来最头疼建议一开始就把依赖装齐。3. 实操三步完成 ONNX 与 TensorRT 导出3.1 快速导出 ONNX 模型ONNX 导出是整条链路的第一步也是最重要的一步。YOLO26 的命令行导出非常简单yolo export modelyolo26s.pt formatonnx opset12 simplifyTrue dynamicTrue这里几个参数拆开讲一下。opset是 ONNX 的算子集版本。版本太低会导致某些新算子无法表达版本太高又可能导致部分推理引擎不支持。实测下来 opset12 在兼容性和表达能力之间比较均衡如果你使用的是比较新的 TensorRT 版本也可以尝试 opset17算子支持更全。simplifyTrue会调用 onnxsim 对计算图进行简化对最终部署非常重要。dynamicTrue表示允许输入宽高动态变化导出的 ONNX 会多出几个动态维度参数。如果你确定只跑固定分辨率比如部署端摄像头推流分辨率永远被预处理成 640×640那我建议dynamicFalse对后续 TensorRT 优化更友好。导出完成后会在当前目录生成yolo26s.onnx。可以用onnxruntime做一次快速验证确认模型能推理并输出预期 shapeimport onnxruntime as ort import numpy as np sess ort.InferenceSession(yolo26s.onnx) input_name sess.get_inputs()[0].name print(sess.get_inputs()[0].shape) # 查看动态输入维度 # 构造一个随机输入跑一次推理验证不报错 dummy_input np.random.rand(1, 3, 640, 640).astype(np.float32) outputs sess.run(None, {input_name: dummy_input}) print([out.shape for out in outputs])能跑通这一步就说明你的 ONNX 计算图基本健全可以继续往下一步走。3.2 导出 TensorRT 引擎TensorRT 是 NVIDIA 平台上值得认真研究的部署格式。它会把 ONNX 的计算图做横向和纵向的算子融合比如把卷积、偏置、激活函数融合成一个算子从而显著降低推理延迟。YOLO26 导出 TensorRT 可以直接用命令行yolo export modelyolo26s.pt formatengine device0 halfTrue但这里有个坑要注意TensorRT 导出的 engine 文件跟显卡型号和 TensorRT 版本强绑定。你在 RTX 4090 上生成的 engine直接拿到 Jetson Orin 上大概率是不能用的必须重新在当前设备上从 ONNX 构建一次。所以更工程化、更可控的做法是手动写一段构建脚本不依赖 ultralytics 的封装这样你能更清楚地设置工作空间、精度、动态 shape 范围import tensorrt as trt logger trt.Logger(trt.Logger.WARNING) builder trt.Builder(logger) network builder.create_network(1 int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)) parser trt.OnnxParser(network, logger) with open(yolo26s.onnx, rb) as f: if not parser.parse(f.read()): for i in range(parser.num_errors): print(parser.get_error(i)) config builder.create_builder_config() config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 30) # 1GB 工作空间 config.set_flag(trt.BuilderFlag.FP16) # 开启半精度 # 固定尺寸维度可以直接用 1x3x640x640 input_tensor network.get_input(0) print(Input shape:, input_tensor.shape) engine builder.build_serialized_network(network, config) with open(yolo26s.engine, wb) as f: f.write(engine)这段代码做的事就是把 ONNX 文件解析成 TensorRT 的计算图然后根据当前 GPU 硬件生成优化后的 engine。WORKSPACE大小建议根据显存调整设太大容易 OOM太小则优化不充分。生成 engine 之后推理时不需要再依赖 PyTorch 或者 ultralytics只需要用 TensorRT Python API 加载 engine 并执行runtime trt.Runtime(logger) engine runtime.deserialize_cuda_engine(open(yolo26s.engine, rb).read()) context engine.create_execution_context()之后就是绑输入输出 buffer做 GPU 内存拷贝这部分代码相对固定网上模板很多核心就是“host buffer → device buffer → 推理 → device buffer → host buffer”这一套流程。3.3 OpenVINO 与边缘 NPU 导出如果你部署的目标是 Intel CPU 或者带 Intel GPU 的边缘盒子OpenVINO 是比 ONNX Runtime 更好的选择。YOLO26 导出 OpenVINO 格式同样一条命令搞定yolo export modelyolo26s.pt formatopenvino导出后生成的是一个yolo26s_openvino_model目录里面包含.xml和.bin两个文件前者是网络结构后者是权重。推理时可以用 OpenVINO 的 Python API 加载from openvino.runtime import Core core Core() model core.read_model(yolo26s_openvino_model/yolo26s.xml) compiled_model core.compile_model(model, CPU)如果你用的是瑞芯微 RK3588 这类边缘 NPU流程则会复杂一些。通常需要先导出 ONNX再用 RKNN-Toolkit2 做模型转换期间要处理量化校准集、算子兼容性等问题。这类 NPU 对量化敏感度更高后文讲到量化时我会详细说。4. 核心参数与导出细节解析4.1 动态 batch 还是静态 batch这是导出时最直观但也是最多人纠结的一个参数。动态 batch 和动态分辨率允许推理时任意指定输入的 batch 大小或图像尺寸灵活性高但代价是计算图优化空间被压缩。TensorRT 在构建 engine 时如果输入尺寸是固定的它会针对这个尺寸做非常激进的显存布局优化和算子选择一旦变成动态范围就得同时考虑多个尺寸的候选方案性能会有一定损失。我的建议非常明确生产部署一律用静态 shape。边缘摄像头推理场景输入分辨率本来就固定预处理阶段把图像 resize 到 640×640 就好。动态能力留给服务端做负载均衡时再考虑那时候吞吐更大对单帧延迟敏感度低一些。如果你确实需要动态建议把动态范围控制得窄一点比如只允许宽高在 320 到 1280 之间变化不要一上来就设成任意值。范围越窄TensorRT 优化效果越好。4.2 内置 NMS 与后处理剥离YOLO26 的原始输出结构是多个尺度的特征图每个尺度对应若干候选框和分类概率。这些原始输出不能直接用于业务逻辑必须经过 NMS非极大值抑制去掉重复框才能得到最终的检测结果。导出时你面临一个选择把 NMS 一起打包进模型还是在模型外部自己做后处理。如果选择内置 NMS也就是在导出 ONNX 时开启nmsTrue好处是部署端代码简单输入图像直接出来就是最终检测框。坏处是灵活性差NMS 的阈值和类别逻辑被冻结在模型里而且 TensorRT 上运行内置 NMS 节点效率并不一定高某些版本还存在算子兼容性问题。我自己做安防人员入侵检测项目时建议走“剥离 NMS”路线导出纯检测头自己写后处理。纯检测头的输出是一个固定 shape 的张量在 YOLO26 上通常形如[1, 8400, 4 num_classes]其中 8400 是当前图像分辨率下所有尺度的候选框总数。业务逻辑里你完全可以用自己熟悉的 NMS 实现来处理后续如果要改成跟踪算法、行为识别、单相机测距输出距离都会方便很多。单相机测距这个需求刚好做个例子。剥离 NMS 之后你在后处理阶段能拿到每个检测框的精确坐标和置信度结合相机的内参矩阵可以直接在同一个流程里做距离估算如果 NMS 被内置在模型里输出就已经丢失了很多原始信息再想接测距逻辑就得改模型成本翻倍。4.3 精度保持与量化技巧导出对单精度模型来说精度损失几乎可以忽略但一旦涉足半精度和 INT8 量化精度问题就必须要正视了。FP16 半精度导出对大多数 GPU 平台都是安全的YOLO26 的 s 和 n 版本在 FP16 下精度损失通常在 0.5 个点以内。TensorRT 导出时加halfTrue就能开启 FP16。真正需要小心的是 INT8 量化。边缘 NPU比如 RK3588、Intel 的某些 VPU往往只支持 INT8 推理。把 FP16 模型强转 INT8如果校准集选得不好精度可能直接掉 10 个点以上。我踩过的坑是用一二百张正常光照的图片做校准结果在夜间低照度监控场景下漏检率肉眼可见地上升。后来重新整理校准集把正常光照、夜间红外、雨天模糊、逆光这几类场景各抽一部分数量控制在 300 到 500 张精度损失才压回到 2 个点以内。校准集只需要图片不需要标注。因为量化的过程是统计每一层激活值的分布范围然后选择合适的映射方式把浮点数值映射到 INT8。所以校准集应该尽量贴近真实使用场景的输入分布而不是图多就完事。5. 常见问题与部署排查实录5.1 导出报错速查表这一段我直接整理成表格方便你们遇到问题的时候快速对照。典型报错常见原因解决办法Unsupported ONNX operatorONNX opset 版本过低提高 opset 到 12 或 17 再导出Parser error while parsing ONNXONNX 图存在冗余节点用 onnxsim 简化后再导入Out of memory during engine build工作空间或动态 shape 设置过大调小 WORKSPACE 或改为静态 shapeEngine deserialization failedengine 与当前 GPU 型号不匹配在目标设备上重新构建 engineOutput shape mismatch输入尺寸设置与预处理不一致检查 resize 和 padding 逻辑统一输入分辨率精度掉到不可用量化校准集分布不合理扩充多样化的校准集重新量化推理速度反而变慢动态 shape 或未开启 FP16固定输入尺寸开启半精度模型输出全是 0后处理未对齐输出格式检查检测头的输出通道数和排列顺序这里面最阴间的其实是“engine 在 A 机器上好好的拷到 B 机器上报错”。TensorRT 的 engine 文件不是跨平台通用的这个点一定要在团队内部强调清楚。正确做法是只分发 ONNX 文件在各目标设备上分别执行 engine 构建或者提前把构建好的 engine 与设备型号、TensorRT 版本做绑定命名。5.2 端到端推理性能调优实测最后分享一组实测数据。项目场景是 yolov26s 做办公室区域的人员入侵检测输入分辨率 640×640数据跑在同一张 RTX 3060 显卡上部署方式单帧延迟毫秒备注PyTorch 直接推理22.5包含后处理前但未优化ONNX Runtime CPU48.3仅作参考CPU 场景TensorRT FP16 静态 shape4.8剥离 NMS后处理单独写TensorRT FP16 内置 NMS6.1内置 NMS 节点耗时偏高OpenVINO CPU FP1618.2Intel i5-1240P效果可接受从这个结果能看出几个关键结论一是 TensorRT 相对 PyTorch 有接近 5 倍的收益二是剥离 NMS 之后反而比内置 NMS 快了不少三是 OpenVINO 在 CPU 上的表现已经很够用了不是所有场景都强行上 GPU。推理性能调优还有几个细节值得提。TensorRT 引擎构建时设workspace大的构建过程时间长但推理速度可能更好显存紧张的设备可以开cudaGraph来降低单帧调度延迟。预处理图像用 CUDA 上的 resize 和 normalize不要用 CPU 做完图再拷到 GPU这个数据传输在帧率要求高的场景会成为瓶颈。模型导出不是一锤子买卖你可能会在同一套代码里反复调整格式、精度和动态范围。每改一次都要重新走一遍“导出—验证—基准测试”的循环建议在工程里把这三个阶段写成脚本固化下来省得每次手工操作。最后分享一个我的个人习惯所有导出后的模型文件中ONNX 文件是唯一保留的“中间产物”它既是 TensorRT 和 OpenVINO 的输入也是后续做模型量化和算子替换的源文件。无论部署格式怎么变、目标平台怎么换只要保留好原始的 ONNX整个部署链路随时可以重来。在实际项目里我导出遇到最多的其实不是技术难题而是流程习惯问题——很多人训练完模型直接丢给部署工程师中间没有经过严格的导出验证和基准测试。你只要把导出当作一个独立环节来对待加上一份清晰的验证清单YOLO26 的模型部署会顺利很多。