
简介本资源是一套基于 TensorRT 与 YOLO 算法的目标检测与实例分割部署项目面向需要跨平台落地深度学习模型的开发者、算法研究人员及企业技术团队帮助解决从模型推理加速到多语言工程集成的实际问题。压缩包共含 1523 个文件约 314.08MB以 hpp、h、cpp 等 C 头文件与源码为主体配合 py 脚本、cu 与 cuh 的 CUDA 核函数、cmake 与 vcxproj 构建配置、dll 与 lib 动态库以及 md 文档和 yml 配置完整覆盖 C 与 Python 两条开发链路。项目同时支持 Linux 与 Windows可实现目标检测与实例分割双重功能适用于监控安全、工业质检、智能交通及医疗图像分析等场景。已有 307 人学习下载读者可获取完整工程文档、可编译的源码结构与跨平台部署配置便于集成到自有项目或用于算法测试验证。1. 从 PyTorch 权重到 TensorRT 引擎这套 YOLO 部署包到底解决了什么训练完一个 YOLO 实例分割模型best.pt在 PyTorch 里跑得好好的一上产线就发现单帧推理要 80ms产线节拍要求 30ms 以内——这是很多人第一次做部署时遇到的真实落差。这套资源就是冲着这个落差来的它把 YOLO 的实例分割和目标检测两条链路用 TensorRT 做了推理加速并且同时给了 C 和 Python 两套调用方式Linux 和 Windows 都能跑。换句话说你拿到的不只是一个能跑的 demo而是一份可以往自己项目里搬的部署骨架。它适合三类人一是手里已经有 YOLO 权重、想把它塞进 C 工程里的开发者二是需要在 Windows 工控机上做本地推理、又不想依赖 Python 环境的团队三是做算法验证、想对比 TensorRT 和原生 PyTorch 推理差距的研究人员。下面按「引擎怎么来 → 两套代码怎么调 → 坑在哪 → 怎么验证」的顺序拆开讲。2. TensorRT 引擎构建从 .pt 到 .engine 的关键参数2.1 为什么不能直接拿 .pt 去推理PyTorch 的.pt文件里存的是计算图和权重推理时框架要动态调度算子、做内存分配这些开销在训练阶段无所谓在部署阶段就是纯浪费。TensorRT 做的事是把这个计算图「编译」成针对特定 GPU 架构优化过的引擎文件过程中会做层融合、精度校准、kernel 自动调优。常见做法是先把.pt导出成 ONNX再由 TensorRT 的解析器读 ONNX 生成.engine。中间多这一步 ONNX是因为它是个通用的中间表示TensorRT、OpenVINO 这些推理框架都能吃方便你以后换后端。这里有个容易被忽略的点.engine文件是跟 GPU 架构绑定的。你在 RTX 4090 上生成的引擎拿到 Jetson 或者 Tesla V100 上是用不了的必须重新构建。所以工程里一般会把构建脚本单独放部署时按目标机器重新跑一遍。2.2 导出 ONNX 的实操与参数导出这一步YOLO 官方仓库一般会提供export.py但实例分割模型和纯检测模型的输出头不一样导出时要注意--include onnx之外还得确认输出节点名字。下面是一段常见的导出命令参数我按实际会改的地方标注# 导出 ONNXimgsz 要和训练时一致否则后处理坐标会错位 python export.py \ --weights best.pt \ --include onnx \ --imgsz 640 640 \ --batch 1 \ --dynamic False \ --simplify \ --opset 12--imgsz必须和训练分辨率对齐训练用 640 导出用 1280检测框会整体偏移。--dynamic False表示固定 batch 和尺寸固定尺寸能让 TensorRT 做更激进的优化吞吐更高如果你确实需要变长输入再开 dynamic但性能会掉一截。--simplify会调用 onnx-simplifier 把冗余节点去掉这一步能减少后面 TensorRT 解析失败的概率。--opset 12是个比较稳的版本太低不支持某些算子太高部分 TensorRT 版本解析器跟不上。导出完建议用onnxruntime跑一遍确认输出和 PyTorch 对得上别等到 TensorRT 阶段才发现数值不对那时候排查成本高得多。2.3 用 trtexec 构建引擎构建引擎最省事的方式是用 TensorRT 自带的trtexec不用写代码# 基础构建FP16 精度适合大多数带 Tensor Core 的卡 trtexec \ --onnxbest.onnx \ --saveEnginebest_fp16.engine \ --fp16 \ --workspace4096 \ --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 \ --maxShapesimages:1x3x640x640--fp16开启半精度速度通常比 FP32 快 1.5 到 2 倍精度损失在检测任务里一般可以接受。--workspace4096是给 TensorRT 的显存工作区单位 MB太小会导致某些层无法用最优 kernel构建失败或者性能不达标。三个 shape 参数在固定尺寸时写一样就行开 dynamic 时才需要区分最小、最优、最大。构建过程可能几分钟日志里会打印每层的耗时如果某一层特别慢往往是那里发生了精度回退。提示构建引擎时显存占用会明显高于推理时如果构建阶段报显存不足先把 workspace 调小或者换一台显存更大的机器构建构建完的引擎文件是可以拷走的同架构前提下。3. Python 与 C 两套推理代码怎么调、怎么改3.1 Python 侧封装推理类与后处理Python 版本适合快速验证和算法调试。核心是把 TensorRT 的 runtime、engine、context 三层对象管好然后喂数据、取输出、做后处理。下面是一个精简的推理封装重点看输入预处理和输出解析import tensorrt as trt import numpy as np import cv2 class TRTInfer: def __init__(self, engine_path): logger trt.Logger(trt.Logger.WARNING) with open(engine_path, rb) as f, trt.Runtime(logger) as runtime: self.engine runtime.deserialize_cuda_engine(f.read()) self.context self.engine.create_execution_context() # 按绑定名字拿输入输出别用固定索引不同版本顺序会变 self.input_name self.engine.get_tensor_name(0) self.output_names [self.engine.get_tensor_name(i) for i in range(1, self.engine.num_io_tensors)] def preprocess(self, img, size640): # letterbox 保持长宽比避免拉伸导致框变形 h, w img.shape[:2] scale min(size / h, size / w) nh, nw int(h * scale), int(w * scale) resized cv2.resize(img, (nw, nh)) canvas np.full((size, size, 3), 114, dtypenp.uint8) canvas[:nh, :nw] resized blob canvas[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 return np.ascontiguousarray(blob[None]), scale, (nw, nh)get_tensor_name按名字取绑定比按索引稳因为 TensorRT 8 之后 IO 顺序不一定和 ONNX 一致。预处理里的 letterbox 是关键直接resize到 640x640 会把宽高比压扁后处理还原坐标时框就对不上。填充值用 114 是 YOLO 系列的惯例和训练时的填充保持一致。后处理部分检测头输出的是[1, 4ncnm, 8400]这种形状实例分割还多一路 mask 系数。要做的是先按置信度阈值筛再 NMS最后把 mask 系数和原型 mask 做矩阵乘还原出每个实例的分割图。这块代码量不小资源包里应该已经封装好了重点是你得知道阈值在哪改置信度阈值一般 0.25NMS 的 IoU 阈值 0.45这两个值直接决定召回和误检的平衡。3.2 C 侧内存管理与跨平台编译C 版本适合往生产环境集成性能开销比 Python 小也没有 GIL 的干扰。但 C 写 TensorRT 的坑集中在内存管理上你得自己cudaMalloc分配显存、自己cudaMemcpy搬数据、自己管 stream 同步。下面这段是推理主循环的骨架// 分配显存绑定地址 void* buffers[2]; cudaMalloc(buffers[0], inputSize * sizeof(float)); cudaMalloc(buffers[1], outputSize * sizeof(float)); context-setTensorAddress(inputName, buffers[0]); context-setTensorAddress(outputName, buffers[1]); // 异步推理用 stream 重叠拷贝和计算 cudaStream_t stream; cudaStreamCreate(stream); cudaMemcpyAsync(buffers[0], hostInput, inputSize * sizeof(float), cudaMemcpyHostToDevice, stream); context-enqueueV3(stream); cudaMemcpyAsync(hostOutput, buffers[1], outputSize * sizeof(float), cudaMemcpyDeviceToHost, stream); cudaStreamSynchronize(stream);setTensorAddress是 TensorRT 8.5 之后的 API老版本用setBindingAddress如果你拿到的代码编译报这个函数找不到先查 TensorRT 版本。enqueueV3对应enqueueV2同样是版本差异。跨平台编译时Linux 下用 CMake 找 TensorRT 的.soWindows 下链接.lib路径配置在 CMakeLists 里通常用find_package或者手动include_directories加target_link_libraries。Windows 上还要注意 CUDA 和 TensorRT 的版本必须匹配CUDA 12 配 TensorRT 8.6 以上混搭会链接失败。注意C 里cudaMalloc的显存一定要在析构里cudaFree否则长时间跑会显存泄漏表现为跑几小时后推理突然变慢甚至崩掉。这个坑我在实际项目里踩过排查了半天才定位到。4. 避坑与排查部署路上最容易翻车的五件事4.1 引擎构建成功但推理结果全错现象是程序不报错但检测框位置离谱或者类别全乱。原因通常是预处理和后处理不匹配要么 letterbox 的填充方式跟训练时不一致要么输出张量的解析顺序搞反了。YOLO 的输出里坐标是xywh还是xyxy、有没有做归一化不同导出配置不一样。解决办法是拿一张已知结果的图把 TensorRT 输出和 PyTorch 输出逐元素对比先确认数值对得上再查坐标变换。4.2 TensorRT 版本和 CUDA 版本对不上现象是import tensorrt直接报找不到库或者构建引擎时报Unsupported SM。原因是 TensorRT 每个版本对 CUDA 有明确要求而且对 GPU 的计算能力有下限。比如 TensorRT 10.x 对老架构的支持就收紧了GTX 1070 这种 Pascal 架构的卡在新版本上可能直接不被支持。解决办法是先查官方兼容性表确认你的卡的计算能力在支持范围内然后严格按版本对应关系装 CUDA 和 TensorRT别图省事混装。4.3 Windows 下缺 Visual C 运行库现象是 C 程序编译通过但一运行就弹窗报缺少msvcp140.dll或者直接闪退。原因是 Windows 上编译出来的 exe 依赖 Visual C Redistributable目标机器没装就跑不起来。解决办法是在部署机器上装对应版本的vc_redist.x64.exe或者编译时改成静态链接运行库。这个坑在工控机上特别常见因为那些机器往往是很干净的系统。4.4 显存不够导致构建或推理失败现象是构建引擎时报out of memory或者推理时 batch 一大就崩。原因是 workspace 设太大或者输入分辨率、batch 超过显存容量。解决办法是构建时把 workspace 从 4096 往下调推理时减小 batch 或者分辨率。另外要注意TensorRT 引擎加载后本身占一部分显存如果同时跑多个模型得把总占用算进去。4.5 Python 和 C 结果不一致现象是同一张图Python 跑出来框对C 跑出来偏了。原因多半是预处理里的图像通道顺序或者归一化系数不同Python 用cv2读进来是 BGRC 如果按 RGB 处理就错了。还有 letterbox 的缩放系数计算两边如果一处用min一处用max结果也会差。解决办法是把预处理单独抽成一个函数两边用同一套逻辑并且打印中间张量的统计值对比。5. 验证部署是否真的达标三个可量化的检查点部署完不能只看「能跑出框」得用数据说话。第一个检查点是精度对齐拿验证集跑一遍把 TensorRT 的 mAP 和 PyTorch 的 mAP 对比FP16 精度下掉点通常在 0.5 个点以内算正常掉太多说明某层精度回退严重可以尝试对敏感层保持 FP32。第二个检查点是延迟用trtexec --loadEnginexxx.engine --iterations100测纯推理耗时再在你的业务代码里测端到端耗时两者差值就是预处理和后处理的开销如果后处理占了大头说明 NMS 那块需要优化。第三个检查点是显存占用用nvidia-smi观察稳定运行时的显存确认没有随时间增长排除泄漏。# 测引擎纯推理性能看 GPU Compute Time 那一行 trtexec --loadEnginebest_fp16.engine --iterations100 --warmUp10--warmUp10是预热次数第一次推理往往包含 kernel 加载和缓存初始化不预热测出来的数偏高。--iterations100取平均单次测量抖动大。输出里重点看GPU Compute Time的 mean 和 percentile如果 99 分位比均值高很多说明有偶发的调度抖动产线上要留够余量。我自己的习惯是每次换 GPU 或者升级 TensorRT 版本后这三个检查点强制走一遍不省这一步。因为引擎这东西是个黑匣子构建日志不报错不代表结果对只有数据能证明。希望这套流程能帮你少走点弯路把模型真正落到产线上。本文还有配套的精品资源点击获取