ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PaddleDetection PP-YOLOE 转 ONNX-TensorRT 部署教程:模型导出、EfficientNMS_TRT 定制与推理实战

PaddleDetection PP-YOLOE 转 ONNX-TensorRT 部署教程:模型导出、EfficientNMS_TRT 定制与推理实战 PaddleDetection PP-YOLOE 转 ONNX-TensorRT 部署教程模型导出、EfficientNMS_TRT 定制与推理实战【免费下载链接】PaddleDetectionObject Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleDetection本教程完整讲解如何将 PaddleDetection 中的 PP-YOLOE 检测模型导出为 ONNX并通过 onnx-graphsurgeon 定制化接入 TensorRT 的 EfficientNMS_TRT 插件最终在 TensorRT 引擎上完成高性能推理。文章以仓库内deploy/third_engine/demo_onnx_trt目录下的完整示例为主线结合tools/export_model.py与 PP-YOLOE 检测头的源码实现带你走通「Paddle 模型 → ONNX → TensorRT Engine → 推理」的整条部署链路。读完本文你将掌握导出时trtTrue与exclude_nmsTrue的含义、EfficientNMS_TRT 各插件参数的作用、trtexec 构建引擎的注意事项以及基于 PyCUDA 的 TensorRT 推理与 COCO 结果输出的完整实现。1. 部署方案概述为什么选择 ONNX EfficientNMS_TRTPP-YOLOE 是 PaddleDetection 中面向工业落地的高精度、高速度单阶段检测模型仓库中提供ppyoloe_crn_l_300e_coco、ppyoloe_plus_crn_s_80e_coco等多个配置与预训练权重。当模型需要部署到 NVIDIA GPU 上追求极致吞吐时TensorRT 是主流加速方案而 Paddle 推理模型并非 TensorRT 原生格式需要借助 ONNX 作为中间交换格式。本仓库在 deploy/third_engine/demo_onnx_trt 目录下提供了一个端到端示例其技术路线为使用tools/export_model.py将 PP-YOLOE 动态图模型导出为静态图推理模型model.pdmodel/model.pdiparams/infer_cfg.yml并在导出阶段通过trtTrue exclude_nmsTrue让检测头跳过 NMS 后处理直接输出原始预测框与分类分数使用paddle2onnx将 Paddle 模型转换为 ONNX 图使用onnx-graphsurgeon读取并修改 ONNX 图在模型尾部插入 TensorRT 官方的EfficientNMS_TRT插件节点把「解码 NMS」后处理整体下沉到 TensorRT 内部完成使用trtexec将定制后的 ONNX 构建为 TensorRT 序列化引擎.engine使用基于 PyCUDA 的 trt_infer.py 加载引擎完成推理并支持输出 COCO 格式的检测结果 json。EfficientNMS_TRT 是 NVIDIA TensorRT 官方插件库efficientNMSPlugin提供的后处理算子它将包围框解码、置信度过滤与 NMS 融合进 TensorRT 图中一次执行避免在 GPU 与 CPU 之间往返做后处理从而显著降低端到端延迟。这正是本示例的核心价值后处理不出图。2. 环境依赖与准备原教程给出的推荐环境组合为CUDA 10.2cuDNN 8.2.1TensorRT 8.2需支持 EfficientNMS_TRT 插件Python 侧依赖三个关键库onnx onnxruntime paddle2onnx此外由于定制 ONNX 图使用了onnx-graphsurgeon见 onnx_custom.py 中的import onnx_graphsurgeon推理阶段还依赖tensorrt与pycuda见 trt_infer.py 中的import tensorrt as trt、import pycuda.driver。建议按实际安装的 CUDA / TensorRT 版本选用与之匹配的 TensorRT Python wheel 与 PyCUDA 版本示例脚本本身会通过trt.init_libnvinfer_plugins(TRT_LOGGER, namespace)在进程启动时加载 TensorRT 内置插件库从而注册 EfficientNMS_TRT 插件。3. 第一步Paddle 模型导出trtTrue 与 exclude_nmsTrue 的作用进入仓库根目录后执行以下命令导出 PP-YOLOE-L 模型python tools/export_model.py -c configs/ppyoloe/ppyoloe_crn_l_300e_coco.yml -o weightshttps://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_300e_coco.pdparams trtTrue exclude_nmsTrue命令拆解-c configs/ppyoloe/ppyoloe_crn_l_300e_coco.yml指定模型配置文件即 configs/ppyoloe/ppyoloe_crn_l_300e_coco.yml-o覆盖配置项这里覆盖了weights为 PP-YOLOE-L 预训练权重下载地址trtTrue导出面向 TensorRT 的图。查看 ppyoloe_head.py 源码可知PPYOLOEHead的forward中MultiClassNMS支持trt开关self.nms.trt trt开启后 NMS 算子的实现形态按 TensorRT 兼容方式输出exclude_nmsTrue跳过检测头内部的 NMS 后处理。源码中exclude_nms分支直接返回pred_bboxes, pred_scores, None不再执行self.nms(...)。这样 ONNX 图的输出就只剩下原始预测框张量和分类分数张量两个输出为后续在 ONNX 图中手动插入 EfficientNMS_TRT 插件腾出了位置。从源码实现看这一开关与后处理链路的关系清晰可见exclude_nmsTrue时输出的是经scale_factor还原到原始图像尺度的解码框pred_bboxes / scale_factor与未经过滤的分数矩阵因此后续插件必须自行完成置信度阈值过滤、NMS 与 topk 截断。导出完成后会在默认输出目录output_inference/ppyoloe_crn_l_300e_coco/下生成model.pdmodel静态图模型结构model.pdiparams模型权重infer_cfg.yml由 export_utils.py 生成的推理配置预处理变换、label_list、draw_threshold、fpn_stride 等后续推理脚本会解析它来还原预处理流程。关于导出入口tools/export_model.py 通过Trainer.export()实现在 trainer.py 的export方法中完成「动转静 参数保存」因此该步骤要求已正确安装 PaddlePaddle 与 PaddleDetection 及其依赖。4. 第二步ONNX 转换与 EfficientNMS_TRT 定制化修改接下来将 Paddle 推理模型转换为 ONNX并把 NMS 后处理定制为 EfficientNMS_TRT 插件python deploy/third_engine/demo_onnx_trt/onnx_custom.py --onnx_fileoutput_inference/ppyoloe_crn_l_300e_coco/ppyoloe_crn_l_300e_coco.onnx --model_diroutput_inference/ppyoloe_crn_l_300e_coco/ --opset_version11onnx_custom.py 是一个「一键两用」的脚本当传入--model_dir时脚本会先调用paddle2onnx.command.program2onnx读取目录下的model.pdmodel与model.pdiparams导出 ONNX 文件到--onnx_file指定路径opset 版本由--opset_version控制无论是否传入--model_dir脚本随后都会对--onnx_file指向的 ONNX 模型执行定制化修改。定制化的核心流程对应main()函数如下onnx.load读取 ONNX 模型onnx_graphsurgeon.import_onnx转为图对象graph.toposort()拓扑排序、fold_constants()折叠常量、cleanup()清理冗余节点从graph.outputs[1]即 PP-YOLOE 输出的分数张量解析出num_anchorsshape 第 3 维与num_classesshape 第 2 维这两个值将用于声明插件输入与输出的形状在分数输出后追加一个Transpose层lastTransposeperm 为[0, 2, 1]将分数张量从[batch, num_classes, num_anchors]调整为[batch, num_anchors, num_classes]与 EfficientNMS_TRT 期望的输入排布对齐插入EfficientNMS_TRT插件节点输入为graph.outputs[0]预测框与转置后的scores输出为四个张量num_dets、det_boxes、det_scores、det_classes将图的输出重定向为上述四个插件输出重新cleanup().toposort()后onnx.save回写原文件并打印保存提示。4.1 EfficientNMS_TRT 插件参数一览脚本暴露了三个可通过命令行调整的 NMS 超参数并硬编码了其余插件属性参数项默认值说明--opset_version11导出 ONNX 时使用的 opset 版本--topk_all300每张图像最多保留的检测框数量对应max_output_boxes--iou_thres0.7NMS 的 IoU 阈值对应iou_threshold--conf_thres0.01置信度过滤阈值对应score_threshold插件节点的固定属性及其含义plugin_version1EfficientNMS_TRT 插件版本background_class-1不设背景类所有类别均参与 NMSmax_output_boxes、score_threshold、iou_threshold分别来自--topk_all、--conf_thres、--iou_thresscore_activationFalse不对分数做额外的 Sigmoid 激活PP-YOLOE 输出的分数本身已含激活box_coding0预测框编码为[x1, y1, x2, y2]corner 格式。插件输出张量语义num_dets[batch, 1]每张图实际检测框数量det_boxes[batch, topk_all, 4]检测框坐标corner 格式det_scores[batch, topk_all]检测框置信度det_classes[batch, topk_all]检测框类别索引。outputs [ onnx_graphsurgeon.Variable(num_dets, np.int32, [-1, 1]), onnx_graphsurgeon.Variable(det_boxes, np.float32, [-1, FLAGS.topk_all, 4]), onnx_graphsurgeon.Variable(det_scores, np.float32, [-1, FLAGS.topk_all]), onnx_graphsurgeon.Variable(det_classes, np.int32, [-1, FLAGS.topk_all]) ] graph.layer( opEfficientNMS_TRT, namebatched_nms, inputs[graph.outputs[0], scores], outputsoutputs, attrsattrs)从代码结构可以推断该定制方式不仅适用于 PP-YOLOE只要模型输出是「解码框 分数」的形态例如 YOLO 系列检测头在exclude_nms下的输出都可以按同一套路接入 EfficientNMS_TRT。而 trt_infer.py 中的SUPPORT_MODELS集合含 YOLO、PPYOLOE、RCNN、SSD、Face、FCOS、SOLOv2、TTFNet、S2ANet、JDE、FairMOT、DeepSORT、GFL、PicoDet、CenterNet、TOOD、RetinaNet、StrongBaseline、STGCN、YOLOX、HRNet 等则表明该推理框架面向 PaddleDetection 的通用部署场景设计。5. 第三步使用 trtexec 构建 TensorRT Engine定制完成并回写 ONNX 文件后使用 TensorRT 自带的trtexec工具构建引擎trtexec --onnxoutput_inference/ppyoloe_crn_l_300e_coco/ppyoloe_crn_l_300e_coco.onnx --saveEngineppyoloe_crn_l_300e_coco.engine该命令会将定制后的 ONNX 解析、构图并做层融合最终序列化为ppyoloe_crn_l_300e_coco.engine文件。注意若构建或运行时报错可以尝试追加以下参数绕开 cuBLASLt 的算子选择问题--tacticSources-cublasLt,cublas该参数指示 TensorRT 在选取卷积/矩阵乘实现策略时排除cublasLt仅使用传统cublas这是 TensorRT 部署中处理算子选型tactic兼容性问题的常用手段。此外若需要以动态 batch 或动态输入尺寸运行还可以在 trtexec 中配置--minShapes/--optShapes/--maxShapes但本示例的推理脚本默认按静态/固定 batchbatch1方式加载引擎。6. 第四步运行 TensorRT 推理引擎构建完成后执行推理python deploy/third_engine/demo_onnx_trt/trt_infer.py --infer_cfgoutput_inference/ppyoloe_crn_l_300e_coco/infer_cfg.yml --trt_engineppyoloe_crn_l_300e_coco.engine --image_filedemo/000000014439.jpg参数说明参数必需说明--infer_cfg是导出阶段生成的infer_cfg.yml描述预处理变换等推理配置--trt_engine是TensorRT 引擎文件路径--image_file二选一单张推理图片路径与--image_dir二选一单图优先级更高--image_dir二选一批量推理图片目录自动收集jpg/jpeg/png/bmp含大写扩展名--repeats否重复推理次数默认 1用于基准测速会输出平均耗时--save_coco否是否输出 COCO 格式结果 json默认关闭--coco_file否COCO 结果保存路径默认results.json6.1 推理脚本内部流程trt_infer.py 的执行链路如下加载引擎load_trt_engine()以二进制读取.engine文件通过trt.Runtime.deserialize_cuda_engine反序列化为ICudaEngine解析推理配置PredictConfig读取infer_cfg.yml校验arch是否在SUPPORT_MODELS中并提取Preprocess变换列表、label_list、use_dynamic_shape、draw_threshold等字段构建预处理Compose实现在 preprocess.py根据infer_cfg.yml中Preprocess的算子类型动态实例化变换链——Resize/LetterBoxResize/NormalizeImage/Permute/PadStride等最终输出与训练时一致的image、im_shape、scale_factor输入绑定缓冲create_trt_bindings()遍历引擎的输入输出 binding分配 host 端内存与cuda.mem_alloc设备显存输入 binding 初始填入随机数据预热与推理predict_image()先以随机输入预热 10 次再对每张图执行「H2D 异步拷贝 →context.execute_async_v2→ D2H 异步拷贝 → 流同步」逐张打印耗时并在最后输出平均推理时间毫秒COCO 结果格式化若开启--save_cocoformat_coco_results()会将插件输出的det_boxesxyxy 格式转换为 COCO 的 xywh 格式并通过 preprocess.py 中的coco_clsid2catid映射表把模型类别索引0~79映射为 COCO 官方类别 ID1~90连同det_scores、det_classes一起写入 json 文件便于直接对接 COCO 评估工具。# 预热 10 次再正式推理并统计平均耗时 run_trt_context(context, bindings, stream, repeats10) ... output run_trt_context(context, bindings, stream, repeatsrepeats) print(f{i 1}/{num_data} infer time: {output[infer_time]} ms.)推理示例图片可直接使用仓库自带的 demo/000000014439.jpgCOCO 数据集风格样张。若想评估多图吞吐可将--image_file换成--image_dir指向图片目录。7. 常见问题与排查建议trtexec 构建失败或推理报错优先尝试--tacticSources-cublasLt,cublas若仍失败请核对 CUDA / cuDNN / TensorRT 三者版本是否与导出环境匹配教程推荐 CUDA 10.2 cuDNN 8.2.1 TensorRT 8.2 的组合不同组合下算子支持度有差异。ONNX 图中找不到预期输出确认导出阶段确实传入了exclude_nmsTrue否则检测头内部已完成 NMS输出形态不是「框 分数」onnx_custom.py中graph.outputs[1]的解析将失去意义。推理结果类别 ID 不符TensorRT 输出的是模型训练时的类别索引写入 COCO 结果时需经coco_clsid2catid映射见 preprocess.py 末尾的映射表直接使用索引会导致评估错误。预处理不一致导致精度下降推理脚本的预处理必须与训练配置完全一致preprocess.py 中Compose完全由infer_cfg.yml驱动请勿手动修改导出后的配置文件。8. 小结本教程围绕 deploy/third_engine/demo_onnx_trt 目录给出了 PP-YOLOE 从 Paddle 到 TensorRT 的完整部署闭环通过trtTrue exclude_nmsTrue导出跳过 NMS 的推理模型用paddle2onnx转 ONNX再用onnx-graphsurgeon接入 EfficientNMS_TRT 插件把解码与 NMS 沉入引擎内部最后经 trtexec 构建引擎并用 PyCUDA 完成推理。整条链路中onnx_custom.py、trt_infer.py 与 preprocess.py 三个脚本即为可直接复用的最小工程样板对于仓库中其他「框 分数」输出的检测模型可参照同一模式完成 ONNX-TensorRT 部署。【免费下载链接】PaddleDetectionObject Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleDetection创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表