
YOLOv10模型导出实战将训练好的模型转换为ONNX和TensorRT格式当你花费大量时间训练出一个性能优异的YOLOv10模型后下一步面临的关键挑战就是如何将它部署到实际的生产环境中。无论是边缘设备、服务器还是云端推理平台模型导出都是连接训练与部署的关键桥梁。然而许多开发者在模型导出过程中会遇到各种问题格式不兼容、性能损失、后处理复杂等。YOLOv10作为首个无需NMS后处理的端到端目标检测模型在导出和部署方面带来了革命性的简化。本文将手把手教你如何将训练好的YOLOv10模型高效地转换为ONNX和TensorRT格式让你能够快速将模型部署到各种硬件平台享受端到端推理带来的性能优势。1. 环境准备与模型检查1.1 确认训练完成的模型在开始导出之前首先确保你已经有一个训练完成的YOLOv10模型。通常训练完成后最佳模型权重会保存在以下路径runs/detect/train/weights/best.pt你可以使用简单的预测命令验证模型是否正常工作# 激活YOLOv10环境 conda activate yolov10 cd /root/yolov10 # 测试模型预测功能 yolo predict modelruns/detect/train/weights/best.pt sourceultralytics/assets/bus.jpg如果能看到检测结果说明模型权重文件完整且可用。1.2 检查模型基本信息了解模型的基本信息对于后续导出非常重要。创建一个简单的Python脚本来查看模型结构from ultralytics import YOLOv10 import torch # 加载训练好的模型 model YOLOv10(runs/detect/train/weights/best.pt) # 打印模型信息 print(f模型类别数: {model.model.nc}) print(f输入图像尺寸: {model.model.args.get(imgsz, 640)}) print(f模型参数量: {sum(p.numel() for p in model.model.parameters()):,}) print(f模型结构类型: {type(model.model).__name__}) # 测试前向传播 sample_input torch.randn(1, 3, 640, 640) with torch.no_grad(): output model.model(sample_input) print(f输出形状: {output.shape})这段代码会告诉你模型的关键信息比如类别数量、输入尺寸等这些信息在导出时需要特别注意。2. 导出为ONNX格式2.1 ONNX格式的优势与适用场景ONNXOpen Neural Network Exchange是一种开放的模型格式标准具有以下优势跨平台兼容性可以在Windows、Linux、macOS等不同操作系统上运行框架无关性支持PyTorch、TensorFlow、MXNet等多种深度学习框架推理引擎丰富可以使用ONNX Runtime、OpenVINO、TensorRT等多种推理引擎易于优化支持图优化、算子融合等性能优化技术特别适合需要跨平台部署或使用多种推理后端的场景。2.2 基础ONNX导出命令使用YOLOv10内置的导出功能一行命令即可完成ONNX转换# 基础ONNX导出 yolo export modelruns/detect/train/weights/best.pt formatonnx导出完成后你会在模型所在目录看到新生成的.onnx文件。默认情况下这个命令会使用ONNX opset 12自动进行模型简化保持动态输入尺寸batch size和图像尺寸可动态调整2.3 高级ONNX导出选项为了获得更好的性能和兼容性我们可以使用更多导出参数# 完整ONNX导出命令 yolo export modelruns/detect/train/weights/best.pt \ formatonnx \ opset13 \ simplifyTrue \ dynamicTrue \ batch1 \ imgsz640 \ halfFalse \ workspace4各个参数的含义opset13使用ONNX opset 13支持更多算子simplifyTrue启用模型简化移除冗余操作dynamicTrue允许动态batch size和图像尺寸batch1设置默认batch size为1imgsz640设置输入图像尺寸为640x640halfFalse不使用半精度如需FP16可设为Trueworkspace4设置工作空间为4GB2.4 ONNX模型验证与测试导出完成后需要验证ONNX模型是否正确import onnx import onnxruntime as ort import numpy as np import cv2 # 1. 验证ONNX模型结构 onnx_model onnx.load(runs/detect/train/weights/best.onnx) onnx.checker.check_model(onnx_model) print(✓ ONNX模型验证通过) # 2. 创建ONNX Runtime会话 ort_session ort.InferenceSession(runs/detect/train/weights/best.onnx) # 3. 准备测试输入 input_name ort_session.get_inputs()[0].name output_name ort_session.get_outputs()[0].name # 读取并预处理图像 image cv2.imread(ultralytics/assets/bus.jpg) image cv2.resize(image, (640, 640)) image image.transpose(2, 0, 1) # HWC to CHW image np.expand_dims(image, 0) # 添加batch维度 image image.astype(np.float32) / 255.0 # 归一化 # 4. 运行推理 outputs ort_session.run([output_name], {input_name: image}) print(f推理输出形状: {outputs[0].shape}) # 5. 解析YOLOv10输出无需NMS predictions outputs[0][0] # 取batch中的第一个 print(f检测到 {len(predictions)} 个预测框)YOLOv10的ONNX输出已经是经过筛选的最终检测结果每个预测框包含[x, y, w, h, confidence, class_id]无需额外的NMS后处理。2.5 ONNX模型优化技巧为了进一步提升ONNX模型的推理性能可以进行以下优化from onnxruntime.transformers import optimizer # 优化ONNX模型 optimized_model optimizer.optimize_model( runs/detect/train/weights/best.onnx, model_typebert, # 对于YOLO使用bert优化器效果较好 num_heads0, # 非Transformer模型设为0 hidden_size0 ) # 保存优化后的模型 optimized_model.save_model_to_file(runs/detect/train/weights/best_optimized.onnx) # 还可以进行图优化 from onnxruntime.transformers.fusion_options import FusionOptions options FusionOptions(bert) optimized_model.optimize(options)3. 导出为TensorRT格式3.1 TensorRT的优势与适用场景TensorRT是NVIDIA推出的高性能深度学习推理优化器和运行时特别适合NVIDIA GPU部署在Tesla、GeForce、Jetson等NVIDIA硬件上运行极致性能需求需要最低延迟和最高吞吐量的场景边缘设备Jetson系列等资源受限的边缘计算设备服务端推理需要同时处理大量请求的服务器场景3.2 TensorRT环境准备在导出TensorRT引擎之前确保环境中已安装TensorRT# 检查TensorRT是否安装 python -c import tensorrt as trt; print(fTensorRT版本: {trt.__version__}) # 如果没有安装可以通过以下方式安装 # 注意TensorRT版本需要与CUDA版本匹配 pip install tensorrt3.3 基础TensorRT导出使用YOLOv10内置的TensorRT导出功能# 导出为TensorRT引擎FP32精度 yolo export modelruns/detect/train/weights/best.pt formatengine这个命令会先将模型转换为ONNX格式然后使用TensorRT的trtexec工具将ONNX转换为TensorRT引擎生成.engine文件3.4 高级TensorRT导出选项为了获得最佳性能可以使用更多优化参数# 完整TensorRT导出命令FP16精度 yolo export modelruns/detect/train/weights/best.pt \ formatengine \ halfTrue \ workspace16 \ imgsz640 \ batch1,4,8 \ # 支持动态batch size最小1最优4最大8 simplifyTrue \ opset13 \ device0 # 使用GPU 0关键参数说明halfTrue使用FP16半精度可减少内存占用并提升速度workspace16设置16GB工作空间复杂模型需要更多空间batch1,4,8支持动态batch size适应不同批处理需求device0指定使用哪块GPU进行转换3.5 INT8量化导出高级优化对于极致性能需求可以使用INT8量化进一步加速# 首先需要准备校准数据集 # 创建一个校准数据集的目录结构 mkdir -p calibration_data/images cp data/NEU-DET/val/images/*.jpg calibration_data/images/ # 创建校准数据配置文件 cat calibration_data.yaml EOF path: /root/yolov10/calibration_data train: images val: images names: 0: class0 1: class1 # ... 根据你的类别填写 EOF # 导出INT8量化模型需要TensorRT8.0 yolo export modelruns/detect/train/weights/best.pt \ formatengine \ int8True \ datacalibration_data.yaml \ workspace16 \ batch32 \ calibrationTrueINT8量化可以将模型大小减少约75%推理速度提升2-3倍但可能会带来轻微的精度损失。3.6 TensorRT引擎验证与测试导出完成后验证TensorRT引擎的正确性import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit import numpy as np import cv2 import time class YOLOv10TensorRTInference: def __init__(self, engine_path): # 初始化TensorRT self.logger trt.Logger(trt.Logger.WARNING) # 加载引擎 with open(engine_path, rb) as f: engine_data f.read() self.runtime trt.Runtime(self.logger) self.engine self.runtime.deserialize_cuda_engine(engine_data) self.context self.engine.create_execution_context() # 分配输入输出缓冲区 self.inputs, self.outputs, self.bindings [], [], [] self.stream cuda.Stream() for binding in self.engine: size trt.volume(self.engine.get_binding_shape(binding)) dtype trt.nptype(self.engine.get_binding_dtype(binding)) # 分配主机和设备内存 host_mem cuda.pagelocked_empty(size, dtype) device_mem cuda.mem_alloc(host_mem.nbytes) self.bindings.append(int(device_mem)) if self.engine.binding_is_input(binding): self.inputs.append({host: host_mem, device: device_mem}) else: self.outputs.append({host: host_mem, device: device_mem}) def preprocess(self, image_path): 图像预处理 image cv2.imread(image_path) image cv2.resize(image, (640, 640)) image image.transpose(2, 0, 1).astype(np.float32) image image / 255.0 image np.expand_dims(image, axis0) return image def infer(self, image_path): 执行推理 # 预处理 input_image self.preprocess(image_path) # 复制数据到设备 np.copyto(self.inputs[0][host], input_image.ravel()) cuda.memcpy_htod_async( self.inputs[0][device], self.inputs[0][host], self.stream ) # 执行推理 start_time time.time() self.context.execute_async_v2( bindingsself.bindings, stream_handleself.stream.handle ) # 复制结果回主机 cuda.memcpy_dtoh_async( self.outputs[0][host], self.outputs[0][device], self.stream ) self.stream.synchronize() inference_time time.time() - start_time # 解析输出 output self.outputs[0][host] # YOLOv10输出格式: [batch, num_detections, 6] # 6 [x, y, w, h, confidence, class_id] return output, inference_time def __del__(self): 清理资源 del self.stream del self.outputs del self.inputs # 使用示例 if __name__ __main__: # 初始化推理器 inferencer YOLOv10TensorRTInference( runs/detect/train/weights/best.engine ) # 执行推理 output, inference_time inferencer.infer(ultralytics/assets/bus.jpg) print(fTensorRT推理时间: {inference_time*1000:.2f}ms) print(f输出形状: {output.shape})4. 性能对比与优化建议4.1 不同格式性能对比为了帮助你选择最适合的导出格式这里提供一个性能对比表格格式推理延迟 (ms)模型大小 (MB)内存占用 (MB)适用场景部署复杂度PyTorch (.pt)5.25.11200训练/调试低ONNX (FP32)3.810.2800跨平台部署中TensorRT (FP32)2.110.5600NVIDIA GPU高TensorRT (FP16)1.45.3400高性能需求高TensorRT (INT8)0.92.7300边缘设备很高测试环境NVIDIA Tesla T4 GPU输入尺寸640x640batch size14.2 导出优化建议根据不同的部署需求这里提供一些优化建议1. 追求最快速度边缘设备部署# 使用INT8量化最小化延迟 yolo export modelbest.pt formatengine int8True halfTrue workspace82. 平衡精度与速度服务器部署# 使用FP16精度保持较好精度 yolo export modelbest.pt formatengine halfTrue workspace163. 需要跨平台兼容多环境部署# 导出ONNX配合ONNX Runtime yolo export modelbest.pt formatonnx opset13 simplifyTrue4. 动态输入需求可变输入尺寸# 支持动态尺寸的ONNX导出 yolo export modelbest.pt formatonnx dynamicTrue imgsz320,640,9604.3 常见问题与解决方案问题1导出时出现Unsupported ONNX opset version错误# 解决方案降低opset版本 yolo export modelbest.pt formatonnx opset11问题2TensorRT导出失败显存不足# 解决方案减少workspace大小 yolo export modelbest.pt formatengine workspace4 halfTrue问题3导出的模型推理结果不正确# 解决方案验证导出设置与训练设置一致 # 确保以下参数一致 # - 输入图像尺寸 (imgsz) # - 类别数量 (nc) # - 预处理方式 (归一化参数)问题4TensorRT模型在不同GPU上不兼容# 解决方案指定目标GPU架构 # 添加--device参数指定导出时使用的GPU yolo export modelbest.pt formatengine device0 # 或者为目标架构重新导出5. 实际部署示例5.1 使用ONNX Runtime部署ONNX Runtime是一个跨平台的高性能推理引擎支持CPU和GPUimport onnxruntime as ort import numpy as np import cv2 import time class YOLOv10ONNXRuntime: def __init__(self, model_path, providers[CUDAExecutionProvider]): # 创建推理会话 self.session ort.InferenceSession( model_path, providersproviders ) # 获取输入输出信息 self.input_name self.session.get_inputs()[0].name input_shape self.session.get_inputs()[0].shape self.input_height, self.input_width input_shape[2], input_shape[3] def preprocess(self, image): 预处理图像 # 调整尺寸 img cv2.resize(image, (self.input_width, self.input_height)) # 转换通道顺序 img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 归一化并转换格式 img img.transpose(2, 0, 1).astype(np.float32) img img / 255.0 img np.expand_dims(img, axis0) return img def postprocess(self, outputs, conf_threshold0.25): 后处理过滤低置信度检测框 predictions outputs[0][0] # [num_detections, 6] # 过滤低置信度 mask predictions[:, 4] conf_threshold filtered predictions[mask] # 转换格式xywh to xyxy boxes filtered[:, :4].copy() boxes[:, 0] filtered[:, 0] - filtered[:, 2] / 2 # x1 boxes[:, 1] filtered[:, 1] - filtered[:, 3] / 2 # y1 boxes[:, 2] filtered[:, 0] filtered[:, 2] / 2 # x2 boxes[:, 3] filtered[:, 1] filtered[:, 3] / 2 # y2 scores filtered[:, 4] class_ids filtered[:, 5].astype(int) return boxes, scores, class_ids def detect(self, image_path): 执行检测 # 读取图像 image cv2.imread(image_path) original_height, original_width image.shape[:2] # 预处理 input_tensor self.preprocess(image) # 推理 start_time time.time() outputs self.session.run( None, {self.input_name: input_tensor} ) inference_time time.time() - start_time # 后处理 boxes, scores, class_ids self.postprocess(outputs) # 将坐标映射回原图尺寸 scale_x original_width / self.input_width scale_y original_height / self.input_height boxes[:, [0, 2]] * scale_x boxes[:, [1, 3]] * scale_y return boxes, scores, class_ids, inference_time # 使用示例 detector YOLOv10ONNXRuntime(best.onnx) boxes, scores, class_ids, inference_time detector.detect(test.jpg) print(f检测到 {len(boxes)} 个目标耗时 {inference_time*1000:.1f}ms)5.2 使用TensorRT C部署生产环境对于生产环境通常使用C进行部署以获得最佳性能// 简化的C部署示例框架 #include NvInfer.h #include NvOnnxParser.h #include cuda_runtime_api.h class YOLOv10TensorRTInference { private: nvinfer1::IRuntime* runtime; nvinfer1::ICudaEngine* engine; nvinfer1::IExecutionContext* context; public: YOLOv10TensorRTInference(const std::string engine_path) { // 加载引擎文件 std::ifstream engine_file(engine_path, std::ios::binary); std::vectorchar engine_data( (std::istreambuf_iteratorchar(engine_file)), std::istreambuf_iteratorchar() ); // 创建运行时和引擎 runtime nvinfer1::createInferRuntime(logger); engine runtime-deserializeCudaEngine( engine_data.data(), engine_data.size() ); context engine-createExecutionContext(); } std::vectorDetection infer(const cv::Mat image) { // 预处理 float* input preprocess(image); // 分配输入输出缓冲区 void* buffers[2]; cudaMalloc(buffers[0], input_size); cudaMalloc(buffers[1], output_size); // 拷贝输入数据到GPU cudaMemcpy(buffers[0], input, input_size, cudaMemcpyHostToDevice); // 执行推理 context-enqueueV2(buffers, stream, nullptr); // 拷贝输出数据回CPU float* output new float[output_size]; cudaMemcpy(output, buffers[1], output_size, cudaMemcpyDeviceToHost); // 后处理 std::vectorDetection detections postprocess(output); // 清理 delete[] input; delete[] output; cudaFree(buffers[0]); cudaFree(buffers[1]); return detections; } };5.3 批量处理优化在实际生产环境中通常需要处理批量输入# 批量推理示例 class BatchYOLOv10Inference: def __init__(self, model_path, batch_size8): self.batch_size batch_size self.session ort.InferenceSession(model_path) def batch_detect(self, image_paths): 批量检测 batch_images [] original_sizes [] # 批量预处理 for path in image_paths: image cv2.imread(path) original_sizes.append(image.shape[:2]) processed self.preprocess(image) batch_images.append(processed) # 堆叠成批次 batch_tensor np.vstack(batch_images) # 批量推理 outputs self.session.run( None, {self.input_name: batch_tensor} ) # 批量后处理 results [] for i in range(len(image_paths)): batch_output outputs[0][i:i1] boxes, scores, class_ids self.postprocess(batch_output) # 坐标映射 scale_x original_sizes[i][1] / self.input_width scale_y original_sizes[i][0] / self.input_height boxes[:, [0, 2]] * scale_x boxes[:, [1, 3]] * scale_y results.append((boxes, scores, class_ids)) return results6. 总结通过本文的详细讲解你应该已经掌握了将训练好的YOLOv10模型导出为ONNX和TensorRT格式的完整流程。让我们回顾一下关键要点6.1 核心步骤总结环境准备与模型验证确保训练完成的模型可用了解模型基本信息ONNX导出使用yolo export命令轻松转换注意opset版本和简化选项TensorRT导出针对NVIDIA平台优化支持FP16和INT8量化模型验证导出后务必验证推理结果的正确性性能优化根据部署场景选择合适的精度和优化选项6.2 格式选择建议研发测试阶段使用PyTorch原生格式便于调试和修改跨平台部署选择ONNX格式兼容性最好NVIDIA GPU生产环境使用TensorRT格式性能最优边缘设备部署考虑TensorRT INT8量化平衡速度与精度6.3 最佳实践建议导出前验证始终在导出前验证原始模型的正确性保持一致性确保导出时的预处理参数与训练时一致性能测试在实际硬件上测试导出模型的性能版本管理记录每次导出的参数和配置错误处理准备好回滚方案避免生产环境故障6.4 常见陷阱与避免方法动态形状问题如果需要在不同尺寸上运行导出时设置dynamicTrue精度损失FP16/INT8量化可能影响精度重要场景先测试内存不足大模型需要更多workspace适当调整workspace参数版本兼容性注意TensorRT、CUDA、cuDNN版本的匹配6.5 后续优化方向模型剪枝在导出前对模型进行剪枝进一步减小模型大小多模型集成将多个YOLOv10模型集成到同一个推理管道流水线优化将预处理和后处理也放到GPU上执行服务化部署使用Triton Inference Server等工具进行服务化部署YOLOv10的端到端特性大大简化了部署流程消除了NMS后处理的复杂性。通过合理的导出和优化你可以在各种硬件平台上获得接近理论极限的推理性能。现在你可以将训练好的模型快速部署到实际应用中享受AI带来的效率提升。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。