- 人工智能
- 深度学习
- 计算机视觉
【免费下载链接】PaddleDetection
Object Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.
本篇技术指南完整讲解如何在 Windows 平台下,使用 Visual Studio 2019 Community 对 PaddleDetection 的 C++ 端预测部署代码(deploy/cpp目录)进行 CMake 编译、链接 PaddlePaddle C++ 预测库(paddle_inference)并运行检测/关键点联合推理。读完本文,你将掌握从源码下载、预测库与 OpenCV 安装配置、VS2019 下 CMake 生成与编译、可执行文件运行到性能基准测试的完整闭环,并理解其底层调用链与源码实现原理。
一、为什么选择 Visual Studio 2019 编译 C++ 部署代码
PaddleDetection 的 C++ 端预测部署位于仓库的 deploy/cpp 目录,该目录不依赖PaddleDetection下其他任何目录,可独立编译、二次开发并集成到自有项目中。它支持跨平台(Windows / Linux / Jetson),可扩展新模型的预处理逻辑,并对图像检测的关键步骤做了性能优化,支持 YOLOv3、Faster RCNN、SSD、PP-YOLO 等多种检测模型结构。
微软从 Visual Studio 2017 开始支持直接管理 CMake 跨平台编译项目,但直到 Visual Studio 2019 才提供稳定且完整的支持。因此官方在 windows_vs2019_build.md 中明确推荐:在 Windows 上使用 CMake 管理项目编译构建时,采用Visual Studio 2019环境,本文全部命令也以 VS2019 的 Community(社区版)为例。
提示:仓库还提供了 Linux 编译部署 与 NV Jetson 编译部署 两篇指南,Windows 与 Linux 的 CMake 参数高度相似,仅有少量平台差异(见下文“平台差异”小节),本文聚焦 Windows 流程。
二、前置条件
在开始编译前,请确认系统已安装如下基本软件:
| 软件 | 说明 |
|---|---|
| Visual Studio 2019 | 需要根据 Paddle 预测库所使用的 VS 版本选择,详见微软官方《Visual Studio 不同版本二进制兼容性》文档 |
| CUDA 9.0 / CUDA 10.0 | 仅在使用 GPU 版本的预测库时需要;cudnn 7+ |
| TensorRT | 仅在使用 GPU 版本预测库且启用 TensorRT 时需要 |
| CMake 3.0+ | 可从 CMake 官网下载安装 |
TensorRT 与预测库版本对照
特别注意:Windows 下预测库需要的 TensorRT 版本有严格对应关系:
| 预测库版本 | TensorRT 版本 |
|---|---|
| cuda10.1_cudnn7.6_avx_mkl_trt6 | TensorRT-6.0.1.5 |
| cuda10.2_cudnn7.6_avx_mkl_trt7 | TensorRT-7.0.0.11 |
| cuda11.0_cudnn8.0_avx_mkl_trt7 | TensorRT-7.2.1.6 |
版本对齐是 Windows GPU 部署最容易踩坑的地方:预测库、CUDA、cuDNN、TensorRT 四者的版本必须匹配,否则运行期会报符号缺失或引擎加载失败。
下面所有示例统一以工作目录为D:\projects演示。
三、Step1:下载代码
git clone https://github.com/PaddlePaddle/PaddleDetection.git其中 C++ 预测代码位于PaddleDetection/deploy/cpp目录。该目录的顶层结构如下(见 deploy/cpp/README.md):
deploy/cpp ├── src │ ├── main.cc # 集成代码示例,程序入口(检测) │ ├── main_keypoint.cc # 关键点+检测联合预测的程序入口 │ ├── main_jde.cc # MOT(多目标跟踪)程序入口 │ ├── object_detector.cc # 模型加载和预测主要逻辑封装类实现 │ ├── keypoint_detector.cc# 关键点检测器封装 │ ├── preprocess_op.cc # 预处理相关主要逻辑封装实现 │ └── utils.cc ├── include │ ├── config_parser.h # 导出模型配置 yaml 文件解析 │ ├── object_detector.h # 模型加载和预测主要逻辑封装类 │ ├── preprocess_op.h # 预处理相关主要逻辑类封装 │ └── ... ├── docs │ ├── linux_build.md # Linux 编译指南 │ └── windows_vs2019_build.md # Windows VS2019 编译指南 ├── CMakeLists.txt # cmake 编译入口文件 └── cmake # 依赖的外部项目 cmake(目前仅有 yaml-cpp)从 CMakeLists.txt 的源码可以看出,编译目标会根据功能开关选择不同的源文件集合:
- 开启
WITH_KEYPOINT:编译main_keypoint.cc+ 检测 + 关键点相关源文件; - 开启
WITH_MOT:编译main_jde.cc+ JDE 检测器 + 跟踪(tracker/trajectory/lapjv)相关源文件; - 默认(两者均不开启):仅编译
main.cc检测入口。
四、Step2:下载 PaddlePaddle C++ 预测库 paddle_inference
PaddlePaddle C++ 预测库针对不同的 CPU 和 CUDA 版本提供了多个预编译版本,请按实际环境从官方 C++ 预测库下载列表(Windows 一节)选择对应版本。
解压后D:\projects\paddle_inference目录包含:
paddle_inference ├── paddle # paddle 核心库和头文件 ├── third_party # 第三方依赖库和头文件 └── version.txt # 版本和编译信息源码视角:预测库目录如何被使用
CMakeLists.txt 中,PADDLE_DIR指向的目录会被加入头文件搜索路径并链接第三方依赖库:
- 头文件:
${PADDLE_DIR}/paddle/include、third_party/install/protobuf/include、glog/include、gflags/include、xxhash/include,以及third_party/boost、third_party/eigen3等; - 库文件:
third_party/install/protobuf/lib、glog/lib、gflags/lib、xxhash/lib、paddle2onnx/lib、onnxruntime/lib与${PADDLE_DIR}/paddle/lib/。
在 Windows 分支(CMakeLists.txt)下还会额外包含${PADDLE_DIR}/paddle/fluid/inference目录,并链接${PADDLE_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}(即paddle_inference.lib)。这就是 Windows 下必须把PADDLE_LIB_NAME设置为paddle_inference的原因。
五、Step3:安装配置 OpenCV
- 在 OpenCV 官网下载适用于 Windows 平台的3.4.6版本;
- 运行下载的可执行文件,将 OpenCV 解压至指定目录,如
D:\projects\opencv; - 配置环境变量(如果后续 CMake 使用全局绝对路径,可以不用设置环境变量):
- 我的电脑 → 属性 → 高级系统设置 → 环境变量;
- 在系统变量中找到
Path(如没有,自行创建),双击编辑; - 新建,将 OpenCV 的 bin 目录填入并保存,如
D:\projects\opencv\build\x64\vc14\bin。
该 bin 目录下的
opencv_world346.dll在运行阶段会被main.exe动态加载,若运行时报"找不到opencv_world346.dll",把该 dll 拷贝到main.exe所在目录即可(详见下文运行小节)。
六、Step4:使用 CMake 编译
1. 进入 cpp 目录
cd D:\projects\PaddleDetection\deploy\cpp2. 使用 CMake 生成项目文件
编译参数的含义说明如下(带*表示仅在使用GPU 版本预测库时指定;其中 CUDA 库版本尽量对齐,使用 9.0、10.0 版本,不要使用 9.2、10.1 等版本的 CUDA 库):
| 参数名 | 含义 |
|---|---|
| *CUDA_LIB | CUDA 的库路径 |
| *CUDNN_LIB | CUDNN 的库路径 |
| OPENCV_DIR | OpenCV 的安装路径 |
| PADDLE_DIR | Paddle 预测库的路径 |
| PADDLE_LIB_NAME | Paddle 预测库名称(Windows 下固定为paddle_inference) |
注意:
- 如果编译环境为 CPU,需要下载 CPU 版预测库,并把
WITH_GPU的勾去掉; - 如果使用的是
openblas版本,请把WITH_MKL勾去掉; - 如无需使用关键点模型,可以把
WITH_KEYPOINT勾去掉; - Windows 环境下,
PADDLE_LIB_NAME需要设置为paddle_inference。
执行如下命令生成项目文件:
cmake . -G "Visual Studio 16 2019" -A x64 -T host=x64 -DWITH_GPU=ON -DWITH_MKL=ON -DCMAKE_BUILD_TYPE=Release -DCUDA_LIB=path_to_cuda_lib -DCUDNN_LIB=path_to_cudnn_lib -DPADDLE_DIR=path_to_paddle_lib -DPADDLE_LIB_NAME=paddle_inference -DOPENCV_DIR=path_to_opencv -DWITH_KEYPOINT=ON例如:
cmake . -G "Visual Studio 16 2019" -A x64 -T host=x64 -DWITH_GPU=ON -DWITH_MKL=ON -DCMAKE_BUILD_TYPE=Release -DCUDA_LIB=D:\projects\packages\cuda10_0\lib\x64 -DCUDNN_LIB=D:\projects\packages\cuda10_0\lib\x64 -DPADDLE_DIR=D:\projects\packages\paddle_inference -DPADDLE_LIB_NAME=paddle_inference -DOPENCV_DIR=D:\projects\packages\opencv3_4_6 -DWITH_KEYPOINT=ON源码视角:编译开关与平台差异
CMakeLists.txt 顶部声明了全部可配置开关:
option(WITH_MKL "Compile demo with MKL/OpenBlas support, defaultuseMKL." ON) option(WITH_GPU "Compile demo with GPU/CPU, default use CPU." ON) option(WITH_TENSORRT "Compile demo with TensorRT." OFF) option(WITH_KEYPOINT "Whether to Compile KeyPoint detector" OFF) option(WITH_MOT "Whether to Compile MOT detector" OFF)同时PADDLE_DIR、PADDLE_LIB_NAME、OPENCV_DIR、CUDA_LIB、CUDNN_LIB、TENSORRT_INC_DIR、TENSORRT_LIB_DIR均为 CACHE 变量,可通过-D传入。如果PADDLE_DIR或OPENCV_DIR未设置,cmake 会直接FATAL_ERROR终止;GPU 模式下未设置CUDA_LIB同样会报错终止(CMakeLists.txt)。
平台差异还体现在:
- 静态运行库:
safe_set_static_flag宏会把/MD替换为/MT(Release 下配合/bigobj /MT标志),避免运行库冲突; - MKL 依赖:启用
WITH_MKL时 Windows 链接mklml.lib与libiomp5md.lib;使用 OpenBLAS 时链接openblas.dll; - DLL 自动拷贝:Windows 编译完成后,CMake 的
POST_BUILD钩子会自动把mklml.dll、libiomp5md.dll、mkldnn.dll、paddle_inference.dll、onnxruntime.dll、paddle2onnx.dll等运行时依赖拷贝到可执行文件及release目录(CMakeLists.txt),保证生成物可直接运行。
3. 编译
用 Visual Studio 2019 打开cpp文件夹下的PaddleObjectDetector.sln,将编译模式设置为Release,点击生成→全部生成。
编译产物(可执行文件main.exe)默认输出在out\build\x64-Release目录下。
七、Step5:预测及可视化
打开cmd并切换到编译输出目录:
cd D:\projects\PaddleDetection\deploy\cpp\out\build\x64-Release可执行文件main即为样例预测程序。其命令行参数由 gflags 定义(见 src/main.cc 与 src/main_keypoint.cc),主要的参数如下:
| 参数 | 说明 | |
|---|---|---|
| --model_dir | 导出的检测预测模型所在路径(必填) | |
| --model_dir_keypoint | Option | 导出的关键点预测模型所在路径 |
| --image_file | 要预测的图片文件路径 | |
| --image_dir | 要预测的图片文件夹路径 | |
| --video_file | 要预测的视频文件路径 | |
| --camera_id | Option | 用来预测的摄像头 ID,默认为 -1(表示不使用摄像头预测) |
| --device | 运行时的设备,可选择CPU/GPU/XPU,默认为CPU | |
| --gpu_id | 指定进行推理的 GPU device id(默认值为 0) | |
| --run_mode | 使用 GPU 时默认为 paddle,可选(paddle/trt_fp32/trt_fp16/trt_int8) | |
| --batch_size | 检测模型预测时的 batch size,在指定image_dir时有效 | |
| --batch_size_keypoint | 关键点模型预测时的 batch size,默认为 8 | |
| --run_benchmark | 是否重复预测来进行 benchmark 测速 | |
| --output_dir | 输出图片所在的文件夹,默认为 output | |
| --use_mkldnn | CPU 预测中是否开启 MKLDNN 加速 | |
| --cpu_threads | 设置 cpu 线程数,默认为 1 | |
| --use_dark | 关键点模型输出预测是否使用 DarkPose 后处理,默认为 true |
此外,源码中还有几个文档表格之外、但在进阶调优中很实用的参数:
--threshold:检测置信度阈值,默认 0.5;--threshold_keypoint:关键点得分阈值,默认 0.5;--trt_min_shape/--trt_max_shape/--trt_opt_shape:TensorRT 动态形状的最小/最大/最优输入尺寸,默认分别为 1 / 1280 / 640(对应输入[batch, 3, h, w]中的 h、w);--trt_calib_mode:当模型由 TensorRT 离线量化校准产出时需置为 True;--use_gpu:已废弃(Deprecated),请改用--device。
注意:
- 优先级顺序:
camera_id>video_file>image_dir>image_file。该优先级在 main.cc 中体现:先判断视频/摄像头分支,再判断图片分支;同时image_dir使用 OpenCV 的cv::glob收集目录内全部图片,而单独指定image_file时batch_size必须为 1,否则程序会直接退出提示; - 如果提示找不到
opencv_world346.dll,把D:\projects\packages\opencv3_4_6\build\x64\vc14\bin文件夹下的opencv_world346.dll拷贝到main.exe文件夹下即可; --run_benchmark如果设置为 True,则需要安装依赖:pip install pynvml psutil GPUtil。
样例一:CPU 预测单张图片
# 不使用 GPU 测试图片 D:\images\test.jpeg .\main --model_dir=D:\models\yolov3_darknet --image_file=D:\images\test.jpeg图片文件的可视化预测结果会保存在当前目录下output.jpg文件中(实际按--output_dir指定目录输出,默认output)。
样例二:GPU 预测视频
# 使用 GPU 测试视频 D:\videos\test.mp4 .\main --model_dir=D:\models\yolov3_darknet --video_path=D:\videos\test.mp4 --device=GPU视频文件目前支持.mp4格式的预测,可视化预测结果会保存在当前目录下output.mp4文件中。源码中通过cv::VideoCapture读取视频、cv::VideoWriter(fourcc0x00000021,即 MP4V)逐帧写入检测结果(main.cc)。
样例三:检测模型 + 关键点模型联合预测
# 使用关键点模型与检测模型联合预测,使用 GPU 预测 # 检测模型检测到的人送入关键点模型进行关键点预测 .\main --model_dir=D:\models\yolov3_darknet --model_dir_keypoint=D:\models\hrnet_w32_256x192 --image_file=D:\images\test.jpeg --device=GPU该功能需在编译时开启WITH_KEYPOINT=ON。从 main_keypoint.cc 可以看到联合推理的完整链路:检测器先输出人体框 → 对每个class_id == 0(人)的检测框调用CropImg裁剪 → 按--batch_size_keypoint(默认 8)攒批送入关键点模型 → 关键点结果经VisualizeKptsResult绘制(关键点使用 20 色 colormap)。视频模式下还会使用PoseSmooth做关键点时序平滑,降低抖动。
源码视角:从命令行参数到推理引擎
main入口的核心逻辑(main.cc):
google::ParseCommandLineFlags解析命令行;- 校验
--model_dir与输入源(image_file/image_dir/video_file至少一个)非空; - 校验
--run_mode必须是paddle/trt_fp32/trt_fp16/trt_int8之一;--device必须是CPU/GPU/XPU之一; - 构造
PaddleDetection::ObjectDetector,其构造函数(object_detector.h)依次完成:解析模型目录下infer_cfg.yml(读取arch、Preprocess、label_list、use_dynamic_shape、min_subgraph_size、NMS、fpn_stride、mask等字段,见 config_parser.h)→ 初始化预处理器 → 调用LoadModel创建paddle_infer::Predictor。
模型加载时(object_detector.cc):
- 加载
model.pdmodel与model.pdiparams(即通过 tools/export_model.py 导出的推理模型,模型目录必须包含这两个文件与infer_cfg.yml); - GPU 模式:
EnableUseGpu(200, gpu_id)并开启 IR 优化;run_mode非 paddle 时调用EnableTensorRtEngine,并根据infer_cfg.yml中的use_dynamic_shape决定是否通过SetTRTDynamicShapeInfo设置image输入的动态形状(min/max/opt 取自--trt_min_shape等参数); - CPU 模式:
DisableGpu,若--use_mkldnn开启则EnableMKLDNN并设置 10 个 shape 的缓存容量,线程数取--cpu_threads; - XPU 模式:
EnableXpu(10 * 1024 * 1024); - 最后统一
DisableGlogInfo+EnableMemoryOptim(内存优化)后创建预测器。
预测时(Predict,object_detector.cc)会按 batch 依次完成:BGR→RGB 转换与预处理 → 组装image、im_shape、scale_factor输入张量 → 执行predictor_->Run()→ 依据infer_cfg.yml的arch/mask字段解析输出(检测框每项 6 维[class_id, score, xmin, ymin, xmax, ymax],旋转框每项 10 维,SOLOv2 走独立后处理)→ 通过VisualizeResult绘制类别、置信度与框(掩码模型还会叠加 mask 轮廓)。
八、性能测试(Benchmark)
Benchmark 详细内容请查看仓库根目录的 deploy/BENCHMARK_INFER.md。其中针对 Windows 平台(GTX 1080Ti)给出了各模型的paddle_inference、trt_fp32、trt_fp16平均单图推理耗时(单位 ms/image,Batch Size=1,去掉前 100 轮 warmup 后测试 100 轮),可用来与本地环境对比验证部署效果。
在本地进行测速时,给main加上--run_benchmark=true即可:源码会以固定 warmup/repeats(10 次)重复预测,并在结束时通过PrintBenchmarkLog打印preproce_time / inference_time / postprocess_time三段耗时(main.cc),便于定位耗时瓶颈。注意此时需要先安装pynvml psutil GPUtil依赖。
九、常见问题与排查建议
- 找不到
opencv_world346.dll:将 OpenCV 安装目录build\x64\vc14\bin下的 dll 拷贝到main.exe同级目录; PADDLE_LIB_NAME设置错误:Windows 下必须为paddle_inference,否则链接阶段找不到paddle_inference.lib;- 预测库与 TensorRT 版本不匹配:严格对照上文第三节的版本表,预测库、CUDA、cuDNN、TensorRT 必须配套;
- 运行时报
run_mode/device不合法:--run_mode只能是paddle/trt_fp32/trt_fp16/trt_int8,--device只能是CPU/GPU/XPU,程序启动时会校验并打印提示; - CPU 版 OpenBLAS 预测库:编译时去掉
WITH_MKL勾选,CMake 会自动切换为链接 OpenBLAS 并拷贝openblas.dll; - 模型导出:C++ 部署使用的模型需先用 tools/export_model.py 导出,得到
model.pdmodel、model.pdiparams与infer_cfg.yml,并将--model_dir指向该目录;导出细节可参考 deploy/EXPORT_MODEL.md。
至此,你已可以在 Windows + Visual Studio 2019 环境下完整编译并运行 PaddleDetection 的 C++ 检测/关键点推理程序,并具备结合 deploy/cpp 源码进行二次开发与性能调优的能力。
- 人工智能
- 深度学习
- 计算机视觉
【免费下载链接】PaddleDetection
Object Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.
相关推荐
PaddleDetection C++ 推理部署:Linux 平台编译指南与预测程序实战
PaddleDetection C++ 推理部署:Linux 平台编译指南与预测程序实战 本指南面向需要在 Linux 服务端将 PaddleDetection
人工智能深度学习计算机视觉OpenToonz Windows 平台构建实战:基于 Visual Studio 2019 与 Qt 5.x 的完整编译部署指南
OpenToonz Windows 平台构建实战:基于 Visual Studio 2019 与 Qt 5.x 的完整编译部署指南 导读 本文以 OpenToo
桌面应用图形学PaddleDetection C++端预测部署指南:跨平台编译、模型集成与推理加速
PaddleDetection C++端预测部署指南:跨平台编译、模型集成与推理加速 PaddleDetection 在 deploy/cpp 目录下提供了一套
人工智能深度学习计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考