diff --git a/deploy/pptracking/CMakeLists.txt b/deploy/pptracking/cpp/CMakeLists.txt similarity index 100% rename from deploy/pptracking/CMakeLists.txt rename to deploy/pptracking/cpp/CMakeLists.txt diff --git a/deploy/pptracking/cpp/README.md b/deploy/pptracking/cpp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..62e80b6bd74d678ac658b6f914ef722e7bd575f6 --- /dev/null +++ b/deploy/pptracking/cpp/README.md @@ -0,0 +1,144 @@ +# C++端预测部署 + +在PaddlePaddle中预测引擎和训练引擎底层有着不同的优化方法, 预测引擎使用了AnalysisPredictor,专门针对推理进行了优化,该引擎可以对模型进行多项图优化,减少不必要的内存拷贝。如果用户在部署已训练模型的过程中对性能有较高的要求,我们提供了独立于PaddleDetection的预测脚本,方便用户直接集成部署。当前C++部署支持基于Fairmot的单镜头类别预测部署,并支持人流量统计、出入口计数功能。 + +主要包含三个步骤: + +- 准备环境 +- 导出预测模型 +- C++预测 + +## 一、准备环境 + +环境要求: + +- GCC 8.2 +- CUDA 10.1/10.2/11.1; CUDNN 7.6/8.1 +- CMake 3.0+ +- TensorRT 6/7 + +NVIDIA Jetson用户请参考[Jetson平台编译指南](../../cpp/Jetson_build.md#jetson环境搭建)完成JetPack安装 + +### 1. 下载代码 + +``` +git clone https://github.com/PaddlePaddle/PaddleDetection.git +# C++部署代码与其他目录代码独立 +cd deploy/pptracking/cpp +``` + +### 2. 下载或编译PaddlePaddle C++预测库 + +请根据环境选择适当的预测库进行下载,参考[C++预测库下载列表](https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html) + +下载并解压后`./paddle_inference`目录包含内容为: + +``` +paddle_inference +├── paddle # paddle核心库和头文件 +| +├── third_party # 第三方依赖库和头文件 +| +└── version.txt # 版本和编译信息 +``` + +**注意:** 如果用户环境与官网提供环境不一致(如cuda 、cudnn、tensorrt版本不一致等),或对飞桨源代码有修改需求,或希望进行定制化构建,可参考[文档](https://paddleinference.paddlepaddle.org.cn/user_guides/source_compile.html)自行源码编译预测库。 + +### 3. 编译 + +编译`cmake`的命令在`scripts/build.sh`中,请根据实际情况修改主要参数,其主要内容说明如下: + +``` +# 是否使用GPU(即是否使用 CUDA) +WITH_GPU=ON + +# 是否使用MKL or openblas,TX2需要设置为OFF +WITH_MKL=OFF + +# 是否集成 TensorRT(仅WITH_GPU=ON 有效) +WITH_TENSORRT=ON + +# TensorRT 的include路径 +TENSORRT_INC_DIR=/path/to/TensorRT/include + +# TensorRT 的lib路径 +TENSORRT_LIB_DIR=/path/to/TensorRT/lib + +# Paddle 预测库路径 +PADDLE_DIR=/path/to/paddle_inference/ + +# Paddle 预测库名称 +PADDLE_LIB_NAME=libpaddle_inference + +# CUDA 的 lib 路径 +CUDA_LIB=/path/to/cuda/lib + +# CUDNN 的 lib 路径 +CUDNN_LIB=/path/to/cudnn/lib + +# OPENCV路径 +OPENCV_DIR=/path/to/opencv +``` + +修改脚本设置好主要参数后,执行```build.sh```脚本: + +``` +sh ./scripts/build.sh +``` + +**注意:** + +1. `TX2`平台的`CUDA`、`CUDNN`需要通过`JetPack`安装。 +2. 已提供linux和tx2平台的opencv下载方式,其他环境请自行安装[opencv](https://opencv.org/) + +## 二、导出预测模型 + +将训练保存的权重导出为预测库需要的模型格式,使用PaddleDetection下的```tools/export_model.py```导出模型 + +``` +python tools/export_model.py -c configs/mot/fairmot/fairmot_hrnetv2_w18_dlafpn_30e_576x320.yml -o weights=https://paddledet.bj.bcebos.com/models/mot/fairmot_hrnetv2_w18_dlafpn_30e_576x320.pdparams +``` + +预测模型会默认导出到```output_inference/fairmot_hrnetv2_w18_dlafpn_30e_576x320```目录下,包括```infer_cfg.yml```, ```model.pdiparams```, ```model.pdiparams.info```, ```model.pdmodel``` + +导出模型也可以通过[预测模型列表]()直接下载使用 + +## 三、C++预测 + +完成以上步骤后,可以通过```build/main```进行预测,参数列表如下: + +| 参数 | 说明 | +| ---- | ---- | +| --track_model_dir | 导出的跟踪预测模型所在路径 | +| --video_file | 要预测的视频文件路径 | +| --device | 运行时的设备,可选择`CPU/GPU/XPU`,默认为`CPU`| +| --gpu_id | 指定进行推理的GPU device id(默认值为0)| +| --run_mode | 使用GPU时,默认为fluid, 可选(fluid/trt_fp32/trt_fp16/trt_int8)| +| --output_dir | 输出图片所在的文件夹, 默认为output | +| --use_mkldnn | CPU预测中是否开启MKLDNN加速 | +| --cpu_threads | 设置cpu线程数,默认为1 | +| --do_entrance_counting | 是否进行出入口流量统计,默认为否 | +| --save_result | 是否保存跟踪结果 | + +样例一: + +```shell +# 使用CPU测试视频 `test.mp4` , 模型和测试视频均移至`build`目录下 + +./main --track_model_dir=./fairmot_hrnetv2_w18_dlafpn_30e_576x320 --video_file=test.mp4 + +# 视频可视化预测结果默认保存在当前目录下output/test.mp4文件中 +``` + + +样例二: + +```shell +# 使用GPU测试视频 `test.mp4` , 模型和测试视频均移至`build`目录下,实现出入口计数功能,并保存跟踪结果 + +./main -video_file=test.mp4 -track_model_dir=./fairmot_dla34_30e_1088x608/ --device=gpu --do_entrance_counting=True --save_result=True + +# 视频可视化预测结果默认保存在当前目录下`output/test.mp4`中 +# 跟踪结果保存在`output/mot_output.txt`中 +# 计数结果保存在`output/flow_statistic.txt`中 +``` diff --git a/deploy/pptracking/cmake/yaml-cpp.cmake b/deploy/pptracking/cpp/cmake/yaml-cpp.cmake similarity index 100% rename from deploy/pptracking/cmake/yaml-cpp.cmake rename to deploy/pptracking/cpp/cmake/yaml-cpp.cmake diff --git a/deploy/pptracking/include/config_parser.h b/deploy/pptracking/cpp/include/config_parser.h similarity index 100% rename from deploy/pptracking/include/config_parser.h rename to deploy/pptracking/cpp/include/config_parser.h diff --git a/deploy/pptracking/include/jde_predictor.h b/deploy/pptracking/cpp/include/jde_predictor.h similarity index 100% rename from deploy/pptracking/include/jde_predictor.h rename to deploy/pptracking/cpp/include/jde_predictor.h diff --git a/deploy/pptracking/include/lapjv.h b/deploy/pptracking/cpp/include/lapjv.h similarity index 92% rename from deploy/pptracking/include/lapjv.h rename to deploy/pptracking/cpp/include/lapjv.h index 5873bfb5b6cf8f31617a37eb1ca388a7505da0c6..ffaa010c00525e9babac1bfe276189187dc840f8 100644 --- a/deploy/pptracking/include/lapjv.h +++ b/deploy/pptracking/cpp/include/lapjv.h @@ -17,8 +17,8 @@ // Ths copyright of gatagat/lap is as follows: // MIT License -#ifndef DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_ -#define DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_ +#ifndef DEPLOY_PPTRACKING_CPP_INCLUDE_LAPJV_H_ +#define DEPLOY_PPTRACKING_CPP_INCLUDE_LAPJV_H_ #define LARGE 1000000 #if !defined TRUE @@ -61,4 +61,4 @@ int lapjv_internal(const cv::Mat &cost, } // namespace PaddleDetection -#endif // DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_ +#endif // DEPLOY_PPTRACKING_CPP_INCLUDE_LAPJV_H_ diff --git a/deploy/pptracking/include/pipeline.h b/deploy/pptracking/cpp/include/pipeline.h similarity index 96% rename from deploy/pptracking/include/pipeline.h rename to deploy/pptracking/cpp/include/pipeline.h index 442af09aeda8bb6c686603f07ef2b67ad5679b7c..f3e6799b132991907f01acbdfd6803578577182d 100644 --- a/deploy/pptracking/include/pipeline.h +++ b/deploy/pptracking/cpp/include/pipeline.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_ -#define DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_ +#ifndef DEPLOY_PPTRACKING_CPP_INCLUDE_PIPELINE_H_ +#define DEPLOY_PPTRACKING_CPP_INCLUDE_PIPELINE_H_ #include @@ -139,4 +139,4 @@ class Pipeline { } // namespace PaddleDetection -#endif // DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_ +#endif // DEPLOY_PPTRACKING_CPP_INCLUDE_PIPELINE_H_ diff --git a/deploy/pptracking/include/postprocess.h b/deploy/pptracking/cpp/include/postprocess.h similarity index 99% rename from deploy/pptracking/include/postprocess.h rename to deploy/pptracking/cpp/include/postprocess.h index 64d69a9d96392379d2182f85f0d300c0a701cfd5..41b10960351d69a0e3388adfc763c11f162a0bbd 100644 --- a/deploy/pptracking/include/postprocess.h +++ b/deploy/pptracking/cpp/include/postprocess.h @@ -18,10 +18,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -54,7 +54,6 @@ void FlowStatistic(const MOTResult& results, std::map>* prev_center, std::vector* records); - // Save Tracking Results void SaveMOTResult(const MOTResult& results, const int frame_id, diff --git a/deploy/pptracking/cpp/include/predictor.h b/deploy/pptracking/cpp/include/predictor.h new file mode 100644 index 0000000000000000000000000000000000000000..f4c4168725ae1e9b0575bd3af4aec662a7f35c5a --- /dev/null +++ b/deploy/pptracking/cpp/include/predictor.h @@ -0,0 +1,99 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "paddle_inference_api.h" // NOLINT + +#include "include/config_parser.h" +#include "include/jde_predictor.h" +#include "include/preprocess_op.h" +#include "include/sde_predictor.h" + +using namespace paddle_infer; // NOLINT + +namespace PaddleDetection { + +class Predictor { + public: + explicit Predictor(const std::string& device = "CPU", + const std::string& track_model_dir = "", + const std::string& det_model_dir = "", + const std::string& reid_model_dir = "", + const double threshold = -1., + const std::string& run_mode = "fluid", + const int gpu_id = 0, + const bool use_mkldnn = false, + const int cpu_threads = 1, + bool trt_calib_mode = false, + const int min_box_area = 200) { + if (track_model_dir.empty() && det_model_dir.empty()) { + throw "Predictor must receive track_model or det_model!"; + } + + if (!track_model_dir.empty() && !det_model_dir.empty()) { + throw "Predictor only receive one of track_model or det_model!"; + } + + if (!track_model_dir.empty()) { + jde_sct_ = + std::make_shared(device, + track_model_dir, + threshold, + run_mode, + gpu_id, + use_mkldnn, + cpu_threads, + trt_calib_mode, + min_box_area); + use_jde_ = true; + } + if (!det_model_dir.empty()) { + sde_sct_ = std::make_shared(device, + det_model_dir, + reid_model_dir, + threshold, + run_mode, + gpu_id, + use_mkldnn, + cpu_threads, + trt_calib_mode, + min_box_area); + use_jde_ = false; + } + } + + // Run predictor + void Predict(const std::vector imgs, + const double threshold = 0.5, + MOTResult* result = nullptr, + std::vector* times = nullptr); + + private: + std::shared_ptr jde_sct_; + std::shared_ptr sde_sct_; + bool use_jde_ = true; +}; + +} // namespace PaddleDetection diff --git a/deploy/pptracking/include/preprocess_op.h b/deploy/pptracking/cpp/include/preprocess_op.h similarity index 100% rename from deploy/pptracking/include/preprocess_op.h rename to deploy/pptracking/cpp/include/preprocess_op.h diff --git a/deploy/pptracking/include/sde_predictor.h b/deploy/pptracking/cpp/include/sde_predictor.h similarity index 100% rename from deploy/pptracking/include/sde_predictor.h rename to deploy/pptracking/cpp/include/sde_predictor.h diff --git a/deploy/pptracking/include/tracker.h b/deploy/pptracking/cpp/include/tracker.h similarity index 100% rename from deploy/pptracking/include/tracker.h rename to deploy/pptracking/cpp/include/tracker.h diff --git a/deploy/pptracking/include/trajectory.h b/deploy/pptracking/cpp/include/trajectory.h similarity index 100% rename from deploy/pptracking/include/trajectory.h rename to deploy/pptracking/cpp/include/trajectory.h diff --git a/deploy/pptracking/include/utils.h b/deploy/pptracking/cpp/include/utils.h similarity index 100% rename from deploy/pptracking/include/utils.h rename to deploy/pptracking/cpp/include/utils.h diff --git a/deploy/pptracking/scripts/build.sh b/deploy/pptracking/cpp/scripts/build.sh similarity index 100% rename from deploy/pptracking/scripts/build.sh rename to deploy/pptracking/cpp/scripts/build.sh diff --git a/deploy/pptracking/src/jde_predictor.cc b/deploy/pptracking/cpp/src/jde_predictor.cc similarity index 100% rename from deploy/pptracking/src/jde_predictor.cc rename to deploy/pptracking/cpp/src/jde_predictor.cc diff --git a/deploy/pptracking/src/lapjv.cpp b/deploy/pptracking/cpp/src/lapjv.cpp similarity index 100% rename from deploy/pptracking/src/lapjv.cpp rename to deploy/pptracking/cpp/src/lapjv.cpp diff --git a/deploy/pptracking/src/main.cc b/deploy/pptracking/cpp/src/main.cc similarity index 100% rename from deploy/pptracking/src/main.cc rename to deploy/pptracking/cpp/src/main.cc diff --git a/deploy/pptracking/src/pipeline.cc b/deploy/pptracking/cpp/src/pipeline.cc similarity index 100% rename from deploy/pptracking/src/pipeline.cc rename to deploy/pptracking/cpp/src/pipeline.cc diff --git a/deploy/pptracking/src/postprocess.cc b/deploy/pptracking/cpp/src/postprocess.cc similarity index 90% rename from deploy/pptracking/src/postprocess.cc rename to deploy/pptracking/cpp/src/postprocess.cc index 2c85b1a4fa81c538eca79bc52875932685b0a3b4..39a752aeb179bdf44da8c1b05376dab4618ad73a 100644 --- a/deploy/pptracking/src/postprocess.cc +++ b/deploy/pptracking/cpp/src/postprocess.cc @@ -105,34 +105,34 @@ void FlowStatistic(const MOTResult& results, const int secs_interval, const bool do_entrance_counting, const int video_fps, - const Rect entrance, + const Rect entrance, std::set* id_set, - std::set* interval_id_set, - std::vector* in_id_list, + std::set* interval_id_set, + std::vector* in_id_list, std::vector* out_id_list, std::map>* prev_center, std::vector* records) { - if (frame_id == 0) - interval_id_set->clear(); - + if (frame_id == 0) interval_id_set->clear(); + if (do_entrance_counting) { - // Count in and out number: + // Count in and out number: // Use horizontal center line as the entrance just for simplification. - // If a person located in the above the horizontal center line + // If a person located in the above the horizontal center line // at the previous frame and is in the below the line at the current frame, // the in number is increased by one. - // If a person was in the below the horizontal center line - // at the previous frame and locates in the below the line at the current frame, + // If a person was in the below the horizontal center line + // at the previous frame and locates in the below the line at the current + // frame, // the out number is increased by one. - // TODO: if the entrance is not the horizontal center line, + // TODO(qianhui): if the entrance is not the horizontal center line, // the counting method should be optimized. - - float entrance_y = entrance.top; + + float entrance_y = entrance.top; for (const auto& result : results) { float center_x = (result.rects.left + result.rects.right) / 2; float center_y = (result.rects.top + result.rects.bottom) / 2; int ids = result.ids; - std::map>::iterator iter; + std::map>::iterator iter; iter = prev_center->find(ids); if (iter != prev_center->end()) { if (iter->second[1] <= entrance_y && center_y > entrance_y) { @@ -145,7 +145,7 @@ void FlowStatistic(const MOTResult& results, (*prev_center)[ids][1] = center_y; } else { prev_center->insert( - std::pair>(ids, {center_x, center_y})); + std::pair>(ids, {center_x, center_y})); } } } @@ -157,8 +157,7 @@ void FlowStatistic(const MOTResult& results, } std::ostringstream os; - os << "Frame id: " << frame_id - << ", Total count: " << id_set->size(); + os << "Frame id: " << frame_id << ", Total count: " << id_set->size(); if (do_entrance_counting) { os << ", In count: " << in_id_list->size() << ", Out count: " << out_id_list->size(); diff --git a/deploy/pptracking/src/predictor.cc b/deploy/pptracking/cpp/src/predictor.cc similarity index 84% rename from deploy/pptracking/src/predictor.cc rename to deploy/pptracking/cpp/src/predictor.cc index 6d1d818392d85d774bd5da6710ef83cae57f509f..ea479f3ab049143147a938bb575f8995dee55c95 100644 --- a/deploy/pptracking/src/predictor.cc +++ b/deploy/pptracking/cpp/src/predictor.cc @@ -13,19 +13,18 @@ // limitations under the License. #include // for setprecision -#include #include +#include #include "include/predictor.h" - -using namespace paddle_infer; +using namespace paddle_infer; // NOLINT namespace PaddleDetection { void Predictor::Predict(const std::vector imgs, - const double threshold, - MOTResult* result, - std::vector* times) { + const double threshold, + MOTResult* result, + std::vector* times) { if (use_jde_) { jde_sct_->Predict(imgs, threshold, result, times); } else { diff --git a/deploy/pptracking/src/preprocess_op.cc b/deploy/pptracking/cpp/src/preprocess_op.cc similarity index 100% rename from deploy/pptracking/src/preprocess_op.cc rename to deploy/pptracking/cpp/src/preprocess_op.cc diff --git a/deploy/pptracking/src/sde_predictor.cc b/deploy/pptracking/cpp/src/sde_predictor.cc similarity index 100% rename from deploy/pptracking/src/sde_predictor.cc rename to deploy/pptracking/cpp/src/sde_predictor.cc diff --git a/deploy/pptracking/src/tracker.cc b/deploy/pptracking/cpp/src/tracker.cc similarity index 100% rename from deploy/pptracking/src/tracker.cc rename to deploy/pptracking/cpp/src/tracker.cc diff --git a/deploy/pptracking/src/trajectory.cc b/deploy/pptracking/cpp/src/trajectory.cc similarity index 100% rename from deploy/pptracking/src/trajectory.cc rename to deploy/pptracking/cpp/src/trajectory.cc diff --git a/deploy/pptracking/include/predictor.h b/deploy/pptracking/include/predictor.h deleted file mode 100644 index 729be4061d284e84d67ace1b2109730cc1ac6ea6..0000000000000000000000000000000000000000 --- a/deploy/pptracking/include/predictor.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "paddle_inference_api.h" // NOLINT - -#include "include/preprocess_op.h" -#include "include/config_parser.h" -#include "include/jde_predictor.h" -#include "include/sde_predictor.h" - - -using namespace paddle_infer; - -namespace PaddleDetection { - -class Predictor { - public: - explicit Predictor(const std::string& device="CPU", - const std::string& track_model_dir="", - const std::string& det_model_dir="", - const std::string& reid_model_dir="", - const double threshold=-1., - const std::string& run_mode="fluid", - const int gpu_id=0, - const bool use_mkldnn=false, - const int cpu_threads=1, - bool trt_calib_mode=false, - const int min_box_area=200) { - - if (track_model_dir.empty() && det_model_dir.empty()) { - throw "Predictor must receive track_model or det_model!"; - } - - if (!track_model_dir.empty()) { - jde_sct_ = std::make_shared(device, track_model_dir, threshold, run_mode, gpu_id, use_mkldnn, cpu_threads, trt_calib_mode, min_box_area); - use_jde_ = true; - } - if (!det_model_dir.empty()) { - sde_sct_ = std::make_shared(device, det_model_dir, reid_model_dir, threshold, run_mode, gpu_id, use_mkldnn, cpu_threads, trt_calib_mode, min_box_area); - use_jde_ = false; - } - } - - // Run predictor - void Predict(const std::vector imgs, - const double threshold = 0.5, - MOTResult* result = nullptr, - std::vector* times = nullptr); - - private: - std::shared_ptr jde_sct_; - std::shared_ptr sde_sct_; - bool use_jde_ = true; -}; - -} // namespace PaddleDetection diff --git a/deploy/pptracking/src/base_predictor.cc b/deploy/pptracking/src/base_predictor.cc deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000