提交 75d4c0f6 编写于 作者: J Jack Zhou 提交者: qingqing01

Update CMakeLists.txt to adapt to the directory structure of win v1.6 inference lib (#20)

2. change code style
3. add error messages: display detail about input errors and config file errors
上级 df6cfd8d
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(cpp_inference_demo CXX C) project(cpp_inference_demo CXX C)
message("cmake module path: ${CMAKE_MODULE_PATH}")
message("cmake root path: ${CMAKE_ROOT}")
option(WITH_MKL "Compile demo with MKL/OpenBlas support,defaultuseMKL." ON) 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_GPU "Compile demo with GPU/CPU, default use CPU." ON)
option(WITH_STATIC_LIB "Compile demo with static/shared library, default use static." ON) option(WITH_STATIC_LIB "Compile demo with static/shared library, default use static." ON)
...@@ -70,6 +69,7 @@ link_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/yaml-cpp/lib") ...@@ -70,6 +69,7 @@ link_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/yaml-cpp/lib")
link_directories("${CMAKE_CURRENT_BINARY_DIR}") link_directories("${CMAKE_CURRENT_BINARY_DIR}")
if (WIN32) if (WIN32)
include_directories("${PADDLE_DIR}/paddle/fluid/inference") include_directories("${PADDLE_DIR}/paddle/fluid/inference")
include_directories("${PADDLE_DIR}/paddle/include")
link_directories("${PADDLE_DIR}/paddle/fluid/inference") link_directories("${PADDLE_DIR}/paddle/fluid/inference")
include_directories("${OPENCV_DIR}/build/include") include_directories("${OPENCV_DIR}/build/include")
include_directories("${OPENCV_DIR}/opencv/build/include") include_directories("${OPENCV_DIR}/opencv/build/include")
...@@ -134,6 +134,7 @@ if(WITH_MKL) ...@@ -134,6 +134,7 @@ if(WITH_MKL)
else () else ()
set(MATH_LIB ${PADDLE_DIR}/third_party/install/mklml/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX} set(MATH_LIB ${PADDLE_DIR}/third_party/install/mklml/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX}
${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5${CMAKE_SHARED_LIBRARY_SUFFIX}) ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5${CMAKE_SHARED_LIBRARY_SUFFIX})
execute_process(COMMAND cp -r ${PADDLE_DIR}/third_party/install/mklml/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX} /usr/lib)
endif () endif ()
set(MKLDNN_PATH "${PADDLE_DIR}/third_party/install/mkldnn") set(MKLDNN_PATH "${PADDLE_DIR}/third_party/install/mkldnn")
if(EXISTS ${MKLDNN_PATH}) if(EXISTS ${MKLDNN_PATH})
...@@ -148,22 +149,22 @@ else() ...@@ -148,22 +149,22 @@ else()
set(MATH_LIB ${PADDLE_DIR}/third_party/install/openblas/lib/libopenblas${CMAKE_STATIC_LIBRARY_SUFFIX}) set(MATH_LIB ${PADDLE_DIR}/third_party/install/openblas/lib/libopenblas${CMAKE_STATIC_LIBRARY_SUFFIX})
endif() endif()
if(WIN32)
if(EXISTS "${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(DEPS
${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
else()
set(DEPS
${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
endif()
endif()
if(WITH_STATIC_LIB) if(WITH_STATIC_LIB)
if (WIN32)
set(DEPS
${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
else ()
set(DEPS set(DEPS
${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX}) ${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
endif()
else() else()
if (WIN32)
set(DEPS
${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
else ()
set(DEPS set(DEPS
${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_SHARED_LIBRARY_SUFFIX}) ${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
endif() endif()
if (NOT WIN32) if (NOT WIN32)
...@@ -242,8 +243,6 @@ if (NOT WIN32) ...@@ -242,8 +243,6 @@ if (NOT WIN32)
set(DEPS ${DEPS} ${OPENCV_3RD_LIB_DIR}/libippicv${CMAKE_STATIC_LIBRARY_SUFFIX}) set(DEPS ${DEPS} ${OPENCV_3RD_LIB_DIR}/libippicv${CMAKE_STATIC_LIBRARY_SUFFIX})
endif() endif()
endif() endif()
# message(${CMAKE_CXX_FLAGS})
# set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
SET(PADDLESEG_INFERENCE_SRCS preprocessor/preprocessor.cpp SET(PADDLESEG_INFERENCE_SRCS preprocessor/preprocessor.cpp
preprocessor/preprocessor_detection.cpp predictor/detection_predictor.cpp preprocessor/preprocessor_detection.cpp predictor/detection_predictor.cpp
...@@ -265,7 +264,7 @@ if (WIN32) ...@@ -265,7 +264,7 @@ if (WIN32)
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./mkldnn.dll COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./mkldnn.dll
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/mklml.dll ./release/mklml.dll COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/mklml.dll ./release/mklml.dll
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5md.dll ./release/libiomp5md.dll COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5md.dll ./release/libiomp5md.dll
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./mkldnn.dll COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./release/mkldnn.dll
) )
endif() endif()
......
...@@ -65,7 +65,7 @@ deploy ...@@ -65,7 +65,7 @@ deploy
完成编译后,便生成了需要的可执行文件和链接库。这里以我们基于`faster rcnn`检测模型为例,介绍部署图像检测模型的通用流程。 完成编译后,便生成了需要的可执行文件和链接库。这里以我们基于`faster rcnn`检测模型为例,介绍部署图像检测模型的通用流程。
### 1. 下载模型文件 ### 4.1. 下载模型文件
我们提供faster rcnn,faster rcnn+fpn模型用于预测coco17数据集,可在以下链接下载:[faster rcnn示例模型下载地址](https://paddleseg.bj.bcebos.com/inference/faster_rcnn_pp50.zip) 我们提供faster rcnn,faster rcnn+fpn模型用于预测coco17数据集,可在以下链接下载:[faster rcnn示例模型下载地址](https://paddleseg.bj.bcebos.com/inference/faster_rcnn_pp50.zip)
[faster rcnn + fpn示例模型下载地址](https://paddleseg.bj.bcebos.com/inference/faster_rcnn_pp50_fpn.zip) [faster rcnn + fpn示例模型下载地址](https://paddleseg.bj.bcebos.com/inference/faster_rcnn_pp50_fpn.zip)
...@@ -83,7 +83,7 @@ faster_rcnn_pp50/ ...@@ -83,7 +83,7 @@ faster_rcnn_pp50/
**假设**`Linux`上对应的路径则为`/root/projects/models/faster_rcnn_pp50/` **假设**`Linux`上对应的路径则为`/root/projects/models/faster_rcnn_pp50/`
### 2. 修改配置 ### 4.2. 修改配置
`inference`源代码(即本目录)的`conf`目录下提供了示例基于faster rcnn的配置文件`detection_rcnn.yaml`, 相关的字段含义和说明如下: `inference`源代码(即本目录)的`conf`目录下提供了示例基于faster rcnn的配置文件`detection_rcnn.yaml`, 相关的字段含义和说明如下:
...@@ -118,7 +118,7 @@ DEPLOY: ...@@ -118,7 +118,7 @@ DEPLOY:
# 预测模式,支持 NATIVE 和 ANALYSIS # 预测模式,支持 NATIVE 和 ANALYSIS
PREDICTOR_MODE: "ANALYSIS" PREDICTOR_MODE: "ANALYSIS"
# 每次预测的 batch_size # 每次预测的 batch_size
BATCH_SIZE : 3 BATCH_SIZE : 3
# 长边伸缩的最大长度,-1代表无限制。 # 长边伸缩的最大长度,-1代表无限制。
RESIZE_MAX_SIZE: 1333 RESIZE_MAX_SIZE: 1333
# 输入的tensor数量。 # 输入的tensor数量。
...@@ -127,7 +127,9 @@ DEPLOY: ...@@ -127,7 +127,9 @@ DEPLOY:
``` ```
修改字段`MODEL_PATH`的值为你在**上一步**下载并解压的模型文件所放置的目录即可。更多配置文件字段介绍,请参考文档[预测部署方案配置文件说明](./docs/configuration.md) 修改字段`MODEL_PATH`的值为你在**上一步**下载并解压的模型文件所放置的目录即可。更多配置文件字段介绍,请参考文档[预测部署方案配置文件说明](./docs/configuration.md)
### 3. 执行预测 **注意**在使用CPU版本预测库时,`USE_GPU`的值必须设为0,否则无法正常预测。
### 4.3. 执行预测
在终端中切换到生成的可执行文件所在目录为当前目录(Windows系统为`cmd`)。 在终端中切换到生成的可执行文件所在目录为当前目录(Windows系统为`cmd`)。
...@@ -155,7 +157,7 @@ DEPLOY: ...@@ -155,7 +157,7 @@ DEPLOY:
运行可视化脚本时,只需输入命令行参数图片路径、检测结果pb文件路径、目标框阈值以及类别-标签映射文件路径即可得到可视化的图片`X.png` (tools目录下提供coco17的类别标签映射文件coco17.json)。 运行可视化脚本时,只需输入命令行参数图片路径、检测结果pb文件路径、目标框阈值以及类别-标签映射文件路径即可得到可视化的图片`X.png` (tools目录下提供coco17的类别标签映射文件coco17.json)。
```bash ```bash
python vis.py --img_path=../build/images/detection_rcnn/000000087038.jpg --img_result_path=../build/images/detection_rcnn/000000087038.jpg.pb --threshold=0.1 --c2l_path=coco17.json python vis.py --img_path=../build/images/detection_rcnn/000000087038.jpg --img_result_path=../build/images/detection_rcnn/000000087038.jpg.pb --threshold=0.1 --c2l_path=coco17.json
``` ```
...@@ -168,3 +170,4 @@ python vis.py --img_path=../build/images/detection_rcnn/000000087038.jpg --img_r ...@@ -168,3 +170,4 @@ python vis.py --img_path=../build/images/detection_rcnn/000000087038.jpg --img_r
```检测结果图:``` ```检测结果图:```
![检测结果](./demo_images/000000087038.jpg.png) ![检测结果](./demo_images/000000087038.jpg.png)
...@@ -13,6 +13,6 @@ DEPLOY: ...@@ -13,6 +13,6 @@ DEPLOY:
CHANNELS : 3 CHANNELS : 3
PRE_PROCESSOR: "DetectionPreProcessor" PRE_PROCESSOR: "DetectionPreProcessor"
PREDICTOR_MODE: "ANALYSIS" PREDICTOR_MODE: "ANALYSIS"
BATCH_SIZE : 3 BATCH_SIZE : 1
RESIZE_MAX_SIZE: 1333 RESIZE_MAX_SIZE: 1333
FEEDS_SIZE: 3 FEEDS_SIZE: 3
...@@ -23,18 +23,24 @@ int main(int argc, char** argv) { ...@@ -23,18 +23,24 @@ int main(int argc, char** argv) {
// 0. parse args // 0. parse args
google::ParseCommandLineFlags(&argc, &argv, true); google::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_conf.empty() || FLAGS_input_dir.empty()) { if (FLAGS_conf.empty() || FLAGS_input_dir.empty()) {
std::cout << "Usage: ./predictor --conf=/config/path/to/your/model --input_dir=/directory/of/your/input/images"; std::cout << "Usage: ./predictor --conf=/config/path/to/your/model "
<< "--input_dir=/directory/of/your/input/images" << std::endl;
return -1; return -1;
} }
// 1. create a predictor and init it with conf // 1. create a predictor and init it with conf
PaddleSolution::DetectionPredictor predictor; PaddleSolution::DetectionPredictor predictor;
if (predictor.init(FLAGS_conf) != 0) { if (predictor.init(FLAGS_conf) != 0) {
#ifdef _WIN32
std::cerr << "Fail to init predictor" << std::endl;
#else
LOG(FATAL) << "Fail to init predictor"; LOG(FATAL) << "Fail to init predictor";
#endif
return -1; return -1;
} }
// 2. get all the images with extension '.jpeg' at input_dir // 2. get all the images with extension '.jpeg' at input_dir
auto imgs = PaddleSolution::utils::get_directory_images(FLAGS_input_dir, ".jpeg|.jpg|.JPEG|.JPG|.bmp|.BMP|.png|.PNG"); auto imgs = PaddleSolution::utils::get_directory_images(FLAGS_input_dir,
".jpeg|.jpg|.JPEG|.JPG|.bmp|.BMP|.png|.PNG");
// 3. predict // 3. predict
predictor.predict(imgs); predictor.predict(imgs);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
```yaml ```yaml
# 预测部署时所有配置字段需在DEPLOY字段下 # 预测部署时所有配置字段需在DEPLOY字段下
DEPLOY: DEPLOY:
# 类型:required int # 类型:required int
# 含义:是否使用GPU预测。 0:不使用 1:使用 # 含义:是否使用GPU预测。 0:不使用 1:使用
USE_GPU: 1 USE_GPU: 1
...@@ -70,6 +70,6 @@ DEPLOY: ...@@ -70,6 +70,6 @@ DEPLOY:
# 含义: 输入张量的个数。大部分模型不需要设置。 默认值为1. # 含义: 输入张量的个数。大部分模型不需要设置。 默认值为1.
FEEDS_SIZE: 2 FEEDS_SIZE: 2
# 类型: optional int # 类型: optional int
# 含义: 将图像的边变为该字段的值的整数倍。默认值为1。 # 含义: 将图像的边变为该字段的值的整数倍。在使用fpn模型时需要设为32。默认值为1。
COARSEST_STRIDE: 32 COARSEST_STRIDE: 32
``` ```
\ No newline at end of file
...@@ -5,22 +5,30 @@ ...@@ -5,22 +5,30 @@
## 前置条件 ## 前置条件
* G++ 4.8.2 ~ 4.9.4 * G++ 4.8.2 ~ 4.9.4
* CUDA 8.0/ CUDA 9.0 * CUDA 9.0 / CUDA 10.0, cudnn 7+ (仅在使用GPU版本的预测库时需要)
* CMake 3.0+ * CMake 3.0+
请确保系统已经安装好上述基本软件,**下面所有示例以工作目录为 `/root/projects/`演示** 请确保系统已经安装好上述基本软件,**下面所有示例以工作目录为 `/root/projects/`演示**
### Step1: 下载代码 ### Step1: 下载代码
1. `mkdir -p /root/projects/paddle_models && cd /root/projects/paddle_models` 1. `git clone https://github.com/PaddlePaddle/PaddleDetection.git`
2. `git clone https://github.com/PaddlePaddle/models.git`
`C++`预测代码在`/root/projects/paddle_models/models/PaddleCV/PaddleDetection/inference` 目录,该目录不依赖任何`PaddleDetection`下其他目录。 `C++`预测代码在`/root/projects/PaddleDetection/inference` 目录,该目录不依赖任何`PaddleDetection`下其他目录。
### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference ### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference
目前仅支持`CUDA 8``CUDA 9`,请点击 [PaddlePaddle预测库下载地址](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/advanced_usage/deploy/inference/build_and_install_lib_cn.html)下载对应的版本(develop版本)。 PaddlePaddle C++ 预测库主要分为CPU版本和GPU版本。其中,针对不同的CUDA版本,GPU版本预测库又分为两个版本预测库:CUDA 9.0和CUDA 10.0版本预测库。以下为各版本C++预测库的下载链接:
| 版本 | 链接 |
| ---- | ---- |
| CPU版本 | [fluid_inference.tgz](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_linux_cpu_1.6.1.tgz) |
| CUDA 9.0版本 | [fluid_inference.tgz](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_linux_cuda97_1.6.1.tgz) |
| CUDA 10.0版本 | [fluid_inference.tgz](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_linux_cuda10_1.6.1.tgz) |
针对不同的CPU类型、不同的指令集,官方提供更多可用的预测库版本,目前已经推出1.6版本的预测库。其余版本具体请参考以下链接:[C++预测库下载列表](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/advanced_usage/deploy/inference/build_and_install_lib_cn.html)
下载并解压后`/root/projects/fluid_inference`目录包含内容为: 下载并解压后`/root/projects/fluid_inference`目录包含内容为:
...@@ -53,25 +61,33 @@ make install ...@@ -53,25 +61,33 @@ make install
### Step4: 编译 ### Step4: 编译
`CMake`编译时,涉及到四个编译参数用于指定核心依赖库的路径, 他们的定义如下: `CMake`编译时,涉及到四个编译参数用于指定核心依赖库的路径, 他们的定义如下:(带*表示仅在使用**GPU版本**预测库时指定,其中CUDA库版本尽量对齐,**使用9.0、10.0版本,不使用9.2、10.1版本CUDA库**
| 参数名 | 含义 | | 参数名 | 含义 |
| ---- | ---- | | ---- | ---- |
| CUDA_LIB | cuda的库路径 | | * CUDA_LIB | CUDA的库路径 |
| CUDNN_LIB | cuDnn的库路径| | * CUDNN_LIB | cudnn的库路径|
| OPENCV_DIR | OpenCV的安装路径 | | OPENCV_DIR | OpenCV的安装路径 |
| PADDLE_DIR | Paddle预测库的路径 | | PADDLE_DIR | Paddle预测库的路径 |
执行下列操作时,**注意**把对应的参数改为你的上述依赖库实际路径: 在使用**GPU版本**预测库进行编译时,可执行下列操作。**注意**把对应的参数改为你的上述依赖库实际路径:
```shell ```shell
cd /root/projects/paddle_models/models/PaddleCV/PaddleDetection/inference cd /root/projects/PaddleDetection/inference
mkdir build && cd build mkdir build && cd build
cmake .. -DWITH_GPU=ON -DPADDLE_DIR=/root/projects/fluid_inference -DCUDA_LIB=/usr/local/cuda/lib64/ -DOPENCV_DIR=/root/projects/opencv3/ -DCUDNN_LIB=/usr/local/cuda/lib64/ cmake .. -DWITH_GPU=ON -DPADDLE_DIR=/root/projects/fluid_inference -DCUDA_LIB=/usr/local/cuda/lib64/ -DOPENCV_DIR=/root/projects/opencv3/ -DCUDNN_LIB=/usr/local/cuda/lib64/ -DWITH_STATIC_LIB=OFF
make make
``` ```
在使用**CPU版本**预测库进行编译时,可执行下列操作:
```shell
cd /root/projects/PaddleDetection/inference
mkdir build && cd build
cmake .. -DWITH_GPU=OFF -DPADDLE_DIR=/root/projects/fluid_inference -DOPENCV_DIR=/root/projects/opencv3/ -DWITH_STATIC_LIB=OFF
make
```
### Step5: 预测及可视化 ### Step5: 预测及可视化
......
...@@ -5,27 +5,28 @@ ...@@ -5,27 +5,28 @@
## 前置条件 ## 前置条件
* Visual Studio 2015 * Visual Studio 2015
* CUDA 8.0/ CUDA 9.0 * CUDA 9.0 / CUDA 10.0,cudnn 7+ (仅在使用GPU版本的预测库时需要)
* CMake 3.0+ * CMake 3.0+
请确保系统已经安装好上述基本软件,**下面所有示例以工作目录为 `D:\projects`演示** 请确保系统已经安装好上述基本软件,**下面所有示例以工作目录为 `D:\projects`演示**
### Step1: 下载代码 ### Step1: 下载代码
1. 打开`cmd`, 执行 `cd D:\projects\paddle_models` 1. 打开`cmd`, 执行 `cd D:\projects`
2. `git clone https://github.com/PaddlePaddle/models.git` 2. `git clone https://github.com/PaddlePaddle/PaddleDetection.git`
`C++`预测库代码在`D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference` 目录,该目录不依赖任何`PaddleDetection`下其他目录。 `C++`预测库代码在`D:\projects\PaddleDetection\inference` 目录,该目录不依赖任何`PaddleDetection`下其他目录。
### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference ### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference
根据Windows环境,下载相应版本的PaddlePaddle预测库,并解压到`D:\projects\`目录 PaddlePaddle C++ 预测库主要分为两大版本:CPU版本和GPU版本。其中,针对不同的CUDA版本,GPU版本预测库又分为两个版本预测库:CUDA 9.0和CUDA 10.0版本预测库。根据Windows环境,下载相应版本的PaddlePaddle预测库,并解压到`D:\projects\`目录。以下为各版本C++预测库的下载链接:
| CUDA | GPU | 下载地址 | | 版本 | 链接 |
|------|------|--------| | ---- | ---- |
| 8.0 | Yes | [fluid_inference.zip](https://bj.bcebos.com/v1/paddleseg/fluid_inference_win.zip) | | CPU版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_install_dir_win_cpu_1.6.zip) |
| 9.0 | Yes | [fluid_inference_cuda90.zip](https://paddleseg.bj.bcebos.com/fluid_inference_cuda9_cudnn7.zip) | | CUDA 9.0版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_install_dir_win_cuda9_1.6.1.zip) |
| CUDA 10.0版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_install_dir_win_cuda10_1.6.1.zip) |
解压后`D:\projects\fluid_inference`目录包含内容为: 解压后`D:\projects\fluid_inference`目录包含内容为:
``` ```
...@@ -42,9 +43,9 @@ fluid_inference ...@@ -42,9 +43,9 @@ fluid_inference
1. 在OpenCV官网下载适用于Windows平台的3.4.6版本, [下载地址](https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download) 1. 在OpenCV官网下载适用于Windows平台的3.4.6版本, [下载地址](https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download)
2. 运行下载的可执行文件,将OpenCV解压至指定目录,如`D:\projects\opencv` 2. 运行下载的可执行文件,将OpenCV解压至指定目录,如`D:\projects\opencv`
3. 配置环境变量,如下流程所示 3. 配置环境变量,如下流程所示
- 我的电脑->属性->高级系统设置->环境变量 - 我的电脑->属性->高级系统设置->环境变量
- 在系统变量中找到Path(如没有,自行创建),并双击编辑 - 在系统变量中找到Path(如没有,自行创建),并双击编辑
- 新建,将opencv路径填入并保存,如`D:\projects\opencv\build\x64\vc14\bin` - 新建,将opencv路径填入并保存,如`D:\projects\opencv\build\x64\vc14\bin`
### Step4: 以VS2015为例编译代码 ### Step4: 以VS2015为例编译代码
...@@ -56,35 +57,52 @@ fluid_inference ...@@ -56,35 +57,52 @@ fluid_inference
``` ```
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
``` ```
三个编译参数的含义说明如下(带*表示仅在使用**GPU版本**预测库时指定, 其中CUDA库版本尽量对齐,**使用9.0、10.0版本,不使用9.2、10.1等版本CUDA库**):
* CMAKE编译工程 | 参数名 | 含义 |
* PADDLE_DIR: fluid_inference预测库路径 | ---- | ---- |
* CUDA_LIB: CUDA动态库目录, 请根据实际安装情况调整 | *CUDA_LIB | CUDA的库路径 |
* OPENCV_DIR: OpenCV解压目录 | OPENCV_DIR | OpenCV的安装路径, |
| PADDLE_DIR | Paddle预测库的路径 |
在使用**GPU版本**预测库进行编译时,可执行下列操作。**注意**把对应的参数改为你的上述依赖库实际路径:
```bash
# 切换到预测库所在目录
cd /d D:\projects\PaddleDetection\inference
# 创建构建目录, 重新构建只需要删除该目录即可
mkdir build
cd build
# cmake构建VS项目
D:\projects\PaddleDetection\inference\build> cmake .. -G "Visual Studio 14 2015 Win64" -DWITH_GPU=ON -DPADDLE_DIR=D:\projects\fluid_inference -DCUDA_LIB=D:\projects\cudalib\v9.0\lib\x64 -DOPENCV_DIR=D:\projects\opencv -T host=x64
``` ```
在使用**CPU版本**预测库进行编译时,可执行下列操作:
```bash
# 切换到预测库所在目录 # 切换到预测库所在目录
cd /d D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference cd /d D:\projects\PaddleDetection\inference
# 创建构建目录, 重新构建只需要删除该目录即可 # 创建构建目录, 重新构建只需要删除该目录即可
mkdir build mkdir build
cd build cd build
# cmake构建VS项目 # cmake构建VS项目
D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build> cmake .. -G "Visual Studio 14 2015 Win64" -DWITH_GPU=ON -DPADDLE_DIR=D:\projects\fluid_inference -DCUDA_LIB=D:\projects\cudalib\v9.0\lib\x64 -DOPENCV_DIR=D:\projects\opencv -T host=x64 D:\projects\PaddleDetection\inference\build> cmake .. -G "Visual Studio 14 2015 Win64" -DWITH_GPU=OFF -DPADDLE_DIR=D:\projects\fluid_inference -DOPENCV_DIR=D:\projects\opencv -T host=x64
``` ```
这里的`cmake`参数`-G`, 表示生成对应的VS版本的工程,可以根据自己的`VS`版本调整,具体请参考[cmake文档](https://cmake.org/cmake/help/v3.15/manual/cmake-generators.7.html) 这里的`cmake`参数`-G`, 表示生成对应的VS版本的工程,可以根据自己的`VS`版本调整,具体请参考[cmake文档](https://cmake.org/cmake/help/v3.15/manual/cmake-generators.7.html)
* 生成可执行文件 * 生成可执行文件
``` ```
D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build> msbuild /m /p:Configuration=Release cpp_inference_demo.sln D:\projects\PaddleDetection\inference\build> msbuild /m /p:Configuration=Release cpp_inference_demo.sln
``` ```
### Step5: 预测及可视化 ### Step5: 预测及可视化
上述`Visual Studio 2015`编译产出的可执行文件在`build\release`目录下,切换到该目录: 上述`Visual Studio 2015`编译产出的可执行文件在`build\release`目录下,切换到该目录:
``` ```
cd /d D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\release cd /d D:\projects\PaddleDetection\inference\build\release
``` ```
之后执行命令: 之后执行命令:
...@@ -93,4 +111,4 @@ cd /d D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\ ...@@ -93,4 +111,4 @@ cd /d D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\
detection_demo.exe --conf=/path/to/your/conf --input_dir=/path/to/your/input/data/directory detection_demo.exe --conf=/path/to/your/conf --input_dir=/path/to/your/input/data/directory
``` ```
更详细说明请参考ReadMe文档: [预测和可视化部分](../README.md) 更详细说明请参考ReadMe文档: [预测和可视化部分](../README.md)
\ No newline at end of file
...@@ -6,7 +6,7 @@ Windows 平台下,我们使用`Visual Studio 2015` 和 `Visual Studio 2019 Com ...@@ -6,7 +6,7 @@ Windows 平台下,我们使用`Visual Studio 2015` 和 `Visual Studio 2019 Com
## 前置条件 ## 前置条件
* Visual Studio 2019 * Visual Studio 2019
* CUDA 8.0/ CUDA 9.0 * CUDA 9.0 / CUDA 10.0,cudnn 7+ (仅在使用GPU版本的预测库时需要)
* CMake 3.0+ * CMake 3.0+
请确保系统已经安装好上述基本软件,我们使用的是`VS2019`的社区版。 请确保系统已经安装好上述基本软件,我们使用的是`VS2019`的社区版。
...@@ -15,20 +15,21 @@ Windows 平台下,我们使用`Visual Studio 2015` 和 `Visual Studio 2019 Com ...@@ -15,20 +15,21 @@ Windows 平台下,我们使用`Visual Studio 2015` 和 `Visual Studio 2019 Com
### Step1: 下载代码 ### Step1: 下载代码
1. 点击下载源代码:[下载地址](https://github.com/PaddlePaddle/models/archive/develop.zip) 1. 点击下载源代码:[下载地址](https://github.com/PaddlePaddle/PaddleDetection/archive/master.zip)
2. 解压,解压后目录重命名为`paddle_models` 2. 解压,解压后目录重命名为`PaddleDetection`
以下代码目录路径为`D:\projects\paddle_models` 为例。 以下代码目录路径为`D:\projects\PaddleDetection` 为例。
### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference ### Step2: 下载PaddlePaddle C++ 预测库 fluid_inference
根据Windows环境,下载相应版本的PaddlePaddle预测库,并解压到`D:\projects\`目录 PaddlePaddle C++ 预测库主要分为两大版本:CPU版本和GPU版本。其中,针对不同的CUDA版本,GPU版本预测库又分为三个版本预测库:CUDA 9.0和CUDA 10.0版本预测库。根据Windows环境,下载相应版本的PaddlePaddle预测库,并解压到`D:\projects\`目录。以下为各版本C++预测库的下载链接:
| CUDA | GPU | 下载地址 | | 版本 | 链接 |
|------|------|--------| | ---- | ---- |
| 8.0 | Yes | [fluid_inference.zip](https://bj.bcebos.com/v1/paddleseg/fluid_inference_win.zip) | | CPU版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_install_dir_win_cpu_1.6.zip) |
| 9.0 | Yes | [fluid_inference_cuda90.zip](https://paddleseg.bj.bcebos.com/fluid_inference_cuda9_cudnn7.zip) | | CUDA 9.0版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_install_dir_win_cuda9_1.6.1.zip) |
| CUDA 10.0版本 | [fluid_inference_install_dir.zip](https://bj.bcebos.com/paddlehub/paddle_inference_lib/fluid_inference_install_dir_win_cuda10_1.6.1.zip) |
解压后`D:\projects\fluid_inference`目录包含内容为: 解压后`D:\projects\fluid_inference`目录包含内容为:
``` ```
...@@ -39,16 +40,15 @@ fluid_inference ...@@ -39,16 +40,15 @@ fluid_inference
| |
└── version.txt # 版本和编译信息 └── version.txt # 版本和编译信息
``` ```
**注意:** `CUDA90`版本解压后目录名称为`fluid_inference_cuda90`。
### Step3: 安装配置OpenCV ### Step3: 安装配置OpenCV
1. 在OpenCV官网下载适用于Windows平台的3.4.6版本, [下载地址](https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download) 1. 在OpenCV官网下载适用于Windows平台的3.4.6版本, [下载地址](https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download)
2. 运行下载的可执行文件,将OpenCV解压至指定目录,如`D:\projects\opencv` 2. 运行下载的可执行文件,将OpenCV解压至指定目录,如`D:\projects\opencv`
3. 配置环境变量,如下流程所示 3. 配置环境变量,如下流程所示
- 我的电脑->属性->高级系统设置->环境变量 - 我的电脑->属性->高级系统设置->环境变量
- 在系统变量中找到Path(如没有,自行创建),并双击编辑 - 在系统变量中找到Path(如没有,自行创建),并双击编辑
- 新建,将opencv路径填入并保存,如`D:\projects\opencv\build\x64\vc14\bin` - 新建,将opencv路径填入并保存,如`D:\projects\opencv\build\x64\vc14\bin`
### Step4: 使用Visual Studio 2019直接编译CMake ### Step4: 使用Visual Studio 2019直接编译CMake
...@@ -67,16 +67,17 @@ fluid_inference ...@@ -67,16 +67,17 @@ fluid_inference
4. 点击`浏览`,分别设置编译选项指定`CUDA`、`OpenCV`、`Paddle预测库`的路径 4. 点击`浏览`,分别设置编译选项指定`CUDA`、`OpenCV`、`Paddle预测库`的路径
![step4](https://paddleseg.bj.bcebos.com/inference/vs2019_step5.png) 三个编译参数的含义说明如下(带*表示仅在使用**GPU版本**预测库时指定, 其中CUDA库版本尽量对齐,**使用9.0、10.0版本,不使用9.2、10.1等版本CUDA库**):
三个编译参数的含义说明如下:
| 参数名 | 含义 | | 参数名 | 含义 |
| ---- | ---- | | ---- | ---- |
| CUDA_LIB | cuda的库路径 | | *CUDA_LIB | CUDA的库路径 |
| OPENCV_DIR | OpenCV的安装路径, | | OPENCV_DIR | OpenCV的安装路径, |
| PADDLE_DIR | Paddle预测库的路径 | | PADDLE_DIR | Paddle预测库的路径 |
**注意**在使用CPU版本预测库时,需要把CUDA_LIB的勾去掉。
![step4](https://paddleseg.bj.bcebos.com/inference/vs2019_step5.png)
**设置完成后**, 点击上图中`保存并生成CMake缓存以加载变量`。 **设置完成后**, 点击上图中`保存并生成CMake缓存以加载变量`。
5. 点击`生成`->`全部生成` 5. 点击`生成`->`全部生成`
...@@ -89,7 +90,7 @@ fluid_inference ...@@ -89,7 +90,7 @@ fluid_inference
上述`Visual Studio 2019`编译产出的可执行文件在`out\build\x64-Release`目录下,打开`cmd`,并切换到该目录: 上述`Visual Studio 2019`编译产出的可执行文件在`out\build\x64-Release`目录下,打开`cmd`,并切换到该目录:
``` ```
cd D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\x64-Release cd D:\projects\PaddleDetection\inference\out\build\x64-Release
``` ```
之后执行命令: 之后执行命令:
...@@ -98,4 +99,4 @@ cd D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\x64 ...@@ -98,4 +99,4 @@ cd D:\projects\paddle_models\models\PaddleCV\PaddleDetection\inference\build\x64
detection_demo.exe --conf=/path/to/your/conf --input_dir=/path/to/your/input/data/directory detection_demo.exe --conf=/path/to/your/conf --input_dir=/path/to/your/input/data/directory
``` ```
更详细说明请参考ReadMe文档: [预测和可视化部分](../README.md) 更详细说明请参考ReadMe文档: [预测和可视化部分](../README.md)
\ No newline at end of file
...@@ -17,31 +17,40 @@ ...@@ -17,31 +17,40 @@
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include "utils/detection_result.pb.h" #include "utils/detection_result.pb.h"
#undef min
namespace PaddleSolution { namespace PaddleSolution {
/* lod_buffer: every item in lod_buffer is an image matrix after preprocessing /* lod_buffer: every item in lod_buffer is an image matrix after preprocessing
* input_buffer: same data with lod_buffer after flattening to 1-D vector and padding, needed to be empty before using this function * input_buffer: same data with lod_buffer after flattening to 1-D vector and padding, needed to be empty before using this function
*/ */
void padding_minibatch(const std::vector<std::vector<float>> &lod_buffer, std::vector<float> &input_buffer, void padding_minibatch(const std::vector<std::vector<float>> &lod_buffer,
std::vector<int> &resize_heights, std::vector<int> &resize_widths, int channels, int coarsest_stride = 1) { std::vector<float> &input_buffer,
std::vector<int> &resize_heights,
std::vector<int> &resize_widths,
int channels, int coarsest_stride = 1) {
int batch_size = lod_buffer.size(); int batch_size = lod_buffer.size();
int max_h = -1; int max_h = -1;
int max_w = -1; int max_w = -1;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
max_h = (max_h > resize_heights[i])? max_h:resize_heights[i]; max_h = (max_h > resize_heights[i])? max_h:resize_heights[i];
max_w = (max_w > resize_widths[i])? max_w:resize_widths[i]; max_w = (max_w > resize_widths[i])? max_w:resize_widths[i];
} }
max_h = static_cast<int>(ceil(static_cast<float>(max_h) / static_cast<float>(coarsest_stride)) * coarsest_stride); max_h = static_cast<int>(ceil(static_cast<float>(max_h)
max_w = static_cast<int>(ceil(static_cast<float>(max_w) / static_cast<float>(coarsest_stride)) * coarsest_stride); / static_cast<float>(coarsest_stride)) * coarsest_stride);
max_w = static_cast<int>(ceil(static_cast<float>(max_w)
/ static_cast<float>(coarsest_stride)) * coarsest_stride);
std::cout << "max_w: " << max_w << " max_h: " << max_h << std::endl; std::cout << "max_w: " << max_w << " max_h: " << max_h << std::endl;
input_buffer.insert(input_buffer.end(), batch_size * channels * max_h * max_w, 0); input_buffer.insert(input_buffer.end(),
batch_size * channels * max_h * max_w, 0);
// flatten tensor and padding // flatten tensor and padding
for(int i = 0; i < lod_buffer.size(); ++i) { for (int i = 0; i < lod_buffer.size(); ++i) {
float *input_buffer_ptr = input_buffer.data() + i * channels * max_h * max_w; float *input_buffer_ptr = input_buffer.data()
+ i * channels * max_h * max_w;
const float *lod_ptr = lod_buffer[i].data(); const float *lod_ptr = lod_buffer[i].data();
for(int c = 0; c < channels; ++c) { for (int c = 0; c < channels; ++c) {
for(int h = 0; h < resize_heights[i]; ++h) { for (int h = 0; h < resize_heights[i]; ++h) {
memcpy(input_buffer_ptr, lod_ptr, resize_widths[i] * sizeof(float)); memcpy(input_buffer_ptr, lod_ptr,
resize_widths[i] * sizeof(float));
lod_ptr += resize_widths[i]; lod_ptr += resize_widths[i];
input_buffer_ptr += max_w; input_buffer_ptr += max_w;
} }
...@@ -49,44 +58,65 @@ namespace PaddleSolution { ...@@ -49,44 +58,65 @@ namespace PaddleSolution {
} }
} }
// change resize w, h // change resize w, h
for(int i = 0; i < batch_size; ++i){ for (int i = 0; i < batch_size; ++i) {
resize_widths[i] = max_w; resize_widths[i] = max_w;
resize_heights[i] = max_h; resize_heights[i] = max_h;
} }
} }
void output_detection_result(const float* out_addr, const std::vector<std::vector<size_t>> &lod_vector, const std::vector<std::string> &imgs_batch){ void output_detection_result(const float* out_addr,
for(int i = 0; i < lod_vector[0].size() - 1; ++i) { const std::vector<std::vector<size_t>> &lod_vector,
const std::vector<std::string> &imgs_batch) {
for (int i = 0; i < lod_vector[0].size() - 1; ++i) {
DetectionResult detection_result; DetectionResult detection_result;
detection_result.set_filename(imgs_batch[i]); detection_result.set_filename(imgs_batch[i]);
std::cout << imgs_batch[i] << ":" << std::endl; std::cout << imgs_batch[i] << ":" << std::endl;
for (int j = lod_vector[0][i]; j < lod_vector[0][i+1]; ++j) { for (int j = lod_vector[0][i]; j < lod_vector[0][i+1]; ++j) {
DetectionBox *box_ptr = detection_result.add_detection_boxes(); DetectionBox *box_ptr = detection_result.add_detection_boxes();
box_ptr->set_class_(static_cast<int>(round(out_addr[0 + j * 6]))); box_ptr->set_class_(
static_cast<int>(round(out_addr[0 + j * 6])));
box_ptr->set_score(out_addr[1 + j * 6]); box_ptr->set_score(out_addr[1 + j * 6]);
box_ptr->set_left_top_x(out_addr[2 + j * 6]); box_ptr->set_left_top_x(out_addr[2 + j * 6]);
box_ptr->set_left_top_y(out_addr[3 + j * 6]); box_ptr->set_left_top_y(out_addr[3 + j * 6]);
box_ptr->set_right_bottom_x(out_addr[4 + j * 6]); box_ptr->set_right_bottom_x(out_addr[4 + j * 6]);
box_ptr->set_right_bottom_y(out_addr[5 + j * 6]); box_ptr->set_right_bottom_y(out_addr[5 + j * 6]);
printf("Class %d, score = %f, left top = [%f, %f], right bottom = [%f, %f]\n", printf("Class %d, score = %f, left top = [%f, %f], right bottom = [%f, %f]\n",
static_cast<int>(round(out_addr[0 + j * 6])), out_addr[1 + j * 6], out_addr[2 + j * 6], static_cast<int>(round(out_addr[0 + j * 6])),
out_addr[3 + j * 6], out_addr[4 + j * 6], out_addr[5 + j * 6]); out_addr[1 + j * 6],
out_addr[2 + j * 6],
out_addr[3 + j * 6],
out_addr[4 + j * 6],
out_addr[5 + j * 6]);
} }
printf("\n"); printf("\n");
std::ofstream output(imgs_batch[i] + ".pb", std::ios::out | std::ios::trunc | std::ios::binary); std::ofstream output(imgs_batch[i] + ".pb",
std::ios::out | std::ios::trunc | std::ios::binary);
detection_result.SerializeToOstream(&output); detection_result.SerializeToOstream(&output);
output.close(); output.close();
} }
} }
int DetectionPredictor::init(const std::string& conf) { int DetectionPredictor::init(const std::string& conf) {
if (!_model_config.load_config(conf)) { if (!_model_config.load_config(conf)) {
LOG(FATAL) << "Fail to load config file: [" << conf << "]"; #ifdef _WIN32
std::cerr << "Fail to load config file: [" << conf << "], "
<< "please check whether the config file path is correct"
<< std::endl;
#else
LOG(FATAL) << "Fail to load config file: [" << conf << "], "
<< "please check whether the config file path is correct";
#endif
return -1; return -1;
} }
_preprocessor = PaddleSolution::create_processor(conf); _preprocessor = PaddleSolution::create_processor(conf);
if (_preprocessor == nullptr) { if (_preprocessor == nullptr) {
LOG(FATAL) << "Failed to create_processor"; #ifdef _WIN32
std::cerr << "Failed to create_processor, please check whether you"
<< " write a correct config file." << std::endl;
#else
LOG(FATAL) << "Failed to create_processor, please check whether"
<< " you write a correct config file.";
#endif
return -1; return -1;
} }
...@@ -116,20 +146,32 @@ namespace PaddleSolution { ...@@ -116,20 +146,32 @@ namespace PaddleSolution {
config.SetModel(prog_file, param_file); config.SetModel(prog_file, param_file);
config.SwitchUseFeedFetchOps(false); config.SwitchUseFeedFetchOps(false);
config.SwitchSpecifyInputNames(true); config.SwitchSpecifyInputNames(true);
config.EnableMemoryOptim(); config.EnableMemoryOptim();
// config.SwitchIrOptim(true);
// config.EnableTensorRtEngine(1<<4, 30, 3);
_main_predictor = paddle::CreatePaddlePredictor(config); _main_predictor = paddle::CreatePaddlePredictor(config);
} else { } else {
return -1; return -1;
} }
return 0; return 0;
} }
int DetectionPredictor::predict(const std::vector<std::string>& imgs) { int DetectionPredictor::predict(const std::vector<std::string>& imgs) {
if (imgs.size() == 0) {
#ifdef _WIN32
std::cerr << "No image found! Please check whether the images path"
<< " is correct or the format of images is correct\n"
<< "Supporting format: [.jpeg|.jpg|.JPEG|.JPG|.bmp|.BMP|.png|.PNG]" << std::endl;
#else
LOG(ERROR) << "No image found! Please check whether the images path"
<< " is correct or the format of images is correct\n"
<< "Supporting format: [.jpeg|.jpg|.JPEG|.JPG|.bmp|.BMP|.png|.PNG]";
#endif
return -1;
}
if (_model_config._predictor_mode == "NATIVE") { if (_model_config._predictor_mode == "NATIVE") {
return native_predict(imgs); return native_predict(imgs);
} } else if (_model_config._predictor_mode == "ANALYSIS") {
else if (_model_config._predictor_mode == "ANALYSIS") {
return analysis_predict(imgs); return analysis_predict(imgs);
} }
return -1; return -1;
...@@ -142,21 +184,24 @@ namespace PaddleSolution { ...@@ -142,21 +184,24 @@ namespace PaddleSolution {
int eval_width = _model_config._resize[0]; int eval_width = _model_config._resize[0];
int eval_height = _model_config._resize[1]; int eval_height = _model_config._resize[1];
std::size_t total_size = imgs.size(); std::size_t total_size = imgs.size();
int default_batch_size = std::min(config_batch_size, (int)total_size); int default_batch_size = std::min(config_batch_size,
int batch = total_size / default_batch_size + ((total_size % default_batch_size) != 0); static_cast<int>(total_size));
int batch_buffer_size = default_batch_size * channels * eval_width * eval_height; int batch = total_size / default_batch_size +
((total_size % default_batch_size) != 0);
int batch_buffer_size = default_batch_size * channels
* eval_width * eval_height;
auto& input_buffer = _buffer; auto& input_buffer = _buffer;
auto& imgs_batch = _imgs_batch; auto& imgs_batch = _imgs_batch;
float sr; float sr;
// DetectionResultsContainer result_container;
for (int u = 0; u < batch; ++u) { for (int u = 0; u < batch; ++u) {
int batch_size = default_batch_size; int batch_size = default_batch_size;
if (u == (batch - 1) && (total_size % default_batch_size)) { if (u == (batch - 1) && (total_size % default_batch_size)) {
batch_size = total_size % default_batch_size; batch_size = total_size % default_batch_size;
} }
int real_buffer_size = batch_size * channels * eval_width * eval_height; int real_buffer_size = batch_size * channels
* eval_width * eval_height;
std::vector<paddle::PaddleTensor> feeds; std::vector<paddle::PaddleTensor> feeds;
input_buffer.clear(); input_buffer.clear();
imgs_batch.clear(); imgs_batch.clear();
...@@ -175,58 +220,70 @@ namespace PaddleSolution { ...@@ -175,58 +220,70 @@ namespace PaddleSolution {
resize_heights.resize(batch_size); resize_heights.resize(batch_size);
scale_ratios.resize(batch_size); scale_ratios.resize(batch_size);
std::vector<std::vector<float>> lod_buffer(batch_size); std::vector<std::vector<float>> lod_buffer(batch_size);
if (!_preprocessor->batch_process(imgs_batch, lod_buffer, ori_widths.data(), ori_heights.data(), if (!_preprocessor->batch_process(imgs_batch, lod_buffer,
resize_widths.data(), resize_heights.data(), scale_ratios.data())) { ori_widths.data(),
ori_heights.data(),
resize_widths.data(),
resize_heights.data(),
scale_ratios.data())) {
return -1; return -1;
} }
// flatten and padding // flatten and padding
padding_minibatch(lod_buffer, input_buffer, resize_heights, resize_widths, channels, _model_config._coarsest_stride); padding_minibatch(lod_buffer, input_buffer, resize_heights,
resize_widths, channels,
_model_config._coarsest_stride);
paddle::PaddleTensor im_tensor, im_size_tensor, im_info_tensor; paddle::PaddleTensor im_tensor, im_size_tensor, im_info_tensor;
im_tensor.name = "image"; im_tensor.name = "image";
im_tensor.shape = std::vector<int>({ batch_size, channels, resize_heights[0], resize_widths[0] }); im_tensor.shape = std::vector<int>({ batch_size,
im_tensor.data.Reset(input_buffer.data(), input_buffer.size() * sizeof(float)); channels,
resize_heights[0],
resize_widths[0] });
im_tensor.data.Reset(input_buffer.data(),
input_buffer.size() * sizeof(float));
im_tensor.dtype = paddle::PaddleDType::FLOAT32; im_tensor.dtype = paddle::PaddleDType::FLOAT32;
std::vector<float> image_infos; std::vector<float> image_infos;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_infos.push_back(resize_heights[i]); image_infos.push_back(resize_heights[i]);
image_infos.push_back(resize_widths[i]); image_infos.push_back(resize_widths[i]);
image_infos.push_back(scale_ratios[i]); image_infos.push_back(scale_ratios[i]);
} }
im_info_tensor.name = "info"; im_info_tensor.name = "info";
im_info_tensor.shape = std::vector<int>({batch_size, 3}); im_info_tensor.shape = std::vector<int>({batch_size, 3});
im_info_tensor.data.Reset(image_infos.data(), batch_size * 3 * sizeof(float)); im_info_tensor.data.Reset(image_infos.data(),
batch_size * 3 * sizeof(float));
im_info_tensor.dtype = paddle::PaddleDType::FLOAT32; im_info_tensor.dtype = paddle::PaddleDType::FLOAT32;
std::vector<int> image_size; std::vector<int> image_size;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_size.push_back(ori_heights[i]); image_size.push_back(ori_heights[i]);
image_size.push_back(ori_widths[i]); image_size.push_back(ori_widths[i]);
} }
std::vector<float> image_size_f; std::vector<float> image_size_f;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_size_f.push_back(ori_heights[i]); image_size_f.push_back(ori_heights[i]);
image_size_f.push_back(ori_widths[i]); image_size_f.push_back(ori_widths[i]);
image_size_f.push_back(1.0); image_size_f.push_back(1.0);
} }
int feeds_size = _model_config._feeds_size; int feeds_size = _model_config._feeds_size;
im_size_tensor.name = "im_size"; im_size_tensor.name = "im_size";
if(feeds_size == 2) { if (feeds_size == 2) {
im_size_tensor.shape = std::vector<int>({ batch_size, 2}); im_size_tensor.shape = std::vector<int>({ batch_size, 2});
im_size_tensor.data.Reset(image_size.data(), batch_size * 2 * sizeof(int)); im_size_tensor.data.Reset(image_size.data(),
batch_size * 2 * sizeof(int));
im_size_tensor.dtype = paddle::PaddleDType::INT32; im_size_tensor.dtype = paddle::PaddleDType::INT32;
} } else if (feeds_size == 3) {
else if(feeds_size == 3) {
im_size_tensor.shape = std::vector<int>({ batch_size, 3}); im_size_tensor.shape = std::vector<int>({ batch_size, 3});
im_size_tensor.data.Reset(image_size_f.data(), batch_size * 3 * sizeof(float)); im_size_tensor.data.Reset(image_size_f.data(),
batch_size * 3 * sizeof(float));
im_size_tensor.dtype = paddle::PaddleDType::FLOAT32; im_size_tensor.dtype = paddle::PaddleDType::FLOAT32;
} }
std::cout << "Feed size = " << feeds_size << std::endl; std::cout << "Feed size = " << feeds_size << std::endl;
feeds.push_back(im_tensor); feeds.push_back(im_tensor);
if(_model_config._feeds_size > 2) { if (_model_config._feeds_size > 2) {
feeds.push_back(im_info_tensor); feeds.push_back(im_info_tensor);
} }
feeds.push_back(im_size_tensor); feeds.push_back(im_size_tensor);
...@@ -234,7 +291,11 @@ namespace PaddleSolution { ...@@ -234,7 +291,11 @@ namespace PaddleSolution {
auto t1 = std::chrono::high_resolution_clock::now(); auto t1 = std::chrono::high_resolution_clock::now();
if (!_main_predictor->Run(feeds, &_outputs, batch_size)) { if (!_main_predictor->Run(feeds, &_outputs, batch_size)) {
#ifdef _WIN32
std::cerr << "Failed: NativePredictor->Run() return false at batch: " << u;
#else
LOG(ERROR) << "Failed: NativePredictor->Run() return false at batch: " << u; LOG(ERROR) << "Failed: NativePredictor->Run() return false at batch: " << u;
#endif
continue; continue;
} }
auto t2 = std::chrono::high_resolution_clock::now(); auto t2 = std::chrono::high_resolution_clock::now();
...@@ -249,48 +310,51 @@ namespace PaddleSolution { ...@@ -249,48 +310,51 @@ namespace PaddleSolution {
std::cout << _outputs[0].shape[j] << ","; std::cout << _outputs[0].shape[j] << ",";
} }
std::cout << ")" << std::endl; std::cout << ")" << std::endl;
// const size_t nums = _outputs.front().data.length() / sizeof(float); // const size_t nums = _outputs.front().data.length() / sizeof(float);
// if (out_num % batch_size != 0 || out_num != nums) { // if (out_num % batch_size != 0 || out_num != nums) {
// LOG(ERROR) << "outputs data size mismatch with shape size."; // LOG(ERROR) << "outputs data size mismatch with shape size.";
// return -1; // return -1;
// } // }
float* out_addr = (float *)(_outputs[0].data.data()); float* out_addr = reinterpret_cast<float *>(_outputs[0].data.data());
output_detection_result(out_addr, _outputs[0].lod, imgs_batch); output_detection_result(out_addr, _outputs[0].lod, imgs_batch);
} }
return 0; return 0;
} }
int DetectionPredictor::analysis_predict(const std::vector<std::string>& imgs) { int DetectionPredictor::analysis_predict(
const std::vector<std::string>& imgs) {
int config_batch_size = _model_config._batch_size; int config_batch_size = _model_config._batch_size;
int channels = _model_config._channels; int channels = _model_config._channels;
int eval_width = _model_config._resize[0]; int eval_width = _model_config._resize[0];
int eval_height = _model_config._resize[1]; int eval_height = _model_config._resize[1];
auto total_size = imgs.size(); auto total_size = imgs.size();
int default_batch_size = std::min(config_batch_size, (int)total_size); int default_batch_size = std::min(config_batch_size,
int batch = total_size / default_batch_size + ((total_size % default_batch_size) != 0); static_cast<int>(total_size));
int batch_buffer_size = default_batch_size * channels * eval_width * eval_height; int batch = total_size / default_batch_size
+ ((total_size % default_batch_size) != 0);
int batch_buffer_size = default_batch_size * channels
* eval_width * eval_height;
auto& input_buffer = _buffer; auto& input_buffer = _buffer;
auto& imgs_batch = _imgs_batch; auto& imgs_batch = _imgs_batch;
//DetectionResultsContainer result_container;
for (int u = 0; u < batch; ++u) { for (int u = 0; u < batch; ++u) {
int batch_size = default_batch_size; int batch_size = default_batch_size;
if (u == (batch - 1) && (total_size % default_batch_size)) { if (u == (batch - 1) && (total_size % default_batch_size)) {
batch_size = total_size % default_batch_size; batch_size = total_size % default_batch_size;
} }
int real_buffer_size = batch_size * channels * eval_width * eval_height; int real_buffer_size = batch_size * channels *
eval_width * eval_height;
std::vector<paddle::PaddleTensor> feeds; std::vector<paddle::PaddleTensor> feeds;
//input_buffer.resize(real_buffer_size); // input_buffer.resize(real_buffer_size);
input_buffer.clear(); input_buffer.clear();
imgs_batch.clear(); imgs_batch.clear();
for (int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
int idx = u * default_batch_size + i; int idx = u * default_batch_size + i;
imgs_batch.push_back(imgs[idx]); imgs_batch.push_back(imgs[idx]);
} }
std::vector<int> ori_widths; std::vector<int> ori_widths;
std::vector<int> ori_heights; std::vector<int> ori_heights;
std::vector<int> resize_widths; std::vector<int> resize_widths;
...@@ -301,56 +365,64 @@ namespace PaddleSolution { ...@@ -301,56 +365,64 @@ namespace PaddleSolution {
resize_widths.resize(batch_size); resize_widths.resize(batch_size);
resize_heights.resize(batch_size); resize_heights.resize(batch_size);
scale_ratios.resize(batch_size); scale_ratios.resize(batch_size);
std::vector<std::vector<float>> lod_buffer(batch_size); std::vector<std::vector<float>> lod_buffer(batch_size);
if (!_preprocessor->batch_process(imgs_batch, lod_buffer, ori_widths.data(), ori_heights.data(), if (!_preprocessor->batch_process(imgs_batch, lod_buffer,
resize_widths.data(), resize_heights.data(), scale_ratios.data())){ ori_widths.data(),
ori_heights.data(),
resize_widths.data(),
resize_heights.data(),
scale_ratios.data())) {
std::cout << "Failed to preprocess!" << std::endl; std::cout << "Failed to preprocess!" << std::endl;
return -1; return -1;
} }
//flatten tensor // flatten tensor
padding_minibatch(lod_buffer, input_buffer, resize_heights, resize_widths, channels, _model_config._coarsest_stride); padding_minibatch(lod_buffer, input_buffer, resize_heights,
resize_widths, channels,
_model_config._coarsest_stride);
std::vector<std::string> input_names = _main_predictor->GetInputNames(); std::vector<std::string> input_names = _main_predictor->GetInputNames();
auto im_tensor = _main_predictor->GetInputTensor(input_names.front()); auto im_tensor = _main_predictor->GetInputTensor(
im_tensor->Reshape({ batch_size, channels, resize_heights[0], resize_widths[0] }); input_names.front());
im_tensor->Reshape({ batch_size, channels,
resize_heights[0], resize_widths[0] });
im_tensor->copy_from_cpu(input_buffer.data()); im_tensor->copy_from_cpu(input_buffer.data());
if(input_names.size() > 2){ if (input_names.size() > 2) {
std::vector<float> image_infos; std::vector<float> image_infos;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_infos.push_back(resize_heights[i]); image_infos.push_back(resize_heights[i]);
image_infos.push_back(resize_widths[i]); image_infos.push_back(resize_widths[i]);
image_infos.push_back(scale_ratios[i]); image_infos.push_back(scale_ratios[i]);
} }
auto im_info_tensor = _main_predictor->GetInputTensor(input_names[1]); auto im_info_tensor = _main_predictor->GetInputTensor(
input_names[1]);
im_info_tensor->Reshape({batch_size, 3}); im_info_tensor->Reshape({batch_size, 3});
im_info_tensor->copy_from_cpu(image_infos.data()); im_info_tensor->copy_from_cpu(image_infos.data());
} }
std::vector<int> image_size; std::vector<int> image_size;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_size.push_back(ori_heights[i]); image_size.push_back(ori_heights[i]);
image_size.push_back(ori_widths[i]); image_size.push_back(ori_widths[i]);
} }
std::vector<float> image_size_f; std::vector<float> image_size_f;
for(int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
image_size_f.push_back(static_cast<float>(ori_heights[i])); image_size_f.push_back(static_cast<float>(ori_heights[i]));
image_size_f.push_back(static_cast<float>(ori_widths[i])); image_size_f.push_back(static_cast<float>(ori_widths[i]));
image_size_f.push_back(1.0); image_size_f.push_back(1.0);
} }
auto im_size_tensor = _main_predictor->GetInputTensor(input_names.back()); auto im_size_tensor = _main_predictor->GetInputTensor(
if(input_names.size() > 2) { input_names.back());
if (input_names.size() > 2) {
im_size_tensor->Reshape({batch_size, 3}); im_size_tensor->Reshape({batch_size, 3});
im_size_tensor->copy_from_cpu(image_size_f.data()); im_size_tensor->copy_from_cpu(image_size_f.data());
} } else {
else{
im_size_tensor->Reshape({batch_size, 2}); im_size_tensor->Reshape({batch_size, 2});
im_size_tensor->copy_from_cpu(image_size.data()); im_size_tensor->copy_from_cpu(image_size.data());
} }
auto t1 = std::chrono::high_resolution_clock::now(); auto t1 = std::chrono::high_resolution_clock::now();
_main_predictor->ZeroCopyRun(); _main_predictor->ZeroCopyRun();
...@@ -374,10 +446,10 @@ namespace PaddleSolution { ...@@ -374,10 +446,10 @@ namespace PaddleSolution {
out_data.resize(out_num); out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data()); output_t->copy_to_cpu(out_data.data());
float* out_addr = (float *)(out_data.data()); float* out_addr = reinterpret_cast<float *>(out_data.data());
auto lod_vector = output_t->lod(); auto lod_vector = output_t->lod();
output_detection_result(out_addr, lod_vector, imgs_batch); output_detection_result(out_addr, lod_vector, imgs_batch);
} }
return 0; return 0;
} }
} } // namespace PaddleSolution
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
...@@ -14,39 +14,40 @@ ...@@ -14,39 +14,40 @@
#pragma once #pragma once
#include <glog/logging.h>
#include <yaml-cpp/yaml.h>
#include <paddle_inference_api.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <algorithm> #include <algorithm>
#include <glog/logging.h>
#include <yaml-cpp/yaml.h>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <paddle_inference_api.h>
#include <utils/conf_parser.h> #include "utils/conf_parser.h"
#include <utils/utils.h> #include "utils/utils.h"
#include <preprocessor/preprocessor.h> #include "preprocessor/preprocessor.h"
namespace PaddleSolution { namespace PaddleSolution {
class DetectionPredictor { class DetectionPredictor {
public: public:
// init a predictor with a yaml config file // init a predictor with a yaml config file
int init(const std::string& conf); int init(const std::string& conf);
// predict api // predict api
int predict(const std::vector<std::string>& imgs); int predict(const std::vector<std::string>& imgs);
private: private:
int native_predict(const std::vector<std::string>& imgs); int native_predict(const std::vector<std::string>& imgs);
int analysis_predict(const std::vector<std::string>& imgs); int analysis_predict(const std::vector<std::string>& imgs);
private: private:
std::vector<float> _buffer; std::vector<float> _buffer;
std::vector<std::string> _imgs_batch; std::vector<std::string> _imgs_batch;
std::vector<paddle::PaddleTensor> _outputs; std::vector<paddle::PaddleTensor> _outputs;
PaddleSolution::PaddleModelConfigPaser _model_config; PaddleSolution::PaddleModelConfigPaser _model_config;
std::shared_ptr<PaddleSolution::ImagePreProcessor> _preprocessor; std::shared_ptr<PaddleSolution::ImagePreProcessor> _preprocessor;
std::unique_ptr<paddle::PaddlePredictor> _main_predictor; std::unique_ptr<paddle::PaddlePredictor> _main_predictor;
}; };
} } // namespace PaddleSolution
...@@ -16,14 +16,18 @@ ...@@ -16,14 +16,18 @@
#include "preprocessor.h" #include "preprocessor.h"
#include "preprocessor_detection.h" #include "preprocessor_detection.h"
#include <iostream>
namespace PaddleSolution { namespace PaddleSolution {
std::shared_ptr<ImagePreProcessor> create_processor(const std::string& conf_file) { std::shared_ptr<ImagePreProcessor> create_processor(const std::string& conf_file) {
auto config = std::make_shared<PaddleSolution::PaddleModelConfigPaser>(); auto config = std::make_shared<PaddleSolution::PaddleModelConfigPaser>();
if (!config->load_config(conf_file)) { if (!config->load_config(conf_file)) {
LOG(FATAL) << "fail to laod conf file [" << conf_file << "]"; #ifdef _WIN32
std::cerr << "fail to load conf file [" << conf_file << "]" << std::endl;
#else
LOG(FATAL) << "fail to load conf file [" << conf_file << "]";
#endif
return nullptr; return nullptr;
} }
...@@ -34,10 +38,13 @@ namespace PaddleSolution { ...@@ -34,10 +38,13 @@ namespace PaddleSolution {
} }
return p; return p;
} }
#ifdef _WIN32
std::cerr << "unknown processor_name [" << config->_pre_processor << "],"
LOG(FATAL) << "unknown processor_name [" << config->_pre_processor << "]"; << "please check whether PRE_PROCESSOR is set correctly" << std::endl;
#else
LOG(FATAL) << "unknown processor_name [" << config->_pre_processor << "],"
<< "please check whether PRE_PROCESSOR is set correctly";
#endif
return nullptr; return nullptr;
} }
} } // namespace PaddleSolution
...@@ -26,39 +26,52 @@ ...@@ -26,39 +26,52 @@
namespace PaddleSolution { namespace PaddleSolution {
class ImagePreProcessor { class ImagePreProcessor {
protected: protected:
ImagePreProcessor() {}; ImagePreProcessor() {}
public: public:
virtual ~ImagePreProcessor() {} virtual ~ImagePreProcessor() {}
virtual bool single_process(const std::string& fname, float* data, int* ori_w, int* ori_h) { virtual bool single_process(const std::string& fname,
float* data,
int* ori_w,
int* ori_h) {
return true; return true;
} }
virtual bool batch_process(const std::vector<std::string>& imgs, float* data, int* ori_w, int* ori_h) { virtual bool batch_process(const std::vector<std::string>& imgs,
float* data,
int* ori_w,
int* ori_h) {
return true; return true;
} }
virtual bool single_process(const std::string& fname, float* data) { virtual bool single_process(const std::string& fname, float* data) {
return true; return true;
} }
virtual bool batch_process(const std::vector<std::string>& imgs, float* data) { virtual bool batch_process(const std::vector<std::string>& imgs,
float* data) {
return true; return true;
} }
virtual bool single_process(const std::string& fname, std::vector<float> &data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio) {
return true;
}
virtual bool batch_process(const std::vector<std::string>& imgs, std::vector<std::vector<float>> &data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio) { virtual bool single_process(const std::string& fname,
return true; std::vector<float> &data,
int* ori_w, int* ori_h,
int* resize_w, int* resize_h,
float* scale_ratio) {
return true;
} }
}; // end of class ImagePreProcessor virtual bool batch_process(const std::vector<std::string>& imgs,
std::vector<std::vector<float>> &data,
std::shared_ptr<ImagePreProcessor> create_processor(const std::string &config_file); int* ori_w, int* ori_h, int* resize_w,
int* resize_h, float* scale_ratio) {
return true;
}
}; // end of class ImagePreProcessor
} // end of namespace paddle_solution std::shared_ptr<ImagePreProcessor>
create_processor(const std::string &config_file);
} // namespace PaddleSolution
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
...@@ -12,119 +12,133 @@ ...@@ -12,119 +12,133 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <glog/logging.h>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <glog/logging.h>
#include "preprocessor_detection.h" #include "preprocessor_detection.h"
#include "utils/utils.h" #include "utils/utils.h"
namespace PaddleSolution { namespace PaddleSolution {
bool DetectionPreProcessor::single_process(const std::string& fname, std::vector<float> &vec_data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio) { bool DetectionPreProcessor::single_process(const std::string& fname,
cv::Mat im1 = cv::imread(fname, -1); std::vector<float> &vec_data,
cv::Mat im; int* ori_w, int* ori_h,
if(_config->_feeds_size == 3) { // faster rcnn int* resize_w, int* resize_h,
im1.convertTo(im, CV_32FC3, 1/255.0); float* scale_ratio) {
} cv::Mat im1 = cv::imread(fname, -1);
else if(_config->_feeds_size == 2){ //yolo v3 cv::Mat im;
im = im1; if (_config->_feeds_size == 3) { // faster rcnn
} im1.convertTo(im, CV_32FC3, 1/255.0);
if (im.data == nullptr || im.empty()) { } else if (_config->_feeds_size == 2) { // yolo v3
LOG(ERROR) << "Failed to open image: " << fname; im = im1;
return false; }
} if (im.data == nullptr || im.empty()) {
#ifdef _WIN32
int channels = im.channels(); std::cerr << "Failed to open image: " << fname << std::endl;
if (channels == 1) { #else
cv::cvtColor(im, im, cv::COLOR_GRAY2BGR); LOG(ERROR) << "Failed to open image: " << fname;
} #endif
channels = im.channels(); return false;
if (channels != 3 && channels != 4) { }
LOG(ERROR) << "Only support rgb(gray) and rgba image."; int channels = im.channels();
return false; if (channels == 1) {
} cv::cvtColor(im, im, cv::COLOR_GRAY2BGR);
*ori_w = im.cols; }
*ori_h = im.rows; channels = im.channels();
cv::cvtColor(im, im, cv::COLOR_BGR2RGB); if (channels != 3 && channels != 4) {
//channels = im.channels(); #ifdef _WIN32
std::cerr << "Only support rgb(gray) and rgba image." << std::endl;
#else
LOG(ERROR) << "Only support rgb(gray) and rgba image.";
#endif
return false;
}
*ori_w = im.cols;
*ori_h = im.rows;
cv::cvtColor(im, im, cv::COLOR_BGR2RGB);
// channels = im.channels();
//resize // resize
int rw = im.cols; int rw = im.cols;
int rh = im.rows; int rh = im.rows;
float im_scale_ratio; float im_scale_ratio;
utils::scaling(_config->_resize_type, rw, rh, _config->_resize[0], _config->_resize[1], _config->_target_short_size, _config->_resize_max_size, im_scale_ratio); utils::scaling(_config->_resize_type, rw, rh, _config->_resize[0],
cv::Size resize_size(rw, rh); _config->_resize[1], _config->_target_short_size,
*resize_w = rw; _config->_resize_max_size, im_scale_ratio);
*resize_h = rh; cv::Size resize_size(rw, rh);
*scale_ratio = im_scale_ratio; *resize_w = rw;
if (*ori_h != rh || *ori_w != rw) { *resize_h = rh;
cv::Mat im_temp; *scale_ratio = im_scale_ratio;
if(_config->_resize_type == utils::SCALE_TYPE::UNPADDING) { if (*ori_h != rh || *ori_w != rw) {
cv::resize(im, im_temp, resize_size, 0, 0, cv::INTER_LINEAR); cv::Mat im_temp;
} if (_config->_resize_type == utils::SCALE_TYPE::UNPADDING) {
else if(_config->_resize_type == utils::SCALE_TYPE::RANGE_SCALING) { cv::resize(im, im_temp, resize_size, 0, 0, cv::INTER_LINEAR);
cv::resize(im, im_temp, cv::Size(), im_scale_ratio, im_scale_ratio, cv::INTER_LINEAR); } else if (_config->_resize_type == utils::SCALE_TYPE::RANGE_SCALING) {
} cv::resize(im, im_temp, cv::Size(), im_scale_ratio,
im = im_temp; im_scale_ratio, cv::INTER_LINEAR);
} }
im = im_temp;
}
vec_data.resize(channels * rw * rh); vec_data.resize(channels * rw * rh);
float *data = vec_data.data(); float *data = vec_data.data();
float* pmean = _config->_mean.data(); float* pmean = _config->_mean.data();
float* pscale = _config->_std.data(); float* pscale = _config->_std.data();
for (int h = 0; h < rh; ++h) { for (int h = 0; h < rh; ++h) {
const uchar* uptr = im.ptr<uchar>(h); const uchar* uptr = im.ptr<uchar>(h);
const float* fptr = im.ptr<float>(h); const float* fptr = im.ptr<float>(h);
int im_index = 0; int im_index = 0;
for (int w = 0; w < rw; ++w) { for (int w = 0; w < rw; ++w) {
for (int c = 0; c < channels; ++c) { for (int c = 0; c < channels; ++c) {
int top_index = (c * rh + h) * rw + w; int top_index = (c * rh + h) * rw + w;
float pixel;// = static_cast<float>(fptr[im_index]);// / 255.0; float pixel;
if(_config->_feeds_size == 2){ //yolo v3 if (_config->_feeds_size == 2) { // yolo v3
pixel = static_cast<float>(uptr[im_index++]) / 255.0; pixel = static_cast<float>(uptr[im_index++]) / 255.0;
} } else if (_config->_feeds_size == 3) {
else if(_config->_feeds_size == 3){ pixel = fptr[im_index++];
pixel = fptr[im_index++];
}
pixel = (pixel - pmean[c]) / pscale[c];
data[top_index] = pixel;
} }
pixel = (pixel - pmean[c]) / pscale[c];
data[top_index] = pixel;
} }
} }
return true;
} }
return true;
}
bool DetectionPreProcessor::batch_process(const std::vector<std::string>& imgs, std::vector<std::vector<float>> &data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio) { bool DetectionPreProcessor::batch_process(const std::vector<std::string>& imgs,
auto ic = _config->_channels; std::vector<std::vector<float>> &data,
auto iw = _config->_resize[0]; int* ori_w, int* ori_h, int* resize_w,
auto ih = _config->_resize[1]; int* resize_h, float* scale_ratio) {
std::vector<std::thread> threads; auto ic = _config->_channels;
for (int i = 0; i < imgs.size(); ++i) { auto iw = _config->_resize[0];
std::string path = imgs[i]; auto ih = _config->_resize[1];
int* width = &ori_w[i]; std::vector<std::thread> threads;
int* height = &ori_h[i]; for (int i = 0; i < imgs.size(); ++i) {
int* resize_width = &resize_w[i]; std::string path = imgs[i];
int* resize_height = &resize_h[i]; int* width = &ori_w[i];
float* sr = &scale_ratio[i]; int* height = &ori_h[i];
threads.emplace_back([this, &data, i, path, width, height, resize_width, resize_height, sr] { int* resize_width = &resize_w[i];
std::vector<float> buffer; int* resize_height = &resize_h[i];
single_process(path, buffer, width, height, resize_width, resize_height, sr); float* sr = &scale_ratio[i];
data[i] = buffer; threads.emplace_back([this, &data, i, path, width, height,
}); resize_width, resize_height, sr] {
} std::vector<float> buffer;
for (auto& t : threads) { single_process(path, buffer, width, height, resize_width,
if (t.joinable()) { resize_height, sr);
t.join(); data[i] = buffer;
} });
}
return true;
} }
for (auto& t : threads) {
bool DetectionPreProcessor::init(std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> config) { if (t.joinable()) {
_config = config; t.join();
return true; }
} }
return true;
}
bool DetectionPreProcessor::init(std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> config) {
_config = config;
return true;
} }
} // namespace PaddleSolution
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
...@@ -18,19 +18,23 @@ ...@@ -18,19 +18,23 @@
namespace PaddleSolution { namespace PaddleSolution {
class DetectionPreProcessor : public ImagePreProcessor { class DetectionPreProcessor : public ImagePreProcessor {
public:
DetectionPreProcessor() : _config(nullptr) {
}
public: bool init(std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> config);
DetectionPreProcessor() : _config(nullptr) {
};
bool init(std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> config); bool single_process(const std::string& fname, std::vector<float> &data,
int* ori_w, int* ori_h, int* resize_w,
bool single_process(const std::string& fname, std::vector<float> &data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio); int* resize_h, float* scale_ratio);
bool batch_process(const std::vector<std::string>& imgs, std::vector<std::vector<float>> &data, int* ori_w, int* ori_h, int* resize_w, int* resize_h, float* scale_ratio); bool batch_process(const std::vector<std::string>& imgs,
private: std::vector<std::vector<float>> &data,
std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> _config; int* ori_w, int* ori_h, int* resize_w,
}; int* resize_h, float* scale_ratio);
private:
std::shared_ptr<PaddleSolution::PaddleModelConfigPaser> _config;
};
} } // namespace PaddleSolution
...@@ -134,7 +134,8 @@ _DETECTIONBOX = _descriptor.Descriptor( ...@@ -134,7 +134,8 @@ _DETECTIONBOX = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[], oneofs=[],
serialized_start=43, serialized_start=43,
serialized_end=175, ) serialized_end=175,
)
_DETECTIONRESULT = _descriptor.Descriptor( _DETECTIONRESULT = _descriptor.Descriptor(
name='DetectionResult', name='DetectionResult',
...@@ -185,7 +186,8 @@ _DETECTIONRESULT = _descriptor.Descriptor( ...@@ -185,7 +186,8 @@ _DETECTIONRESULT = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[], oneofs=[],
serialized_start=177, serialized_start=177,
serialized_end=267, ) serialized_end=267,
)
_DETECTIONRESULT.fields_by_name['detection_boxes'].message_type = _DETECTIONBOX _DETECTIONRESULT.fields_by_name['detection_boxes'].message_type = _DETECTIONBOX
DESCRIPTOR.message_types_by_name['DetectionBox'] = _DETECTIONBOX DESCRIPTOR.message_types_by_name['DetectionBox'] = _DETECTIONBOX
...@@ -193,22 +195,20 @@ DESCRIPTOR.message_types_by_name['DetectionResult'] = _DETECTIONRESULT ...@@ -193,22 +195,20 @@ DESCRIPTOR.message_types_by_name['DetectionResult'] = _DETECTIONRESULT
DetectionBox = _reflection.GeneratedProtocolMessageType( DetectionBox = _reflection.GeneratedProtocolMessageType(
'DetectionBox', 'DetectionBox',
(_message.Message, ), (_message.Message,),
dict( dict(DESCRIPTOR=_DETECTIONBOX,
DESCRIPTOR=_DETECTIONBOX, __module__='detection_result_pb2'
__module__='detection_result_pb2' # @@protoc_insertion_point(class_scope:PaddleSolution.DetectionBox)
# @@protoc_insertion_point(class_scope:PaddleSolution.DetectionBox) ))
))
_sym_db.RegisterMessage(DetectionBox) _sym_db.RegisterMessage(DetectionBox)
DetectionResult = _reflection.GeneratedProtocolMessageType( DetectionResult = _reflection.GeneratedProtocolMessageType(
'DetectionResult', 'DetectionResult',
(_message.Message, ), (_message.Message,),
dict( dict(DESCRIPTOR=_DETECTIONRESULT,
DESCRIPTOR=_DETECTIONRESULT, __module__='detection_result_pb2'
__module__='detection_result_pb2' # @@protoc_insertion_point(class_scope:PaddleSolution.DetectionResult)
# @@protoc_insertion_point(class_scope:PaddleSolution.DetectionResult) ))
))
_sym_db.RegisterMessage(DetectionResult) _sym_db.RegisterMessage(DetectionResult)
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)
...@@ -85,8 +85,8 @@ if __name__ == "__main__": ...@@ -85,8 +85,8 @@ if __name__ == "__main__":
for box in detection_result.detection_boxes: for box in detection_result.detection_boxes:
if box.score >= Flags.threshold: if box.score >= Flags.threshold:
box_class = getattr(box, 'class') box_class = getattr(box, 'class')
text_class_score_str = "%s %.2f" % ( text_class_score_str = "%s %.2f" % (class2LabelMap.get(
class2LabelMap.get(str(box_class)), box.score) str(box_class)), box.score)
text_point = (int(box.left_top_x), int(box.left_top_y)) text_point = (int(box.left_top_x), int(box.left_top_y))
ptLeftTop = (int(box.left_top_x), int(box.left_top_y)) ptLeftTop = (int(box.left_top_x), int(box.left_top_y))
...@@ -106,8 +106,8 @@ if __name__ == "__main__": ...@@ -106,8 +106,8 @@ if __name__ == "__main__":
text_box_left_top = (text_point[0], text_box_left_top = (text_point[0],
text_point[1] - text_size[0][1]) text_point[1] - text_size[0][1])
text_box_right_bottom = ( text_box_right_bottom = (text_point[0] +
text_point[0] + text_size[0][0], text_point[1]) text_size[0][0], text_point[1])
cv2.rectangle(img, text_box_left_top, cv2.rectangle(img, text_box_left_top,
text_box_right_bottom, color, -1, 8) text_box_right_bottom, color, -1, 8)
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
...@@ -13,225 +13,285 @@ ...@@ -13,225 +13,285 @@
// limitations under the License. // limitations under the License.
#pragma once #pragma once
#include <yaml-cpp/yaml.h>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <map> #include <map>
#include <yaml-cpp/yaml.h>
namespace PaddleSolution { namespace PaddleSolution {
class PaddleModelConfigPaser { class PaddleModelConfigPaser {
std::map<std::string, int> _scaling_map; std::map<std::string, int> _scaling_map;
public:
PaddleModelConfigPaser()
:_class_num(0),
_channels(0),
_use_gpu(0),
_batch_size(1),
_target_short_size(0),
_model_file_name("__model__"),
_param_file_name("__params__"),
_scaling_map{{"UNPADDING", 0},
{"RANGE_SCALING",1}},
_feeds_size(1),
_coarsest_stride(1)
{
}
~PaddleModelConfigPaser() {
}
void reset() { public:
_crop_size.clear(); PaddleModelConfigPaser()
_resize.clear(); :_class_num(0),
_mean.clear(); _channels(0),
_std.clear(); _use_gpu(0),
_img_type.clear(); _batch_size(1),
_class_num = 0; _target_short_size(0),
_channels = 0; _model_file_name("__model__"),
_use_gpu = 0; _param_file_name("__params__"),
_target_short_size = 0; _scaling_map{{"UNPADDING", 0},
_batch_size = 1; {"RANGE_SCALING", 1}},
_model_file_name = "__model__"; _feeds_size(1),
_model_path = "./"; _coarsest_stride(1) {}
_param_file_name="__params__";
_resize_type = 0;
_resize_max_size = 0;
_feeds_size = 1;
_coarsest_stride = 1;
}
std::string process_parenthesis(const std::string& str) { ~PaddleModelConfigPaser() {}
if (str.size() < 2) {
return str;
}
std::string nstr(str);
if (str[0] == '(' && str.back() == ')') {
nstr[0] = '[';
nstr[str.size() - 1] = ']';
}
return nstr;
}
template <typename T> void reset() {
std::vector<T> parse_str_to_vec(const std::string& str) { _crop_size.clear();
std::vector<T> data; _resize.clear();
auto node = YAML::Load(str); _mean.clear();
for (const auto& item : node) { _std.clear();
data.push_back(item.as<T>()); _img_type.clear();
} _class_num = 0;
return data; _channels = 0;
_use_gpu = 0;
_target_short_size = 0;
_batch_size = 1;
_model_file_name = "__model__";
_model_path = "./";
_param_file_name = "__params__";
_resize_type = 0;
_resize_max_size = 0;
_feeds_size = 1;
_coarsest_stride = 1;
}
std::string process_parenthesis(const std::string& str) {
if (str.size() < 2) {
return str;
}
std::string nstr(str);
if (str[0] == '(' && str.back() == ')') {
nstr[0] = '[';
nstr[str.size() - 1] = ']';
} }
return nstr;
}
bool load_config(const std::string& conf_file) { template <typename T>
std::vector<T> parse_str_to_vec(const std::string& str) {
reset(); std::vector<T> data;
auto node = YAML::Load(str);
for (const auto& item : node) {
data.push_back(item.as<T>());
}
return data;
}
YAML::Node config = YAML::LoadFile(conf_file); bool load_config(const std::string& conf_file) {
// 1. get resize reset();
YAML::Node config;
try {
config = YAML::LoadFile(conf_file);
} catch(...) {
return false;
}
// 1. get resize
if (config["DEPLOY"]["EVAL_CROP_SIZE"].IsDefined()) {
auto str = config["DEPLOY"]["EVAL_CROP_SIZE"].as<std::string>(); auto str = config["DEPLOY"]["EVAL_CROP_SIZE"].as<std::string>();
_resize = parse_str_to_vec<int>(process_parenthesis(str)); _resize = parse_str_to_vec<int>(process_parenthesis(str));
} else {
std::cerr << "Please set EVAL_CROP_SIZE: (xx, xx)" << std::endl;
return false;
}
// 0. get crop_size
if (config["DEPLOY"]["CROP_SIZE"].IsDefined()) {
auto crop_str = config["DEPLOY"]["CROP_SIZE"].as<std::string>();
_crop_size = parse_str_to_vec<int>(process_parenthesis(crop_str));
} else {
_crop_size = _resize;
}
// 0. get crop_size // 2. get mean
if(config["DEPLOY"]["CROP_SIZE"].IsDefined()) { if (config["DEPLOY"]["MEAN"].IsDefined()) {
auto crop_str = config["DEPLOY"]["CROP_SIZE"].as<std::string>();
_crop_size = parse_str_to_vec<int>(process_parenthesis(crop_str));
}
else {
_crop_size = _resize;
}
// 2. get mean
for (const auto& item : config["DEPLOY"]["MEAN"]) { for (const auto& item : config["DEPLOY"]["MEAN"]) {
_mean.push_back(item.as<float>()); _mean.push_back(item.as<float>());
} }
} else {
// 3. get std std::cerr << "Please set MEAN: [xx, xx, xx]" << std::endl;
return false;
}
// 3. get std
if(config["DEPLOY"]["STD"].IsDefined()) {
for (const auto& item : config["DEPLOY"]["STD"]) { for (const auto& item : config["DEPLOY"]["STD"]) {
_std.push_back(item.as<float>()); _std.push_back(item.as<float>());
} }
} else {
// 4. get image type std::cerr << "Please set STD: [xx, xx, xx]" << std::endl;
return false;
}
// 4. get image type
if (config["DEPLOY"]["IMAGE_TYPE"].IsDefined()) {
_img_type = config["DEPLOY"]["IMAGE_TYPE"].as<std::string>(); _img_type = config["DEPLOY"]["IMAGE_TYPE"].as<std::string>();
// 5. get class number } else {
std::cerr << "Please set IMAGE_TYPE: \"rgb\" or \"rgba\"" << std::endl;
return false;
}
// 5. get class number
if (config["DEPLOY"]["NUM_CLASSES"].IsDefined()) {
_class_num = config["DEPLOY"]["NUM_CLASSES"].as<int>(); _class_num = config["DEPLOY"]["NUM_CLASSES"].as<int>();
// 7. set model path } else {
std::cerr << "Please set NUM_CLASSES: x" << std::endl;
return false;
}
// 7. set model path
if (config["DEPLOY"]["MODEL_PATH"].IsDefined()) {
_model_path = config["DEPLOY"]["MODEL_PATH"].as<std::string>(); _model_path = config["DEPLOY"]["MODEL_PATH"].as<std::string>();
// 8. get model file_name } else {
std::cerr << "Please set MODEL_PATH: \"/path/to/model_dir\"" << std::endl;
return false;
}
// 8. get model file_name
if (config["DEPLOY"]["MODEL_FILENAME"].IsDefined()) {
_model_file_name = config["DEPLOY"]["MODEL_FILENAME"].as<std::string>(); _model_file_name = config["DEPLOY"]["MODEL_FILENAME"].as<std::string>();
// 9. get model param file name } else {
_param_file_name = config["DEPLOY"]["PARAMS_FILENAME"].as<std::string>(); _model_file_name = "__model__";
// 10. get pre_processor }
// 9. get model param file name
if (config["DEPLOY"]["PARAMS_FILENAME"].IsDefined()) {
_param_file_name
= config["DEPLOY"]["PARAMS_FILENAME"].as<std::string>();
} else {
_param_file_name = "__params__";
}
// 10. get pre_processor
if (config["DEPLOY"]["PRE_PROCESSOR"].IsDefined()) {
_pre_processor = config["DEPLOY"]["PRE_PROCESSOR"].as<std::string>(); _pre_processor = config["DEPLOY"]["PRE_PROCESSOR"].as<std::string>();
// 11. use_gpu } else {
std::cerr << "Please set PRE_PROCESSOR: \"DetectionPreProcessor\"" << std::endl;
return false;
}
// 11. use_gpu
if (config["DEPLOY"]["USE_GPU"].IsDefined()) {
_use_gpu = config["DEPLOY"]["USE_GPU"].as<int>(); _use_gpu = config["DEPLOY"]["USE_GPU"].as<int>();
// 12. predictor_mode } else {
_use_gpu = 0;
}
// 12. predictor_mode
if (config["DEPLOY"]["PREDICTOR_MODE"].IsDefined()) {
_predictor_mode = config["DEPLOY"]["PREDICTOR_MODE"].as<std::string>(); _predictor_mode = config["DEPLOY"]["PREDICTOR_MODE"].as<std::string>();
// 13. batch_size } else {
std::cerr << "Please set PREDICTOR_MODE: \"NATIVE\" or \"ANALYSIS\"" << std::endl;
return false;
}
// 13. batch_size
if (config["DEPLOY"]["BATCH_SIZE"].IsDefined()) {
_batch_size = config["DEPLOY"]["BATCH_SIZE"].as<int>(); _batch_size = config["DEPLOY"]["BATCH_SIZE"].as<int>();
// 14. channels } else {
_batch_size = 1;
}
// 14. channels
if (config["DEPLOY"]["CHANNELS"].IsDefined()) {
_channels = config["DEPLOY"]["CHANNELS"].as<int>(); _channels = config["DEPLOY"]["CHANNELS"].as<int>();
// 15. target_short_size } else {
if(config["DEPLOY"]["TARGET_SHORT_SIZE"].IsDefined()) { std::cerr << "Please set CHANNELS: x" << std::endl;
_target_short_size = config["DEPLOY"]["TARGET_SHORT_SIZE"].as<int>(); return false;
} }
// 16.resize_type // 15. target_short_size
if(config["DEPLOY"]["RESIZE_TYPE"].IsDefined() && if (config["DEPLOY"]["TARGET_SHORT_SIZE"].IsDefined()) {
_scaling_map.find(config["DEPLOY"]["RESIZE_TYPE"].as<std::string>()) != _scaling_map.end()) { _target_short_size = config["DEPLOY"]["TARGET_SHORT_SIZE"].as<int>();
_resize_type = _scaling_map[config["DEPLOY"]["RESIZE_TYPE"].as<std::string>()]; }
} // 16.resize_type
else{ if (config["DEPLOY"]["RESIZE_TYPE"].IsDefined() &&
_resize_type = 0; _scaling_map.find(config["DEPLOY"]["RESIZE_TYPE"].as<std::string>()) != _scaling_map.end()) {
} _resize_type = _scaling_map[config["DEPLOY"]["RESIZE_TYPE"].as<std::string>()];
// 17.resize_max_size } else {
if(config["DEPLOY"]["RESIZE_MAX_SIZE"].IsDefined()) { _resize_type = 0;
_resize_max_size = config["DEPLOY"]["RESIZE_MAX_SIZE"].as<int>(); }
} // 17.resize_max_size
// 18.feeds_size if (config["DEPLOY"]["RESIZE_MAX_SIZE"].IsDefined()) {
if(config["DEPLOY"]["FEEDS_SIZE"].IsDefined()){ _resize_max_size = config["DEPLOY"]["RESIZE_MAX_SIZE"].as<int>();
_feeds_size = config["DEPLOY"]["FEEDS_SIZE"].as<int>();
}
// 19. coarsest_stride
if(config["DEPLOY"]["COARSEST_STRIDE"].IsDefined()) {
_coarsest_stride = config["DEPLOY"]["COARSEST_STRIDE"].as<int>();
}
return true;
} }
// 18.feeds_size
if (config["DEPLOY"]["FEEDS_SIZE"].IsDefined()) {
_feeds_size = config["DEPLOY"]["FEEDS_SIZE"].as<int>();
}
// 19. coarsest_stride
if (config["DEPLOY"]["COARSEST_STRIDE"].IsDefined()) {
_coarsest_stride = config["DEPLOY"]["COARSEST_STRIDE"].as<int>();
}
return true;
}
void debug() const { void debug() const {
std::cout << "SCALE_RESIZE: (" << _resize[0] << ", "
std::cout << "SCALE_RESIZE: (" << _resize[0] << ", " << _resize[1] << ")" << std::endl; << _resize[1] << ")" << std::endl;
std::cout << "MEAN: ["; std::cout << "MEAN: [";
for (int i = 0; i < _mean.size(); ++i) { for (int i = 0; i < _mean.size(); ++i) {
if (i != _mean.size() - 1) { if (i != _mean.size() - 1) {
std::cout << _mean[i] << ", "; std::cout << _mean[i] << ", ";
} else { } else {
std::cout << _mean[i]; std::cout << _mean[i];
}
} }
std::cout << "]" << std::endl; }
std::cout << "]" << std::endl;
std::cout << "STD: ["; std::cout << "STD: [";
for (int i = 0; i < _std.size(); ++i) { for (int i = 0; i < _std.size(); ++i) {
if (i != _std.size() - 1) { if (i != _std.size() - 1) {
std::cout << _std[i] << ", "; std::cout << _std[i] << ", ";
} } else {
else { std::cout << _std[i];
std::cout << _std[i];
}
} }
std::cout << "]" << std::endl; }
std::cout << "DEPLOY.TARGET_SHORT_SIZE: " << _target_short_size << std::endl; std::cout << "]" << std::endl;
std::cout << "DEPLOY.IMAGE_TYPE: " << _img_type << std::endl; std::cout << "DEPLOY.TARGET_SHORT_SIZE: " << _target_short_size
std::cout << "DEPLOY.NUM_CLASSES: " << _class_num << std::endl; << std::endl;
std::cout << "DEPLOY.CHANNELS: " << _channels << std::endl; std::cout << "DEPLOY.IMAGE_TYPE: " << _img_type << std::endl;
std::cout << "DEPLOY.MODEL_PATH: " << _model_path << std::endl; std::cout << "DEPLOY.NUM_CLASSES: " << _class_num << std::endl;
std::cout << "DEPLOY.MODEL_FILENAME: " << _model_file_name << std::endl; std::cout << "DEPLOY.CHANNELS: " << _channels << std::endl;
std::cout << "DEPLOY.PARAMS_FILENAME: " << _param_file_name << std::endl; std::cout << "DEPLOY.MODEL_PATH: " << _model_path << std::endl;
std::cout << "DEPLOY.PRE_PROCESSOR: " << _pre_processor << std::endl; std::cout << "DEPLOY.MODEL_FILENAME: " << _model_file_name
std::cout << "DEPLOY.USE_GPU: " << _use_gpu << std::endl; << std::endl;
std::cout << "DEPLOY.PREDICTOR_MODE: " << _predictor_mode << std::endl; std::cout << "DEPLOY.PARAMS_FILENAME: " << _param_file_name
std::cout << "DEPLOY.BATCH_SIZE: " << _batch_size << std::endl; << std::endl;
} std::cout << "DEPLOY.PRE_PROCESSOR: " << _pre_processor << std::endl;
//DEPLOY.COARSEST_STRIDE std::cout << "DEPLOY.USE_GPU: " << _use_gpu << std::endl;
int _coarsest_stride; std::cout << "DEPLOY.PREDICTOR_MODE: " << _predictor_mode << std::endl;
// DEPLOY.FEEDS_SIZE std::cout << "DEPLOY.BATCH_SIZE: " << _batch_size << std::endl;
int _feeds_size; }
// DEPLOY.RESIZE_TYPE 0:unpadding 1:rangescaling Default:0 // DEPLOY.COARSEST_STRIDE
int _resize_type; int _coarsest_stride;
// DEPLOY.RESIZE_MAX_SIZE // DEPLOY.FEEDS_SIZE
int _resize_max_size; int _feeds_size;
// DEPLOY.CROP_SIZE // DEPLOY.RESIZE_TYPE 0:unpadding 1:rangescaling Default:0
std::vector<int> _crop_size; int _resize_type;
// DEPLOY.SCALE_RESIZE // DEPLOY.RESIZE_MAX_SIZE
std::vector<int> _resize; int _resize_max_size;
// DEPLOY.MEAN // DEPLOY.CROP_SIZE
std::vector<float> _mean; std::vector<int> _crop_size;
// DEPLOY.STD // DEPLOY.SCALE_RESIZE
std::vector<float> _std; std::vector<int> _resize;
// DEPLOY.IMAGE_TYPE // DEPLOY.MEAN
std::string _img_type; std::vector<float> _mean;
// DEPLOY.TARGET_SHORT_SIZE // DEPLOY.STD
int _target_short_size; std::vector<float> _std;
// DEPLOY.NUM_CLASSES // DEPLOY.IMAGE_TYPE
int _class_num; std::string _img_type;
// DEPLOY.CHANNELS // DEPLOY.TARGET_SHORT_SIZE
int _channels; int _target_short_size;
// DEPLOY.MODEL_PATH // DEPLOY.NUM_CLASSES
std::string _model_path; int _class_num;
// DEPLOY.MODEL_FILENAME // DEPLOY.CHANNELS
std::string _model_file_name; int _channels;
// DEPLOY.PARAMS_FILENAME // DEPLOY.MODEL_PATH
std::string _param_file_name; std::string _model_path;
// DEPLOY.PRE_PROCESSOR // DEPLOY.MODEL_FILENAME
std::string _pre_processor; std::string _model_file_name;
// DEPLOY.USE_GPU // DEPLOY.PARAMS_FILENAME
int _use_gpu; std::string _param_file_name;
// DEPLOY.PREDICTOR_MODE // DEPLOY.PRE_PROCESSOR
std::string _predictor_mode; std::string _pre_processor;
// DEPLOY.BATCH_SIZE // DEPLOY.USE_GPU
int _batch_size; int _use_gpu;
}; // DEPLOY.PREDICTOR_MODE
std::string _predictor_mode;
} // DEPLOY.BATCH_SIZE
int _batch_size;
};
} // namespace PaddleSolution
...@@ -28,97 +28,103 @@ ...@@ -28,97 +28,103 @@
#endif #endif
namespace PaddleSolution { namespace PaddleSolution {
namespace utils { namespace utils {
enum SCALE_TYPE{
UNPADDING, enum SCALE_TYPE{
RANGE_SCALING UNPADDING,
}; RANGE_SCALING
inline std::string path_join(const std::string& dir, const std::string& path) { };
std::string seperator = "/";
#ifdef _WIN32 inline std::string path_join(const std::string& dir, const std::string& path) {
seperator = "\\"; std::string seperator = "/";
#endif #ifdef _WIN32
return dir + seperator + path; seperator = "\\";
#endif
return dir + seperator + path;
}
#ifndef _WIN32
// scan a directory and get all files with input extensions
inline std::vector<std::string> get_directory_images(const std::string& path,
const std::string& exts) {
std::vector<std::string> imgs;
struct dirent *entry;
DIR *dir = opendir(path.c_str());
if (dir == NULL) {
closedir(dir);
return imgs;
}
while ((entry = readdir(dir)) != NULL) {
std::string item = entry->d_name;
auto ext = strrchr(entry->d_name, '.');
if (!ext || std::string(ext) == "." || std::string(ext) == "..") {
continue;
} }
#ifndef _WIN32 if (exts.find(ext) != std::string::npos) {
// scan a directory and get all files with input extensions imgs.push_back(path_join(path, entry->d_name));
inline std::vector<std::string> get_directory_images(const std::string& path, const std::string& exts) }
{ }
std::vector<std::string> imgs; sort(imgs.begin(), imgs.end());
struct dirent *entry; return imgs;
DIR *dir = opendir(path.c_str()); }
if (dir == NULL) { #else
closedir(dir); // scan a directory and get all files with input extensions
return imgs; inline std::vector<std::string> get_directory_images(const std::string& path,
} const std::string& exts) {
std::vector<std::string> imgs;
for (const auto& item :
std::experimental::filesystem::directory_iterator(path)) {
auto suffix = item.path().extension().string();
if (exts.find(suffix) != std::string::npos && suffix.size() > 0) {
auto fullname = path_join(path, item.path().filename().string());
imgs.push_back(item.path().string());
}
}
sort(imgs.begin(), imgs.end());
return imgs;
}
#endif
while ((entry = readdir(dir)) != NULL) { inline int scaling(int resize_type, int &w, int &h, int new_w, int new_h,
std::string item = entry->d_name; int target_size, int max_size, float &im_scale_ratio) {
auto ext = strrchr(entry->d_name, '.'); if (w <= 0 || h <= 0 || new_w <= 0 || new_h <= 0) {
if (!ext || std::string(ext) == "." || std::string(ext) == "..") { return -1;
continue; }
} switch (resize_type) {
if (exts.find(ext) != std::string::npos) { case SCALE_TYPE::UNPADDING:
imgs.push_back(path_join(path, entry->d_name)); {
} w = new_w;
} h = new_h;
sort(imgs.begin(), imgs.end()); im_scale_ratio = 0;
return imgs;
} }
#else break;
// scan a directory and get all files with input extensions case SCALE_TYPE::RANGE_SCALING:
inline std::vector<std::string> get_directory_images(const std::string& path, const std::string& exts)
{ {
std::vector<std::string> imgs; int im_max_size = std::max(w, h);
for (const auto& item : std::experimental::filesystem::directory_iterator(path)) { int im_min_size = std::min(w, h);
auto suffix = item.path().extension().string(); float scale_ratio = static_cast<float>(target_size)
if (exts.find(suffix) != std::string::npos && suffix.size() > 0) { / static_cast<float>(im_min_size);
auto fullname = path_join(path, item.path().filename().string()); if (max_size > 0) {
imgs.push_back(item.path().string()); if (round(scale_ratio * im_max_size) > max_size) {
scale_ratio = static_cast<float>(max_size)
/ static_cast<float>(im_max_size);
} }
} }
sort(imgs.begin(), imgs.end()); w = round(scale_ratio * static_cast<float>(w));
return imgs; h = round(scale_ratio * static_cast<float>(h));
im_scale_ratio = scale_ratio;
} }
#endif break;
default :
inline int scaling(int resize_type, int &w, int &h, int new_w, int new_h, int target_size, int max_size, float &im_scale_ratio) {
{ std::cout << "Can't support this type of scaling strategy."
if(w <= 0 || h <= 0 || new_w <= 0 || new_h <= 0){ << std::endl;
return -1; std::cout << "Throw exception at file " << __FILE__
} << " on line " << __LINE__ << std::endl;
switch(resize_type) { throw 0;
case SCALE_TYPE::UNPADDING: }
{ break;
w = new_w;
h = new_h;
im_scale_ratio=0;
}
break;
case SCALE_TYPE::RANGE_SCALING:
{
int im_max_size = std::max(w, h);
int im_min_size = std::min(w, h);
float scale_ratio= static_cast<float>(target_size) / static_cast<float>(im_min_size);
if(max_size > 0) {
if(round(scale_ratio * im_max_size) > max_size) {
scale_ratio = static_cast<float>(max_size) / static_cast<float>(im_max_size);
}
}
w = round(scale_ratio * static_cast<float>(w));
h = round(scale_ratio * static_cast<float>(h));
im_scale_ratio = scale_ratio;
}
break;
default :
{
std::cout << "Can't support this type of scaling strategy." << std::endl;
std::cout << "Throw exception at file " << __FILE__ << " on line " << __LINE__ << std::endl;
throw 0;
}
break;
}
return 0;
}
} }
return 0;
} }
} // namespace utils
} // namespace PaddleSolution
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册