[Model] Add Paddle3D smoke model (#1766)

* add smoke model

* add 3d vis

* update code

* update doc

* mv paddle3d from detection to perception

* update result for velocity

* update code for CI

* add set input data for TRT backend

* add serving support for smoke model

* update code

* update code

* update code

---------

Co-authored-by: DefTruth <31974251+DefTruth@users.noreply.github.com>
This commit is contained in:
yeliang2258
2023-04-14 16:30:56 +08:00
committed by GitHub
parent 81fbd54c9d
commit a509dd8ec1
53 changed files with 2610 additions and 26 deletions

View File

@@ -199,6 +199,6 @@ else()
endif()
find_package(OpenCV REQUIRED PATHS ${OpenCV_DIR} NO_DEFAULT_PATH)
include_directories(${OpenCV_INCLUDE_DIRS})
list(APPEND DEPEND_LIBS opencv_core opencv_video opencv_highgui opencv_imgproc opencv_imgcodecs)
list(APPEND DEPEND_LIBS opencv_core opencv_video opencv_highgui opencv_imgproc opencv_imgcodecs opencv_calib3d opencv_features2d opencv_flann)
endif()
endif()

View File

@@ -0,0 +1,48 @@
English | [简体中文](detection_result_CN.md)
# PerceptionResult target detection result
The PerceptionResult code is defined in `fastdeploy/vision/common/result.h`, which is used to indicate the detected 3D target: two-dimensional target frame, target frame length, width and height, target category and target confidence, target orientation angle and observation angle etc.
## C++ definition
```c++
fastdeploy::vision::PerceptionResult
```
```c++
struct PerceptionResult {
std::vector<float> scores;
std::vector<int32_t> label_ids;
std::vector<std::array<float, 7>> boxes;
std::vector<std::array<float, 3>> center;
std::vector<float>observation_angle;
std::vector<float>yaw_angle;
std::vector<std::array<float, 3>>velocity;
void Clear();
std::string Str();
};
```
- **scores**: Member variable, indicating the confidence of all detected targets, `scores.size()` indicates the number of detected boxes
- **label_ids**: Member variable, representing all detected target categories, the number of elements is consistent with `scores.size()`
- **boxes**: Member variable, representing the coordinates of all detected target boxes, the number of elements is consistent with `scores.size()`, and each box represents xmin, ymin, xmax, ymax in turn with 7 float values , h, w, l, the coordinates of the upper left and lower right corners and the length, width and height of the 3D box
- **center**: member variable, indicating the center point coordinates of all detected target frames, the number of elements is consistent with `scores.size()`, and each frame uses 3 float values to represent the center point coordinates of the frame in turn
- **observation_angle**: Member variable, indicating the observation angle of the detected frame, and the number of elements is consistent with `scores.size()`
- **yaw_angle**: Member variable, indicating the orientation angle of the detected frame, the number of elements is consistent with `scores.size()`
- **velocity**: Member variable, indicating the velocity of the detected frame, the number of elements is consistent with `scores.size()`
- **Clear()**: member function, used to clear the results stored in the structure
- **Str()**: member function, output the information in the structure as a string (for Debug)
## Python definition
```python
fastdeploy.vision.PerceptionResult
```
- **scores**(list of float): Member variable, indicating the confidence of all detected targets, `scores.size()` indicates the number of detected frames
- **label_ids**(list of int): Member variable, representing all detected target categories, the number of elements is consistent with `scores.size()`
- **boxes**(list of list(float)): Member variable, indicating the coordinates of all detected target boxes, the number of elements is the same as `scores.size()`, and each box is in order of 7 float values Indicates xmin, ymin, xmax, ymax, h, w, l, that is, the coordinates of the upper left and lower right corners and the length, width and height of the 3D box
- **center**(list of list(float)): Member variable, which represents the coordinates of the center points of all detected target frames, the number of elements is the same as `scores.size()`, and each frame is represented by 3 floats The values in turn represent the coordinates of the center point of the box
- **observation_angle**: member variable, indicating the orientation angle of the detected frame, and the number of elements is consistent with `scores.size()`
- **yaw_angle**: Member variable, indicating the orientation angle of the detected frame, the number of elements is consistent with `scores.size()`
- **velocity**: Member variable, indicating the velocity of the detected frame, the number of elements is consistent with `scores.size()`

View File

@@ -0,0 +1,48 @@
简体中文 [English](perception_result.md)
# PerceptionResult 目标检测结果
PerceptionResult`fastdeploy/vision/common/result.h`用于表明检测出来的3D目标的二维目标框、目标框长宽高、目标类别和目标置信度、目标朝向角和观测角等。
## C++ 定义
```c++
fastdeploy::vision::PerceptionResult
```
```c++
struct PerceptionResult {
std::vector<float> scores;
std::vector<int32_t> label_ids;
std::vector<std::array<float, 7>> boxes;
std::vector<std::array<float, 3>> center;
std::vector<float>observation_angle;
std::vector<float>yaw_angle;
std::vector<std::array<float, 3>>velocity;
void Clear();
std::string Str();
};
```
- **scores**: 成员变量,表示检测出来的所有目标置信度,`scores.size()`表示检测出来框的个数
- **label_ids**: 成员变量,表示检测出来的所有目标类别,其元素个数与`scores.size()`一致
- **boxes**: 成员变量,表示检测出来的所有目标框坐标,其元素个数与`scores.size()`一致每个框以7个float数值依次表示xmin, ymin, xmax, ymaxh, w, l 即左上角和右下角坐标以及3D框的长宽高
- **center**: 成员变量,表示检测出来的所有目标框中心点坐标,其元素个数与`scores.size()`一致每个框以3个float数值依次表示框中心点坐标
- **observation_angle**: 成员变量,表示检测出来的框的观测角,其元素个数与`scores.size()`一致
- **yaw_angle**: 成员变量,表示检测出来的框的朝向角,其元素个数与`scores.size()`一致
- **velocity**: 成员变量,表示检测出来的框的速度,其元素个数与`scores.size()`一致
- **Clear()**: 成员函数,用于清除结构体中存储的结果
- **Str()**: 成员函数将结构体中的信息以字符串形式输出用于Debug
## Python 定义
```python
fastdeploy.vision.PerceptionResult
```
- **scores**(list of float): 成员变量,表示检测出来的所有目标置信度,`scores.size()`表示检测出来框的个数
- **label_ids**(list of int): 成员变量,表示检测出来的所有目标类别,其元素个数与`scores.size()`一致
- **boxes**(list of list(float)): 成员变量,表示检测出来的所有目标框坐标,其元素个数与`scores.size()`一致每个框以7个float数值依次表示xmin, ymin, xmax, ymaxh, w, l 即左上角和右下角坐标以及3D框的长宽高
- **center**(list of list(float)): 成员变量,表示检测出来的所有目标框中心点坐标,其元素个数与`scores.size()`一致每个框以3个float数值依次表示框中心点坐标
- **observation_angle**: 成员变量,表示检测出来的框的朝向角,其元素个数与`scores.size()`一致
- **yaw_angle**: 成员变量,表示检测出来的框的朝向角,其元素个数与`scores.size()`一致
- **velocity**: 成员变量,表示检测出来的框的速度,其元素个数与`scores.size()`一致

View File

@@ -0,0 +1,11 @@
English | [简体中文](README_CN.md)
# Smoke Ready-to-deploy Model
The Smoke deployment model implements the Smoke model from Paddle3D. For more detailed information about the model, please refer to [Smoke Introduction](https://github.com/PaddlePaddle/Paddle3D/tree/develop/docs/models/smoke)
## Detailed Deployment Documents
- [Python Deployment](python)
- [C++ Deployment](cpp)

View File

@@ -0,0 +1,12 @@
[English](README.md) | 简体中文
# Smoke 准备部署模型
Smoke 部署模型实现来自 Paddle3D 的 Smoke 模型,模型相关的更多详细信息可以参考[Smoke 介绍](https://github.com/PaddlePaddle/Paddle3D/tree/develop/docs/models/smoke)
## 详细部署文档
- [Python部署](python)
- [C++部署](cpp)

View File

@@ -0,0 +1,14 @@
PROJECT(infer_demo C CXX)
CMAKE_MINIMUM_REQUIRED (VERSION 3.10)
# 指定下载解压后的fastdeploy库路径
option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.")
include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake)
# 添加FastDeploy依赖头文件
include_directories(${FASTDEPLOY_INCS})
add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc)
# 添加FastDeploy库依赖
target_link_libraries(infer_demo ${FASTDEPLOY_LIBS})

View File

@@ -0,0 +1,80 @@
English | [简体中文](README_CN.md)
# Smoke C++ Deployment Example
This directory provides an example of `infer.cc` to quickly complete the deployment of Smoke on CPU/GPU.
Before deployment, the following two steps need to be confirmed
- 1. The hardware and software environment meets the requirements, refer to [FastDeploy environment requirements](../../../../../docs/en/build_and_install/download_prebuilt_libraries.md)
- 2. According to the development environment, download the precompiled deployment library and samples code, refer to [FastDeploy prebuilt library](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
Taking CPU inference on Linux as an example, execute the following command in this directory to complete the compilation test. To support this model, you need to ensure FastDeploy version 1.0.6 or higher (x.x.x>=1.0.6)
```bash
mkdir build
cd build
# Download the FastDeploy precompiled library, users can choose the appropriate version to use in the `FastDeploy precompiled library` mentioned above
wget https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-x.x.x.tgz
tar xvf fastdeploy-linux-x64-x.x.x.tgz
cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/fastdeploy-linux-x64-x.x.x
make -j
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# CPU
./infer_demo smoke smoke_test.png 0
# GPU
./infer_demo smoke smoke_test.png 1
```
The visual result after running is shown in the figure below
<img width="640" src="https://user-images.githubusercontent.com/30516196/230387825-53ac0a09-4137-4e49-9564-197cbc30ff08.png">
The above commands are only applicable to Linux or MacOS. For the usage of SDK under Windows, please refer to:
- [How to use FastDeploy C++ SDK in Windows](../../../../../docs/en/faq/use_sdk_on_windows.md)
## Smoke C++ interface
### Class Smoke
```c++
fastdeploy::vision::detection::Smoke(
const string& model_file,
const string& params_file,
const string& config_file,
const RuntimeOption& runtime_option = RuntimeOption(),
const ModelFormat& model_format = ModelFormat::PADDLE)
```
Smoke model loading and initialization.
**parameter**
> * **model_file**(str): model file path
> * **params_file**(str): parameter file path
> * **config_file**(str): configuration file path
> * **runtime_option**(RuntimeOption): Backend reasoning configuration, the default is None, that is, the default configuration is used
> * **model_format**(ModelFormat): model format, the default is Paddle format
#### Predict function
> ```c++
> Smoke::Predict(cv::Mat* im, PerceptionResult* result)
> ```
>
> Model prediction interface, the input image directly outputs the detection result.
>
> **parameters**
>
> > * **im**: input image, note that it must be in HWC, BGR format
> > * **result**: Detection result, including the detection frame, the confidence of each frame, PerceptionResult description reference [visual model prediction results](../../../../../docs/api /vision_results/)
- [Model Introduction](../../)
- [Python deployment](../python)
- [Vision Model Prediction Results](../../../../../docs/api/vision_results/)
- [How to switch model inference backend engine](../../../../../docs/en/faq/how_to_change_backend.md)

View File

@@ -0,0 +1,80 @@
[English](README.md) | 简体中文
# Smoke C++部署示例
本目录下提供 `infer.cc` 快速完成 Smoke 在 CPU/GPU 上部署的示例。
在部署前,需确认以下两个步骤
- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
- 2. 根据开发环境下载预编译部署库和samples代码参考[FastDeploy预编译库](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
以Linux上 CPU 推理为例,在本目录执行如下命令即可完成编译测试,支持此模型需保证 FastDeploy 版本1.0.6以上(x.x.x>=1.0.6)
```bash
mkdir build
cd build
# 下载FastDeploy预编译库用户可在上文提到的`FastDeploy预编译库`中自行选择合适的版本使用
wget https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-x.x.x.tgz
tar xvf fastdeploy-linux-x64-x.x.x.tgz
cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/fastdeploy-linux-x64-x.x.x
make -j
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# CPU推理
./infer_demo smoke smoke_test.png 0
# GPU推理
./infer_demo smoke smoke_test.png 1
```
运行完成可视化结果如下图所示
<img width="640" src="https://user-images.githubusercontent.com/30516196/230387825-53ac0a09-4137-4e49-9564-197cbc30ff08.png">
以上命令只适用于Linux或MacOS, Windows下SDK的使用方式请参考:
- [如何在Windows中使用FastDeploy C++ SDK](../../../../../docs/cn/faq/use_sdk_on_windows.md)
## Smoke C++ 接口
### Smoke 类
```c++
fastdeploy::vision::detection::Smoke(
const string& model_file,
const string& params_file,
const string& config_file,
const RuntimeOption& runtime_option = RuntimeOption(),
const ModelFormat& model_format = ModelFormat::PADDLE)
```
Smoke模型加载和初始化。
**参数**
> * **model_file**(str): 模型文件路径
> * **params_file**(str): 参数文件路径
> * **config_file**(str): 配置文件路径
> * **runtime_option**(RuntimeOption): 后端推理配置默认为None即采用默认配置
> * **model_format**(ModelFormat): 模型格式默认为Paddle格式
#### Predict函数
> ```c++
> Smoke::Predict(cv::Mat* im, PerceptionResult* result)
> ```
>
> 模型预测接口,输入图像直接输出检测结果。
>
> **参数**
>
> > * **im**: 输入图像注意需为HWCBGR格式
> > * **result**: 检测结果,包括检测框,各个框的置信度, PerceptionResult 说明参考[视觉模型预测结果](../../../../../docs/api/vision_results/)
- [模型介绍](../../)
- [Python部署](../python)
- [视觉模型预测结果](../../../../../docs/api/vision_results/)
- [如何切换模型推理后端引擎](../../../../../docs/cn/faq/how_to_change_backend.md)

View File

@@ -0,0 +1,83 @@
// Copyright (c) 2022 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.
#include "fastdeploy/vision.h"
#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endif
void InitAndInfer(const std::string& model_dir, const std::string& image_file,
const fastdeploy::RuntimeOption& option) {
auto model_file = model_dir + sep + "smoke.pdmodel";
auto params_file = model_dir + sep + "smoke.pdiparams";
auto config_file = model_dir + sep + "infer_cfg.yml";
fastdeploy::vision::EnableFlyCV();
auto model = fastdeploy::vision::perception::Smoke(
model_file, params_file, config_file, option,
fastdeploy::ModelFormat::PADDLE);
assert(model.Initialized());
auto im = cv::imread(image_file);
fastdeploy::vision::PerceptionResult res;
if (!model.Predict(im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
std::cout << res.Str() << std::endl;
auto vis_im = fastdeploy::vision::VisPerception(im, res, config_file);
cv::imwrite("vis_result.jpg", vis_im);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
}
int main(int argc, char* argv[]) {
if (argc < 4) {
std::cout << "Usage: infer_demo path/to/paddle_model"
"path/to/image "
"run_option, "
"e.g ./infer_demo ./smoke ./00000.png 0"
<< std::endl;
std::cout << "The data type of run_option is int, 0: run with cpu; 1: run "
"with gpu; 2: run with paddle-trt"
<< std::endl;
return -1;
}
fastdeploy::RuntimeOption option;
if (std::atoi(argv[3]) == 0) {
option.UseCpu();
} else if (std::atoi(argv[3]) == 1) {
option.UseGpu();
} else if (std::atoi(argv[3]) == 2) {
option.UseGpu();
option.UseTrtBackend();
option.EnablePaddleToTrt();
option.SetTrtInputShape("images", {1, 3, 384, 1280});
option.SetTrtInputShape("down_ratios", {1, 2});
option.SetTrtInputShape("trans_cam_to_img", {1, 3, 3});
option.SetTrtInputData("trans_cam_to_img",
{721.53771973, 0., 609.55932617, 0., 721.53771973,
172.85400391, 0, 0, 1});
option.EnablePaddleTrtCollectShape();
}
option.UsePaddleBackend();
std::string model_dir = argv[1];
std::string test_image = argv[2];
InitAndInfer(model_dir, test_image, option);
return 0;
}

View File

@@ -0,0 +1,67 @@
English | [简体中文](README_CN.md)
# Smoke Python Deployment Example
Before deployment, the following two steps need to be confirmed
- 1. The hardware and software environment meets the requirements, refer to [FastDeploy environment requirements](../../../../../docs/en/build_and_install/download_prebuilt_libraries.md)
- 2. FastDeploy Python whl package installation, refer to [FastDeploy Python Installation](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
This directory provides an example of `infer.py` to quickly complete the deployment of Smoke on CPU/GPU. Execute the following script to complete
```bash
#Download deployment sample code
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd examples/vision/vision/paddle3d/smoke/python
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# CPU reasoning
python infer.py --model smoke --image smoke_test.png --device cpu
# GPU inference
python infer.py --model smoke --image smoke_test.png --device gpu
```
The visual result after running is shown in the figure below
<img width="640" src="https://user-images.githubusercontent.com/30516196/230387825-53ac0a09-4137-4e49-9564-197cbc30ff08.png">
## Smoke Python interface
```python
fastdeploy.vision.detection.Smoke(model_file, params_file, config_file, runtime_option=None, model_format=ModelFormat.PADDLE)
```
Smoke model loading and initialization.
**parameter**
> * **model_file**(str): model file path
> * **params_file**(str): parameter file path
> * **config_file**(str): configuration file path
> * **runtime_option**(RuntimeOption): Backend reasoning configuration, the default is None, that is, the default configuration is used
> * **model_format**(ModelFormat): model format, the default is Paddle format
### predict function
> ```python
> Smoke. predict(image_data)
> ```
>
> Model prediction interface, the input image directly outputs the detection result.
>
> **parameters**
>
> > * **image_data**(np.ndarray): input data, note that it must be in HWC, BGR format
> **Back**
>
> > Return the `fastdeploy.vision.PerceptionResult` structure, structure description reference document [Vision Model Prediction Results](../../../../../docs/api/vision_results/)
## Other documents
- [Smoke Model Introduction](..)
- [Smoke C++ deployment](../cpp)
- [Description of model prediction results](../../../../../docs/api/vision_results/)
- [How to switch model inference backend engine](../../../../../docs/en/faq/how_to_change_backend.md)

View File

@@ -0,0 +1,68 @@
[English](README.md) | 简体中文
# Smoke Python 部署示例
在部署前,需确认以下两个步骤
- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
- 2. FastDeploy Python whl 包安装,参考[FastDeploy Python安装](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md)
本目录下提供 `infer.py` 快速完成 Smoke 在 CPU/GPU上部署的示例。执行如下脚本即可完成
```bash
#下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd examples/vision/vision/paddle3d/smoke/python
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# CPU推理
python infer.py --model smoke --image smoke_test.png --device cpu
# GPU推理
python infer.py --model smoke --image smoke_test.png --device gpu
```
运行完成可视化结果如下图所示
<img width="640" src="https://user-images.githubusercontent.com/30516196/230387825-53ac0a09-4137-4e49-9564-197cbc30ff08.png">
## Smoke Python接口
```python
fastdeploy.vision.detection.Smoke(model_file, params_file, config_file, runtime_option=None, model_format=ModelFormat.PADDLE)
```
Smoke模型加载和初始化。
**参数**
> * **model_file**(str): 模型文件路径
> * **params_file**(str): 参数文件路径
> * **config_file**(str): 配置文件路径
> * **runtime_option**(RuntimeOption): 后端推理配置默认为None即采用默认配置
> * **model_format**(ModelFormat): 模型格式默认为Paddle格式
### predict 函数
> ```python
> Smoke.predict(image_data)
> ```
>
> 模型预测结口,输入图像直接输出检测结果。
>
> **参数**
>
> > * **image_data**(np.ndarray): 输入数据注意需为HWCBGR格式
> **返回**
>
> > 返回`fastdeploy.vision.PerceptionResult`结构体,结构体说明参考文档[视觉模型预测结果](../../../../../docs/api/vision_results/)
## 其它文档
- [Smoke 模型介绍](..)
- [Smoke C++部署](../cpp)
- [模型预测结果说明](../../../../../docs/api/vision_results/)
- [如何切换模型推理后端引擎](../../../../../docs/cn/faq/how_to_change_backend.md)

View File

@@ -0,0 +1,50 @@
import fastdeploy as fd
import cv2
import os
from fastdeploy import ModelFormat
def parse_arguments():
import argparse
import ast
parser = argparse.ArgumentParser()
parser.add_argument(
"--model", required=True, help="Path of smoke paddle model.")
parser.add_argument(
"--image", required=True, help="Path of test image file.")
parser.add_argument(
"--device",
type=str,
default='cpu',
help="Type of inference device, support 'cpu' or 'gpu'.")
return parser.parse_args()
def build_option(args):
option = fd.RuntimeOption()
if args.device.lower() == "gpu":
option.use_gpu(0)
if args.device.lower() == "cpu":
option.use_cpu()
return option
args = parse_arguments()
model_file = os.path.join(args.model, "smoke.pdmodel")
params_file = os.path.join(args.model, "smoke.pdiparams")
config_file = os.path.join(args.model, "infer_cfg.yml")
# 配置runtime加载模型
runtime_option = build_option(args)
model = fd.vision.perception.Smoke(
model_file, params_file, config_file, runtime_option=runtime_option)
# 预测图片检测结果
im = cv2.imread(args.image)
result = model.predict(im)
print(result)
# 预测结果可视化
vis_im = fd.vision.vis_perception(im, result, config_file)
cv2.imwrite("visualized_result.jpg", vis_im)
print("Visualized result save in ./visualized_result.jpg")

View File

@@ -0,0 +1,85 @@
English | [简体中文](README_CN.md)
# Smoke service deployment example
This document introduces the service deployment of the Smoke model in Paddle3D.
For Smoke model export and pre-training model download, please refer to [Smoke Model Deployment](../README.md) document.
Before service deployment, you need to confirm
- 1. Please refer to [FastDeploy Service-based Deployment](../../../../../serving/README_CN.md) for the hardware and software environment requirements of the service image and the image pull command
## Start the service
```bash
#Download deployment sample code
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd FastDeploy/examples/vision/perception/paddle3d/smoke/serving
#Download the Smoke model file and test image
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# Put the configuration file into the preprocessing directory
mv smoke/infer_cfg.yml models/preprocess/1/
# Put the model into the models/runtime/1 directory, and rename it to model.pdmodel and model.pdiparams
mv smoke/smoke.pdmodel models/runtime/1/model.pdmodel
mv smoke/smoke.pdiparams models/runtime/1/model.pdiparams
# Pull the fastdeploy image (x.y.z is the image version number, which needs to be replaced with the fastdeploy version number)
# GPU mirroring
docker pull registry.baidubce.com/paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10
# CPU mirroring
docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10
# Run the container. The container name is fd_serving, and mount the current directory as the /serving directory of the container
nvidia-docker run -it --net=host --name fd_serving --shm-size="1g" -v `pwd`/:/serving registry.baidubce.com/paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4 -trt8.4-21.10 bash
# Start the service (if you do not set the CUDA_VISIBLE_DEVICES environment variable, you will have the scheduling authority of all GPU cards)
CUDA_VISIBLE_DEVICES=0 fastdeployserver --model-repository=/serving/models
```
>> **NOTE**:
>> For pulling images, please refer to [Serving Deployment Main Document](../../../../../serving/README_CN.md)
>> Execute fastdeployserver to start the service and "Address already in use" appears, please use `--grpc-port` to specify the grpc port number to start the service, and change the request port number in the client example.
>> Other startup parameters can be viewed using fastdeployserver --help
After the service starts successfully, there will be the following output:
```
 …
I0928 04:51:15.784517 206 grpc_server.cc:4117] Started GRPCInferenceService at 0.0.0.0:8001
I0928 04:51:15.785177 206 http_server.cc:2815] Started HTTPService at 0.0.0.0:8000
I0928 04:51:15.826578 206 http_server.cc:167] Started Metrics Service at 0.0.0.0:8002
```
## Client request
Execute the following command on the physical machine, send the grpc request and output the result
```
#Download test image
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# Install client dependencies
python3 -m pip install tritonclient[all]
# send request
python3 smoke_grpc_client.py
```
After sending the request successfully, the detection result in json format will be returned and printed out:
```
output_name: PERCEPTION_RESULT
, 0.0068892366252839565]
label_ids: [2, 0, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 , 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0]
```
## Configuration modification
The current default configuration runs the Paddle engine on the CPU, if you want to run it on the GPU or other inference engines. It is necessary to modify the configuration in `models/runtime/config.pbtxt`, for details, please refer to [configuration document](../../../../../serving/docs/zh_CN/model_configuration.md)

View File

@@ -0,0 +1,85 @@
[English](README.md) | 简体中文
# Smoke 服务化部署示例
本文档介绍 Paddle3D 中 Smoke 模型的服务化部署。
Smoke 模型导出和预训练模型下载请看[Smoke模型部署](../README.md)文档。
在服务化部署前,需确认
- 1. 服务化镜像的软硬件环境要求和镜像拉取命令请参考[FastDeploy服务化部署](../../../../../serving/README_CN.md)
## 启动服务
```bash
#下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd FastDeploy/examples/vision/perception/paddle3d/smoke/serving
#下载 Smoke 模型文件和测试图片
wget https://bj.bcebos.com/fastdeploy/models/smoke.tar.gz
tar -xf smoke.tar.gz
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
# 将配置文件放入预处理目录
mv smoke/infer_cfg.yml models/preprocess/1/
# 将模型放入 models/runtime/1 目录下, 并重命名为 model.pdmodel 和 model.pdiparams
mv smoke/smoke.pdmodel models/runtime/1/model.pdmodel
mv smoke/smoke.pdiparams models/runtime/1/model.pdiparams
# 拉取 fastdeploy 镜像(x.y.z 为镜像版本号,需替换成 fastdeploy 版本数字)
# GPU 镜像
docker pull registry.baidubce.com/paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10
# CPU 镜像
docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10
# 运行容器.容器名字为 fd_serving, 并挂载当前目录为容器的 /serving 目录
nvidia-docker run -it --net=host --name fd_serving --shm-size="1g" -v `pwd`/:/serving registry.baidubce.com/paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash
# 启动服务(不设置 CUDA_VISIBLE_DEVICES 环境变量,会拥有所有 GPU 卡的调度权限)
CUDA_VISIBLE_DEVICES=0 fastdeployserver --model-repository=/serving/models
```
>> **注意**:
>> 拉取镜像请看[服务化部署主文档](../../../../../serving/README_CN.md)
>> 执行 fastdeployserver 启动服务出现 "Address already in use", 请使用 `--grpc-port` 指定 grpc 端口号来启动服务,同时更改客户端示例中的请求端口号.
>> 其他启动参数可以使用 fastdeployserver --help 查看
服务启动成功后, 会有以下输出:
```
......
I0928 04:51:15.784517 206 grpc_server.cc:4117] Started GRPCInferenceService at 0.0.0.0:8001
I0928 04:51:15.785177 206 http_server.cc:2815] Started HTTPService at 0.0.0.0:8000
I0928 04:51:15.826578 206 http_server.cc:167] Started Metrics Service at 0.0.0.0:8002
```
## 客户端请求
在物理机器中执行以下命令,发送 grpc 请求并输出结果
```
#下载测试图片
wget https://bj.bcebos.com/fastdeploy/models/smoke_test.png
#安装客户端依赖
python3 -m pip install tritonclient[all]
# 发送请求
python3 smoke_grpc_client.py
```
发送请求成功后,会返回 json 格式的检测结果并打印输出:
```
output_name: PERCEPTION_RESULT
scores: [0.8080164790153503, 0.03356542810797691, 0.03165825456380844, 0.020817330107092857, 0.018075695261359215, 0.017861749976873398, 0.016441335901618004, 0.01476177480071783, 0.012927377596497536, 0.012407636269927025, 0.012400650419294834, 0.012216777540743351, 0.01208423636853695, 0.011721019633114338, 0.011697308160364628, 0.011695655062794685, 0.011603309772908688, 0.011140472255647182, 0.010927721858024597, 0.01036786288022995, 0.00984608568251133, 0.009827949106693268, 0.009761993773281574, 0.00959752406924963, 0.009595031850039959, 0.009423951618373394, 0.008946355432271957, 0.008635037578642368, 0.008597995154559612, 0.008552121929824352, 0.00839947909116745, 0.008325068280100822, 0.00830004084855318, 0.00826205126941204, 0.008174785412847996, 0.008085251785814762, 0.008026468567550182, 0.00796759407967329, 0.007873599417507648, 0.007816540077328682, 0.007742374204099178, 0.007734378334134817, 0.0077047450467944145, 0.007684454321861267, 0.007525254040956497, 0.007521109655499458, 0.007519087754189968, 0.007399206515401602, 0.0071790567599236965, 0.0068892366252839565]
label_ids: [2, 0, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```
## 配置修改
当前默认配置在 CPU 上运行 Paddle 引擎, 如果要在 GPU 或其他推理引擎上运行。 需要修改 `models/runtime/config.pbtxt` 中配置,详情请参考[配置文档](../../../../../serving/docs/zh_CN/model_configuration.md)

View File

@@ -0,0 +1,110 @@
# Copyright (c) 2022 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.
import json
import numpy as np
import time
import fastdeploy as fd
# triton_python_backend_utils is available in every Triton Python model. You
# need to use this module to create inference requests and responses. It also
# contains some utility functions for extracting information from model_config
# and converting Triton input/output types to numpy types.
import triton_python_backend_utils as pb_utils
class TritonPythonModel:
"""Your Python model must use the same class name. Every Python model
that is created must have "TritonPythonModel" as the class name.
"""
def initialize(self, args):
"""`initialize` is called only once when the model is being loaded.
Implementing `initialize` function is optional. This function allows
the model to intialize any state associated with this model.
Parameters
----------
args : dict
Both keys and values are strings. The dictionary keys and values are:
* model_config: A JSON string containing the model configuration
* model_instance_kind: A string containing model instance kind
* model_instance_device_id: A string containing model instance device ID
* model_repository: Model repository path
* model_version: Model version
* model_name: Model name
"""
# You must parse model_config. JSON string is not parsed here
self.model_config = json.loads(args['model_config'])
print("model_config:", self.model_config)
self.input_names = []
for input_config in self.model_config["input"]:
self.input_names.append(input_config["name"])
print("postprocess input names:", self.input_names)
self.output_names = []
self.output_dtype = []
for output_config in self.model_config["output"]:
self.output_names.append(output_config["name"])
dtype = pb_utils.triton_string_to_numpy(output_config["data_type"])
self.output_dtype.append(dtype)
print("postprocess output names:", self.output_names)
self.postprocess_ = fd.vision.perception.SmokePostprocessor()
def execute(self, requests):
"""`execute` must be implemented in every Python model. `execute`
function receives a list of pb_utils.InferenceRequest as the only
argument. This function is called when an inference is requested
for this model. Depending on the batching configuration (e.g. Dynamic
Batching) used, `requests` may contain multiple requests. Every
Python model, must create one pb_utils.InferenceResponse for every
pb_utils.InferenceRequest in `requests`. If there is an error, you can
set the error argument when creating a pb_utils.InferenceResponse.
Parameters
----------
requests : list
A list of pb_utils.InferenceRequest
Returns
-------
list
A list of pb_utils.InferenceResponse. The length of this list must
be the same as `requests`
"""
responses = []
for request in requests:
infer_outputs = []
for name in self.input_names:
infer_output = pb_utils.get_input_tensor_by_name(request, name)
if infer_output:
infer_output = infer_output.as_numpy()
infer_outputs.append(infer_output)
results = self.postprocess_.run(infer_outputs)
r_str = fd.vision.utils.fd_result_to_json(results)
r_np = np.array(r_str, dtype=np.object_)
out_tensor = pb_utils.Tensor(self.output_names[0], r_np)
inference_response = pb_utils.InferenceResponse(
output_tensors=[out_tensor, ])
responses.append(inference_response)
return responses
def finalize(self):
"""`finalize` is called only once when the model is being unloaded.
Implementing `finalize` function is optional. This function allows
the model to perform any necessary clean ups before exit.
"""
print('Cleaning up...')

View File

@@ -0,0 +1,25 @@
name: "postprocess"
backend: "python"
input [
{
name: "post_input1"
data_type: TYPE_FP32
dims: [ 50, 14 ]
}
]
output [
{
name: "post_output"
data_type: TYPE_STRING
dims: [ -1 ]
}
]
instance_group [
{
count: 1
kind: KIND_CPU
}
]

View File

@@ -0,0 +1,114 @@
# Copyright (c) 2022 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.
import json
import numpy as np
import os
import fastdeploy as fd
# triton_python_backend_utils is available in every Triton Python model. You
# need to use this module to create inference requests and responses. It also
# contains some utility functions for extracting information from model_config
# and converting Triton input/output types to numpy types.
import triton_python_backend_utils as pb_utils
class TritonPythonModel:
"""Your Python model must use the same class name. Every Python model
that is created must have "TritonPythonModel" as the class name.
"""
def initialize(self, args):
"""`initialize` is called only once when the model is being loaded.
Implementing `initialize` function is optional. This function allows
the model to intialize any state associated with this model.
Parameters
----------
args : dict
Both keys and values are strings. The dictionary keys and values are:
* model_config: A JSON string containing the model configuration
* model_instance_kind: A string containing model instance kind
* model_instance_device_id: A string containing model instance device ID
* model_repository: Model repository path
* model_version: Model version
* model_name: Model name
"""
# You must parse model_config. JSON string is not parsed here
self.model_config = json.loads(args['model_config'])
print("model_config:", self.model_config)
self.input_names = []
for input_config in self.model_config["input"]:
self.input_names.append(input_config["name"])
print("preprocess input names:", self.input_names)
self.output_names = []
self.output_dtype = []
for output_config in self.model_config["output"]:
self.output_names.append(output_config["name"])
# dtype = pb_utils.triton_string_to_numpy(output_config["data_type"])
# self.output_dtype.append(dtype)
self.output_dtype.append(output_config["data_type"])
print("preprocess output names:", self.output_names)
# init PaddleClasPreprocess class
yaml_path = os.path.abspath(os.path.dirname(
__file__)) + "/infer_cfg.yml"
self.preprocess_ = fd.vision.perception.SmokePreprocessor(yaml_path)
def execute(self, requests):
"""`execute` must be implemented in every Python model. `execute`
function receives a list of pb_utils.InferenceRequest as the only
argument. This function is called when an inference is requested
for this model. Depending on the batching configuration (e.g. Dynamic
Batching) used, `requests` may contain multiple requests. Every
Python model, must create one pb_utils.InferenceResponse for every
pb_utils.InferenceRequest in `requests`. If there is an error, you can
set the error argument when creating a pb_utils.InferenceResponse.
Parameters
----------
requests : list
A list of pb_utils.InferenceRequest
Returns
-------
list
A list of pb_utils.InferenceResponse. The length of this list must
be the same as `requests`
"""
responses = []
for request in requests:
data = pb_utils.get_input_tensor_by_name(request,
self.input_names[0])
data = data.as_numpy()
outputs = self.preprocess_.run(data)
output_tensors = []
for idx, name in enumerate(self.output_names):
dlpack_tensor = outputs[idx].to_dlpack()
output_tensor = pb_utils.Tensor.from_dlpack(name,
dlpack_tensor)
output_tensors.append(output_tensor)
inference_response = pb_utils.InferenceResponse(
output_tensors=output_tensors)
responses.append(inference_response)
return responses
def finalize(self):
"""`finalize` is called only once when the model is being unloaded.
Implementing `finalize` function is optional. This function allows
the model to perform any necessary clean ups before exit.
"""
print('Cleaning up...')

View File

@@ -0,0 +1,35 @@
name: "preprocess"
backend: "python"
input [
{
name: "preprocess_input"
data_type: TYPE_UINT8
dims: [ 1, -1, -1, 3 ]
}
]
output [
{
name: "preprocess_output1"
data_type: TYPE_FP32
dims: [ 1, 2 ]
},
{
name: "preprocess_output2"
data_type: TYPE_FP32
dims: [ 1, 3, -1, -1 ]
},
{
name: "preprocess_output3"
data_type: TYPE_FP32
dims: [ 1, 3, 3 ]
}
]
instance_group [
{
count: 1
kind: KIND_CPU
}
]

View File

@@ -0,0 +1,5 @@
# Runtime Directory
This directory holds the model files.
Paddle models must be model.pdmodel and model.pdiparams files.
ONNX models must be model.onnx files.

View File

@@ -0,0 +1,57 @@
# optional, If name is specified it must match the name of the model repository directory containing the model.
name: "runtime"
backend: "fastdeploy"
# Input configuration of the model
input [
{
# input name
name: "down_ratios"
# input type such as TYPE_FP32、TYPE_UINT8、TYPE_INT8、TYPE_INT16、TYPE_INT32、TYPE_INT64、TYPE_FP16、TYPE_STRING
data_type: TYPE_FP32
dims: [ 1, 2 ]
},
{
# input name
name: "images"
# input type such as TYPE_FP32、TYPE_UINT8、TYPE_INT8、TYPE_INT16、TYPE_INT32、TYPE_INT64、TYPE_FP16、TYPE_STRING
data_type: TYPE_FP32
dims: [ 1, 3, -1, -1 ]
},
{
name: "trans_cam_to_img"
data_type: TYPE_FP32
dims: [ 1, 3, 3 ]
}
]
# The output of the model is configured in the same format as the input
output [
{
name: "concat_13.tmp_0"
data_type: TYPE_FP32
dims: [ 50, 14 ]
}
]
# Number of instances of the model
instance_group [
{
# The number of instances is 1
count: 1
# Use GPU, CPU inference option is:KIND_CPU
kind: KIND_CPU
# The instance is deployed on the 0th GPU card
# gpus: [0]
}
]
optimization {
execution_accelerators {
cpu_execution_accelerator : [ {
# use Paddle engine
name: "paddle",
parameters { key: "use_mkldnn" value: "1" }
}
]
}}

View File

@@ -0,0 +1,3 @@
# Smoke Pipeline
The pipeline directory does not have model files, but a version number directory needs to be maintained.

View File

@@ -0,0 +1,72 @@
platform: "ensemble"
input [
{
name: "INPUT"
data_type: TYPE_UINT8
dims: [ 1, -1, -1, 3 ]
}
]
output [
{
name: "PERCEPTION_RESULT"
data_type: TYPE_STRING
dims: [ -1 ]
}
]
ensemble_scheduling {
step [
{
model_name: "preprocess"
model_version: 1
input_map {
key: "preprocess_input"
value: "INPUT"
}
output_map {
key: "preprocess_output1"
value: "RUNTIME_INPUT1"
}
output_map {
key: "preprocess_output2"
value: "RUNTIME_INPUT2"
}
output_map {
key: "preprocess_output3"
value: "RUNTIME_INPUT3"
}
},
{
model_name: "runtime"
model_version: 1
input_map {
key: "down_ratios"
value: "RUNTIME_INPUT1"
}
input_map {
key: "images"
value: "RUNTIME_INPUT2"
}
input_map {
key: "trans_cam_to_img"
value: "RUNTIME_INPUT3"
}
output_map {
key: "concat_13.tmp_0"
value: "RUNTIME_OUTPUT1"
}
},
{
model_name: "postprocess"
model_version: 1
input_map {
key: "post_input1"
value: "RUNTIME_OUTPUT1"
}
output_map {
key: "post_output"
value: "PERCEPTION_RESULT"
}
}
]
}

View File

@@ -0,0 +1,108 @@
import logging
import numpy as np
import time
from typing import Optional
import cv2
import json
from tritonclient import utils as client_utils
from tritonclient.grpc import InferenceServerClient, InferInput, InferRequestedOutput, service_pb2_grpc, service_pb2
LOGGER = logging.getLogger("run_inference_on_triton")
class SyncGRPCTritonRunner:
DEFAULT_MAX_RESP_WAIT_S = 120
def __init__(
self,
server_url: str,
model_name: str,
model_version: str,
*,
verbose=False,
resp_wait_s: Optional[float]=None, ):
self._server_url = server_url
self._model_name = model_name
self._model_version = model_version
self._verbose = verbose
self._response_wait_t = self.DEFAULT_MAX_RESP_WAIT_S if resp_wait_s is None else resp_wait_s
self._client = InferenceServerClient(
self._server_url, verbose=self._verbose)
error = self._verify_triton_state(self._client)
if error:
raise RuntimeError(
f"Could not communicate to Triton Server: {error}")
LOGGER.debug(
f"Triton server {self._server_url} and model {self._model_name}:{self._model_version} "
f"are up and ready!")
model_config = self._client.get_model_config(self._model_name,
self._model_version)
model_metadata = self._client.get_model_metadata(self._model_name,
self._model_version)
LOGGER.info(f"Model config {model_config}")
LOGGER.info(f"Model metadata {model_metadata}")
for tm in model_metadata.inputs:
print("tm:", tm)
self._inputs = {tm.name: tm for tm in model_metadata.inputs}
self._input_names = list(self._inputs)
self._outputs = {tm.name: tm for tm in model_metadata.outputs}
self._output_names = list(self._outputs)
self._outputs_req = [
InferRequestedOutput(name) for name in self._outputs
]
def Run(self, inputs):
"""
Args:
inputs: list, Each value corresponds to an input name of self._input_names
Returns:
results: dict, {name : numpy.array}
"""
infer_inputs = []
for idx, data in enumerate(inputs):
infer_input = InferInput(self._input_names[idx], data.shape,
"UINT8")
infer_input.set_data_from_numpy(data)
infer_inputs.append(infer_input)
results = self._client.infer(
model_name=self._model_name,
model_version=self._model_version,
inputs=infer_inputs,
outputs=self._outputs_req,
client_timeout=self._response_wait_t, )
results = {name: results.as_numpy(name) for name in self._output_names}
return results
def _verify_triton_state(self, triton_client):
if not triton_client.is_server_live():
return f"Triton server {self._server_url} is not live"
elif not triton_client.is_server_ready():
return f"Triton server {self._server_url} is not ready"
elif not triton_client.is_model_ready(self._model_name,
self._model_version):
return f"Model {self._model_name}:{self._model_version} is not ready"
return None
if __name__ == "__main__":
model_name = "smoke"
model_version = "1"
url = "localhost:8001"
runner = SyncGRPCTritonRunner(url, model_name, model_version)
im = cv2.imread("smoke_test.png")
im = np.array([im, ])
for i in range(1):
result = runner.Run([im, ])
for name, values in result.items():
print("output_name:", name)
# values is batch
for value in values:
value = json.loads(value)
print("scores: ", value['scores'])
print("label_ids: ", value['label_ids'])

65
fastdeploy/runtime/backends/paddle/paddle_backend.cc Executable file → Normal file
View File

@@ -226,10 +226,17 @@ bool PaddleBackend::InitFromPaddle(const std::string& model,
std::map<std::string, std::vector<int>> min_shape;
std::map<std::string, std::vector<int>> opt_shape;
GetDynamicShapeFromOption(option, &max_shape, &min_shape, &opt_shape);
std::map<std::string, std::vector<float>> max_input_data;
std::map<std::string, std::vector<float>> min_input_data;
std::map<std::string, std::vector<float>> opt_input_data;
if (!option.trt_option.min_input_data.empty()) {
GetInputDataFromOption(option, &max_input_data, &min_input_data,
&opt_input_data);
}
// Need to run once to get the shape range info file.
CollectShapeRun(predictor_tmp.get(), max_shape);
CollectShapeRun(predictor_tmp.get(), min_shape);
CollectShapeRun(predictor_tmp.get(), opt_shape);
CollectShapeRun(predictor_tmp.get(), max_shape, max_input_data);
CollectShapeRun(predictor_tmp.get(), min_shape, min_input_data);
CollectShapeRun(predictor_tmp.get(), opt_shape, min_input_data);
FDINFO << "Finish generating shape range info file." << std::endl;
}
FDINFO << "Start loading shape range info file " << shape_range_info
@@ -400,9 +407,33 @@ void PaddleBackend::GetDynamicShapeFromOption(
}
}
void PaddleBackend::GetInputDataFromOption(
const PaddleBackendOption& option,
std::map<std::string, std::vector<float>>* max_input_data,
std::map<std::string, std::vector<float>>* min_input_data,
std::map<std::string, std::vector<float>>* opt_input_data) const {
for (const auto& item : option.trt_option.min_input_data) {
auto max_iter = option.trt_option.max_input_data.find(item.first);
auto opt_iter = option.trt_option.opt_input_data.find(item.first);
FDASSERT(max_iter != option.trt_option.max_input_data.end(),
"Cannot find %s in TrtBackendOption::min_input_data.",
item.first.c_str());
FDASSERT(opt_iter != option.trt_option.opt_input_data.end(),
"Cannot find %s in TrtBackendOption::opt_input_data.",
item.first.c_str());
(*max_input_data)[item.first].assign(max_iter->second.begin(),
max_iter->second.end());
(*opt_input_data)[item.first].assign(opt_iter->second.begin(),
opt_iter->second.end());
(*min_input_data)[item.first].assign(item.second.begin(),
item.second.end());
}
}
void PaddleBackend::CollectShapeRun(
paddle_infer::Predictor* predictor,
const std::map<std::string, std::vector<int>>& shape) const {
const std::map<std::string, std::vector<int>>& shape,
const std::map<std::string, std::vector<float>>& data) const {
auto input_names = predictor->GetInputNames();
auto input_type = predictor->GetInputTypes();
for (const auto& name : input_names) {
@@ -418,21 +449,47 @@ void PaddleBackend::CollectShapeRun(
int shape_num = std::accumulate(shape_value.begin(), shape_value.end(), 1,
std::multiplies<int>());
tensor->Reshape(shape_value);
if (data.find(name) != data.end()) {
FDASSERT(data.at(name).size() == shape_num,
"The data num and accumulate of shape must be equal for input: "
"[\"%s\"], "
" When Use the (C++)RuntimeOption.trt_option.SetInputData/ "
" (Python)RuntimeOption.trt_option.set_input_data/",
name.c_str());
}
auto dtype = input_type[name];
switch (dtype) {
case paddle_infer::DataType::FLOAT32: {
if (data.find(name) != data.end()) {
tensor->CopyFromCpu(data.at(name).data());
} else {
std::vector<float> input_data(shape_num, 1.0);
tensor->CopyFromCpu(input_data.data());
}
break;
}
case paddle_infer::DataType::INT32: {
if (data.find(name) != data.end()) {
std::vector<int> input_data(data.at(name).begin(),
data.at(name).end());
tensor->CopyFromCpu(input_data.data());
} else {
std::vector<int> input_data(shape_num, 1);
tensor->CopyFromCpu(input_data.data());
}
break;
}
case paddle_infer::DataType::INT64: {
if (data.find(name) != data.end()) {
std::vector<int64_t> input_data(data.at(name).begin(),
data.at(name).end());
tensor->CopyFromCpu(input_data.data());
} else {
std::vector<int64_t> input_data(shape_num, 1);
tensor->CopyFromCpu(input_data.data());
}
break;
}
default: {

View File

@@ -81,12 +81,18 @@ class PaddleBackend : public BaseBackend {
void
CollectShapeRun(paddle_infer::Predictor* predictor,
const std::map<std::string, std::vector<int>>& shape) const;
const std::map<std::string, std::vector<int>>& shape,
const std::map<std::string, std::vector<float>>& data) const;
void GetDynamicShapeFromOption(
const PaddleBackendOption& option,
std::map<std::string, std::vector<int>>* max_shape,
std::map<std::string, std::vector<int>>* min_shape,
std::map<std::string, std::vector<int>>* opt_shape) const;
void GetInputDataFromOption(
const PaddleBackendOption& option,
std::map<std::string, std::vector<float>>* max_input_data,
std::map<std::string, std::vector<float>>* min_input_data,
std::map<std::string, std::vector<float>>* opt_input_data) const;
void SetTRTDynamicShapeToConfig(const PaddleBackendOption& option);
PaddleBackendOption option_;
paddle_infer::Config config_;

View File

@@ -34,7 +34,8 @@ struct TrtBackendOption {
bool enable_log_info = false;
/// Enable half precison inference, on some device not support half precision, it will fallback to float32 mode
/// Enable half precison inference, on some device not support half precision,
/// it will fallback to float32 mode
bool enable_fp16 = false;
/** \brief Set shape range of input tensor for the model that contain dynamic input shape while using TensorRT backend
@@ -63,9 +64,44 @@ struct TrtBackendOption {
max_shape[tensor_name].assign(max.begin(), max.end());
}
}
/// Set cache file path while use TensorRT backend. Loadding a Paddle/ONNX model and initialize TensorRT will take a long time, by this interface it will save the tensorrt engine to `cache_file_path`, and load it directly while execute the code again
/** \brief Set Input data for input tensor for the model while using TensorRT backend
*
* \param[in] tensor_name The name of input for the model which is dynamic shape
* \param[in] min_data The input data for minimal shape for the input tensor
* \param[in] opt_data The input data for optimized shape for the input tensor
* \param[in] max_data The input data for maximum shape for the input tensor, if set as default value, it will keep same with min_data
*/
void SetInputData(const std::string& tensor_name,
const std::vector<float> min_data,
const std::vector<float> opt_data = std::vector<float>(),
const std::vector<float> max_data = std::vector<float>()) {
max_input_data[tensor_name].clear();
min_input_data[tensor_name].clear();
opt_input_data[tensor_name].clear();
min_input_data[tensor_name].assign(min_data.begin(), min_data.end());
if (opt_data.empty()) {
opt_input_data[tensor_name].assign(min_data.begin(), min_data.end());
} else {
opt_input_data[tensor_name].assign(opt_data.begin(), opt_data.end());
}
if (max_data.empty()) {
max_input_data[tensor_name].assign(min_data.begin(), min_data.end());
} else {
max_input_data[tensor_name].assign(max_data.begin(), max_data.end());
}
}
/// Set cache file path while use TensorRT backend.
/// Loadding a Paddle/ONNX model and initialize TensorRT will
/// take a long time,
/// by this interface it will save the tensorrt engine to `cache_file_path`,
/// and load it directly while execute the code again
std::string serialize_file = "";
std::map<std::string, std::vector<float>> max_input_data;
std::map<std::string, std::vector<float>> min_input_data;
std::map<std::string, std::vector<float>> opt_input_data;
// The below parameters may be removed in next version, please do not
// visit or use them directly
std::map<std::string, std::vector<int32_t>> max_shape;

3
fastdeploy/runtime/backends/tensorrt/option_pybind.cc Normal file → Executable file
View File

@@ -26,7 +26,8 @@ void BindTrtOption(pybind11::module& m) {
.def_readwrite("max_workspace_size",
&TrtBackendOption::max_workspace_size)
.def_readwrite("serialize_file", &TrtBackendOption::serialize_file)
.def("set_shape", &TrtBackendOption::SetShape);
.def("set_shape", &TrtBackendOption::SetShape)
.def("set_input_data", &TrtBackendOption::SetInputData);
}
} // namespace fastdeploy

View File

@@ -379,6 +379,17 @@ void RuntimeOption::SetTrtInputShape(const std::string& input_name,
trt_option.SetShape(input_name, min_shape, opt_shape, max_shape);
}
void RuntimeOption::SetTrtInputData(const std::string& input_name,
const std::vector<float>& min_shape_data,
const std::vector<float>& opt_shape_data,
const std::vector<float>& max_shape_data) {
FDWARNING << "`RuntimeOption::SetTrtInputData` will be removed in v1.2.0, "
"please use `RuntimeOption.trt_option.SetInputData()` instead."
<< std::endl;
trt_option.SetInputData(input_name, min_shape_data, opt_shape_data,
max_shape_data);
}
void RuntimeOption::SetTrtMaxWorkspaceSize(size_t max_workspace_size) {
FDWARNING << "`RuntimeOption::SetTrtMaxWorkspaceSize` will be removed in "
"v1.2.0, please modify its member variable directly, e.g "

View File

@@ -257,6 +257,12 @@ struct FASTDEPLOY_DECL RuntimeOption {
const std::string& input_name, const std::vector<int32_t>& min_shape,
const std::vector<int32_t>& opt_shape = std::vector<int32_t>(),
const std::vector<int32_t>& max_shape = std::vector<int32_t>());
void SetTrtInputData(
const std::string& input_name, const std::vector<float>& min_shape_data,
const std::vector<float>& opt_shape_data = std::vector<float>(),
const std::vector<float>& max_shape_data = std::vector<float>());
void SetTrtMaxWorkspaceSize(size_t trt_max_workspace_size);
void SetTrtMaxBatchSize(size_t max_batch_size);
void EnableTrtFP16();

1
fastdeploy/vision.h Normal file → Executable file
View File

@@ -32,6 +32,7 @@
#include "fastdeploy/vision/detection/contrib/yolov8/yolov8.h"
#include "fastdeploy/vision/detection/contrib/yolox.h"
#include "fastdeploy/vision/detection/contrib/rknpu2/model.h"
#include "fastdeploy/vision/perception/paddle3d/smoke/smoke.h"
#include "fastdeploy/vision/detection/ppdet/model.h"
#include "fastdeploy/vision/facealign/contrib/face_landmark_1000.h"
#include "fastdeploy/vision/facealign/contrib/pfld.h"

View File

@@ -166,6 +166,96 @@ std::string DetectionResult::Str() {
return out;
}
// PerceptionResult -----------------------------------------------------
PerceptionResult::PerceptionResult(const PerceptionResult& res) {
scores.assign(res.scores.begin(), res.scores.end());
label_ids.assign(res.label_ids.begin(), res.label_ids.end());
boxes.assign(res.boxes.begin(), res.boxes.end());
center.assign(res.center.begin(), res.center.end());
observation_angle.assign(res.observation_angle.begin(),
res.observation_angle.end());
yaw_angle.assign(res.yaw_angle.begin(), res.yaw_angle.end());
velocity.assign(res.velocity.begin(), res.velocity.end());
}
PerceptionResult& PerceptionResult::operator=(PerceptionResult&& other) {
if (&other != this) {
scores = std::move(other.scores);
label_ids = std::move(other.label_ids);
boxes = std::move(other.boxes);
center = std::move(other.center);
observation_angle = std::move(other.observation_angle);
yaw_angle = std::move(other.yaw_angle);
velocity = std::move(other.velocity);
}
return *this;
}
void PerceptionResult::Free() {
std::vector<float>().swap(scores);
std::vector<int32_t>().swap(label_ids);
std::vector<std::array<float, 7>>().swap(boxes);
std::vector<std::array<float, 3>>().swap(center);
std::vector<float>().swap(observation_angle);
std::vector<float>().swap(yaw_angle);
std::vector<std::array<float, 3>>().swap(velocity);
}
void PerceptionResult::Clear() {
scores.clear();
label_ids.clear();
boxes.clear();
center.clear();
observation_angle.clear();
yaw_angle.clear();
velocity.clear();
}
void PerceptionResult::Reserve(int size) {
scores.reserve(size);
label_ids.reserve(size);
boxes.reserve(size);
center.reserve(size);
observation_angle.reserve(size);
yaw_angle.reserve(size);
velocity.reserve(size);
}
void PerceptionResult::Resize(int size) {
scores.resize(size);
label_ids.resize(size);
boxes.resize(size);
center.resize(size);
observation_angle.resize(size);
yaw_angle.resize(size);
velocity.resize(size);
}
std::string PerceptionResult::Str() {
std::string out;
out =
"PerceptionResult: [xmin, ymin, xmax, ymax, w, h, l, cx, cy, cz, "
"yaw_angle, "
"ob_angle, score, label_id]\n";
for (size_t i = 0; i < boxes.size(); ++i) {
out = out + std::to_string(boxes[i][0]) + "," +
std::to_string(boxes[i][1]) + ", " + std::to_string(boxes[i][2]) +
", " + std::to_string(boxes[i][3]) + ", " +
std::to_string(boxes[i][4]) + ", " + std::to_string(boxes[i][5]) +
", " + std::to_string(boxes[i][6]) + ", " +
std::to_string(center[i][0]) + ", " + std::to_string(center[i][1]) +
", " + std::to_string(center[i][2]) + ", " +
std::to_string(yaw_angle[i]) + ", " +
std::to_string(observation_angle[i]) + ", " +
std::to_string(scores[i]) + ", " + std::to_string(label_ids[i]);
out += "\n";
}
return out;
}
// PerceptionResult finished
void KeyPointDetectionResult::Free() {
std::vector<std::array<float, 2>>().swap(keypoints);
std::vector<float>().swap(scores);
@@ -531,8 +621,8 @@ std::string OCRResult::Str() {
out = out + "]";
if (rec_scores.size() > 0) {
out = out + "rec text: " + text[n] + " rec score:" +
std::to_string(rec_scores[n]) + " ";
out = out + "rec text: " + text[n] +
" rec score:" + std::to_string(rec_scores[n]) + " ";
}
if (cls_labels.size() > 0) {
out = out + "cls label: " + std::to_string(cls_labels[n]) +
@@ -546,8 +636,8 @@ std::string OCRResult::Str() {
cls_scores.size() > 0) {
std::string out;
for (int i = 0; i < rec_scores.size(); i++) {
out = out + "rec text: " + text[i] + " rec score:" +
std::to_string(rec_scores[i]) + " ";
out = out + "rec text: " + text[i] +
" rec score:" + std::to_string(rec_scores[i]) + " ";
out = out + "cls label: " + std::to_string(cls_labels[i]) +
" cls score: " + std::to_string(cls_scores[i]);
out = out + "\n";
@@ -566,8 +656,8 @@ std::string OCRResult::Str() {
cls_scores.size() == 0) {
std::string out;
for (int i = 0; i < rec_scores.size(); i++) {
out = out + "rec text: " + text[i] + " rec score:" +
std::to_string(rec_scores[i]) + " ";
out = out + "rec text: " + text[i] +
" rec score:" + std::to_string(rec_scores[i]) + " ";
out = out + "\n";
}
return out;
@@ -589,9 +679,9 @@ std::string HeadPoseResult::Str() {
std::string out;
out = "HeadPoseResult: [yaw, pitch, roll]\n";
out = out + "yaw: " + std::to_string(euler_angles[0]) + "\n" + "pitch: " +
std::to_string(euler_angles[1]) + "\n" + "roll: " +
std::to_string(euler_angles[2]) + "\n";
out = out + "yaw: " + std::to_string(euler_angles[0]) + "\n" +
"pitch: " + std::to_string(euler_angles[1]) + "\n" +
"roll: " + std::to_string(euler_angles[2]) + "\n";
return out;
}

View File

@@ -140,6 +140,44 @@ struct FASTDEPLOY_DECL DetectionResult : public BaseResult {
std::string Str();
};
/*! @brief Detection result structure for all the object detection models and instance segmentation models
*/
struct FASTDEPLOY_DECL PerceptionResult : public BaseResult {
PerceptionResult() = default;
std::vector<float> scores;
std::vector<int32_t> label_ids;
// xmin, ymin, xmax, ymax, h, w, l
std::vector<std::array<float, 7>> boxes;
// cx, cy, cz
std::vector<std::array<float, 3>> center;
std::vector<float> observation_angle;
std::vector<float> yaw_angle;
// vx, vy, vz
std::vector<std::array<float, 3>> velocity;
/// Copy constructor
PerceptionResult(const PerceptionResult& res);
/// Move assignment
PerceptionResult& operator=(PerceptionResult&& other);
/// Clear PerceptionResult
void Clear();
/// Clear PerceptionResult and free the memory
void Free();
void Reserve(int size);
void Resize(int size);
/// Debug function, convert the result to string to print
std::string Str();
};
/*! @brief KeyPoint Detection result structure for all the keypoint detection models
*/
struct FASTDEPLOY_DECL KeyPointDetectionResult : public BaseResult {

View File

@@ -0,0 +1,58 @@
// Copyright (c) 2022 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.
#include "fastdeploy/vision/perception/paddle3d/smoke/postprocessor.h"
#include "fastdeploy/vision/utils/utils.h"
namespace fastdeploy {
namespace vision {
namespace perception {
SmokePostprocessor::SmokePostprocessor() {}
bool SmokePostprocessor::Run(const std::vector<FDTensor>& tensors,
std::vector<PerceptionResult>* results) {
results->resize(1);
(*results)[0].Clear();
(*results)[0].Reserve(tensors[0].shape[0]);
if (tensors[0].dtype != FDDataType::FP32) {
FDERROR << "Only support post process with float32 data." << std::endl;
return false;
}
const float* data = reinterpret_cast<const float*>(tensors[0].Data());
auto result = &(*results)[0];
for (int i = 0; i < tensors[0].shape[0] * tensors[0].shape[1]; i += 14) {
// item 1 : class
// item 2 : observation angle α
// item 3 ~ 6 : box2d x1, y1, x2, y2
// item 7 ~ 9 : box3d h, w, l
// item 10 ~ 12 : box3d bottom center x, y, z
// item 13 : box3d yaw angle
// item 14 : score
std::vector<float> vec(data + i, data + i + 14);
result->scores.push_back(vec[13]);
result->label_ids.push_back(vec[0]);
result->boxes.emplace_back(std::array<float, 7>{
vec[2], vec[3], vec[4], vec[5], vec[6], vec[7], vec[8]});
result->center.emplace_back(std::array<float, 3>{vec[9], vec[10], vec[11]});
result->observation_angle.push_back(vec[1]);
result->yaw_angle.push_back(vec[12]);
}
return true;
}
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,48 @@
// Copyright (c) 2022 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 "fastdeploy/vision/common/processors/transform.h"
#include "fastdeploy/vision/common/result.h"
namespace fastdeploy {
namespace vision {
namespace perception {
/*! @brief Postprocessor object for Smoke serials model.
*/
class FASTDEPLOY_DECL SmokePostprocessor {
public:
/** \brief Create a postprocessor instance for Smoke serials model
*/
SmokePostprocessor();
/** \brief Process the result of runtime and fill to PerceptionResult structure
*
* \param[in] tensors The inference result from runtime
* \param[in] result The output result of detection
* \param[in] ims_info The shape info list, record input_shape and output_shape
* \return true if the postprocess successed, otherwise false
*/
bool Run(const std::vector<FDTensor>& tensors,
std::vector<PerceptionResult>* results);
protected:
float conf_threshold_;
};
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,161 @@
// Copyright (c) 2022 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.
#include "fastdeploy/vision/perception/paddle3d/smoke/preprocessor.h"
#include "fastdeploy/function/concat.h"
#include "yaml-cpp/yaml.h"
namespace fastdeploy {
namespace vision {
namespace perception {
SmokePreprocessor::SmokePreprocessor(const std::string& config_file) {
config_file_ = config_file;
FDASSERT(BuildPreprocessPipelineFromConfig(),
"Failed to create Paddle3DDetPreprocessor.");
initialized_ = true;
}
bool SmokePreprocessor::BuildPreprocessPipelineFromConfig() {
processors_.clear();
YAML::Node cfg;
try {
cfg = YAML::LoadFile(config_file_);
} catch (YAML::BadFile& e) {
FDERROR << "Failed to load yaml file " << config_file_
<< ", maybe you should check this file." << std::endl;
return false;
}
// read for preprocess
processors_.push_back(std::make_shared<BGR2RGB>());
bool has_permute = false;
for (const auto& op : cfg["Preprocess"]) {
std::string op_name = op["type"].as<std::string>();
if (op_name == "NormalizeImage") {
auto mean = op["mean"].as<std::vector<float>>();
auto std = op["std"].as<std::vector<float>>();
bool is_scale = true;
if (op["is_scale"]) {
is_scale = op["is_scale"].as<bool>();
}
std::string norm_type = "mean_std";
if (op["norm_type"]) {
norm_type = op["norm_type"].as<std::string>();
}
if (norm_type != "mean_std") {
std::fill(mean.begin(), mean.end(), 0.0);
std::fill(std.begin(), std.end(), 1.0);
}
processors_.push_back(std::make_shared<Normalize>(mean, std, is_scale));
} else if (op_name == "Resize") {
bool keep_ratio = op["keep_ratio"].as<bool>();
auto target_size = op["target_size"].as<std::vector<int>>();
int interp = op["interp"].as<int>();
FDASSERT(target_size.size() == 2,
"Require size of target_size be 2, but now it's %lu.",
target_size.size());
if (!keep_ratio) {
int width = target_size[1];
int height = target_size[0];
processors_.push_back(
std::make_shared<Resize>(width, height, -1.0, -1.0, interp, false));
} else {
int min_target_size = std::min(target_size[0], target_size[1]);
int max_target_size = std::max(target_size[0], target_size[1]);
std::vector<int> max_size;
if (max_target_size > 0) {
max_size.push_back(max_target_size);
max_size.push_back(max_target_size);
}
processors_.push_back(std::make_shared<ResizeByShort>(
min_target_size, interp, true, max_size));
}
} else if (op_name == "Permute") {
// Do nothing, do permute as the last operation
has_permute = true;
continue;
} else {
FDERROR << "Unexcepted preprocess operator: " << op_name << "."
<< std::endl;
return false;
}
}
if (!disable_permute_) {
if (has_permute) {
// permute = cast<float> + HWC2CHW
processors_.push_back(std::make_shared<Cast>("float"));
processors_.push_back(std::make_shared<HWC2CHW>());
}
}
// Fusion will improve performance
FuseTransforms(&processors_);
input_k_data_ = cfg["k_data"].as<std::vector<float>>();
input_ratio_data_ = cfg["ratio_data"].as<std::vector<float>>();
return true;
}
bool SmokePreprocessor::Apply(FDMatBatch* image_batch,
std::vector<FDTensor>* outputs) {
if (image_batch->mats->empty()) {
FDERROR << "The size of input images should be greater than 0."
<< std::endl;
return false;
}
if (!initialized_) {
FDERROR << "The preprocessor is not initialized." << std::endl;
return false;
}
// There are 3 outputs, image, k_data, ratio_data
outputs->resize(3);
int batch = static_cast<int>(image_batch->mats->size());
// Allocate memory for k_data
(*outputs)[2].Resize({batch, 3, 3}, FDDataType::FP32);
// Allocate memory for ratio_data
(*outputs)[0].Resize({batch, 2}, FDDataType::FP32);
auto* k_data_ptr = reinterpret_cast<float*>((*outputs)[2].MutableData());
auto* ratio_data_ptr = reinterpret_cast<float*>((*outputs)[0].MutableData());
for (size_t i = 0; i < image_batch->mats->size(); ++i) {
FDMat* mat = &(image_batch->mats->at(i));
for (size_t j = 0; j < processors_.size(); ++j) {
if (!(*(processors_[j].get()))(mat)) {
FDERROR << "Failed to processs image:" << i << " in "
<< processors_[j]->Name() << "." << std::endl;
return false;
}
}
memcpy(k_data_ptr + i * 9, input_k_data_.data(), 9 * sizeof(float));
memcpy(ratio_data_ptr + i * 2, input_ratio_data_.data(), 2 * sizeof(float));
}
FDTensor* tensor = image_batch->Tensor();
(*outputs)[1].SetExternalData(tensor->Shape(), tensor->Dtype(),
tensor->Data(), tensor->device,
tensor->device_id);
return true;
}
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,61 @@
// Copyright (c) 2022 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 "fastdeploy/vision/common/processors/manager.h"
#include "fastdeploy/vision/common/processors/transform.h"
#include "fastdeploy/vision/common/result.h"
namespace fastdeploy {
namespace vision {
namespace perception {
/*! @brief Preprocessor object for Smoke serials model.
*/
class FASTDEPLOY_DECL SmokePreprocessor : public ProcessorManager {
public:
SmokePreprocessor() = default;
/** \brief Create a preprocessor instance for Smoke model
*
* \param[in] config_file Path of configuration file for deployment, e.g smoke/infer_cfg.yml
*/
explicit SmokePreprocessor(const std::string& config_file);
/** \brief Process the input image and prepare input tensors for runtime
*
* \param[in] images The input image data list, all the elements are returned by cv::imread()
* \param[in] outputs The output tensors which will feed in runtime
* \param[in] ims_info The shape info list, record input_shape and output_shape
* \return true if the preprocess successed, otherwise false
*/
bool Apply(FDMatBatch* image_batch, std::vector<FDTensor>* outputs);
protected:
bool BuildPreprocessPipelineFromConfig();
std::vector<std::shared_ptr<Processor>> processors_;
bool disable_permute_ = false;
bool initialized_ = false;
std::string config_file_;
std::vector<float> input_k_data_;
std::vector<float> input_ratio_data_;
};
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,82 @@
// Copyright (c) 2022 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.
#include "fastdeploy/vision/perception/paddle3d/smoke/smoke.h"
namespace fastdeploy {
namespace vision {
namespace perception {
Smoke::Smoke(const std::string& model_file, const std::string& params_file,
const std::string& config_file, const RuntimeOption& custom_option,
const ModelFormat& model_format)
: preprocessor_(config_file) {
valid_cpu_backends = {Backend::PDINFER};
valid_gpu_backends = {Backend::PDINFER};
runtime_option = custom_option;
runtime_option.model_format = model_format;
runtime_option.model_file = model_file;
runtime_option.params_file = params_file;
initialized = Initialize();
}
bool Smoke::Initialize() {
if (!InitRuntime()) {
FDERROR << "Failed to initialize fastdeploy backend." << std::endl;
return false;
}
return true;
}
bool Smoke::Predict(const cv::Mat& im, PerceptionResult* result) {
std::vector<PerceptionResult> results;
if (!BatchPredict({im}, &results)) {
return false;
}
if (results.size()) {
*result = std::move(results[0]);
}
return true;
}
bool Smoke::BatchPredict(const std::vector<cv::Mat>& images,
std::vector<PerceptionResult>* results) {
std::vector<FDMat> fd_images = WrapMat(images);
if (!preprocessor_.Run(&fd_images, &reused_input_tensors_)) {
FDERROR << "Failed to preprocess the input image." << std::endl;
return false;
}
reused_input_tensors_[0].name = InputInfoOfRuntime(0).name;
reused_input_tensors_[1].name = InputInfoOfRuntime(1).name;
reused_input_tensors_[2].name = InputInfoOfRuntime(2).name;
if (!Infer(reused_input_tensors_, &reused_output_tensors_)) {
FDERROR << "Failed to inference by runtime." << std::endl;
return false;
}
if (!postprocessor_.Run(reused_output_tensors_, results)) {
FDERROR << "Failed to postprocess the inference results by runtime."
<< std::endl;
return false;
}
return true;
}
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,78 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. //NOLINT
//
// 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 "fastdeploy/fastdeploy_model.h"
#include "fastdeploy/vision/perception/paddle3d/smoke/preprocessor.h"
#include "fastdeploy/vision/perception/paddle3d/smoke/postprocessor.h"
namespace fastdeploy {
namespace vision {
namespace perception {
/*! @brief smoke model object used when to load a smoke model exported by smoke.
*/
class FASTDEPLOY_DECL Smoke : public FastDeployModel {
public:
/** \brief Set path of model file and the configuration of runtime.
*
* \param[in] model_file Path of model file, e.g smoke/model.pdiparams
* \param[in] params_file Path of parameter file, e.g smoke/model.pdiparams, if the model format is ONNX, this parameter will be ignored
* \param[in] custom_option RuntimeOption for inference, the default will use cpu, and choose the backend defined in "valid_cpu_backends"
* \param[in] model_format Model format of the loaded model, default is Paddle format
*/
Smoke(const std::string& model_file, const std::string& params_file,
const std::string& config_file,
const RuntimeOption& custom_option = RuntimeOption(),
const ModelFormat& model_format = ModelFormat::PADDLE);
std::string ModelName() const { return "Paddle3D/smoke"; }
/** \brief Predict the perception result for an input image
*
* \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format
* \param[in] result The output perception result will be writen to this structure
* \return true if the prediction successed, otherwise false
*/
virtual bool Predict(const cv::Mat& img, PerceptionResult* result);
/** \brief Predict the perception results for a batch of input images
*
* \param[in] imgs, The input image list, each element comes from cv::imread()
* \param[in] results The output perception result list
* \return true if the prediction successed, otherwise false
*/
virtual bool BatchPredict(const std::vector<cv::Mat>& imgs,
std::vector<PerceptionResult>* results);
/// Get preprocessor reference of Smoke
virtual SmokePreprocessor& GetPreprocessor() {
return preprocessor_;
}
/// Get postprocessor reference of Smoke
virtual SmokePostprocessor& GetPostprocessor() {
return postprocessor_;
}
protected:
bool Initialize();
SmokePreprocessor preprocessor_;
SmokePostprocessor postprocessor_;
bool initialized_ = false;
};
} // namespace perception
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2022 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.
#include "fastdeploy/pybind/main.h"
namespace fastdeploy {
void BindSmoke(pybind11::module& m) {
pybind11::class_<vision::perception::SmokePreprocessor,
vision::ProcessorManager>(m, "SmokePreprocessor")
.def(pybind11::init<std::string>())
.def("run", [](vision::perception::SmokePreprocessor& self,
std::vector<pybind11::array>& im_list) {
std::vector<vision::FDMat> images;
for (size_t i = 0; i < im_list.size(); ++i) {
images.push_back(vision::WrapMat(PyArrayToCvMat(im_list[i])));
}
std::vector<FDTensor> outputs;
if (!self.Run(&images, &outputs)) {
throw std::runtime_error(
"Failed to preprocess the input data in SmokePreprocessor.");
}
for (size_t i = 0; i < outputs.size(); ++i) {
outputs[i].StopSharing();
}
return outputs;
});
pybind11::class_<vision::perception::SmokePostprocessor>(m,
"SmokePostprocessor")
.def(pybind11::init<>())
.def("run",
[](vision::perception::SmokePostprocessor& self,
std::vector<FDTensor>& inputs) {
std::vector<vision::PerceptionResult> results;
if (!self.Run(inputs, &results)) {
throw std::runtime_error(
"Failed to postprocess the runtime result in "
"SmokePostprocessor.");
}
return results;
})
.def("run", [](vision::perception::SmokePostprocessor& self,
std::vector<pybind11::array>& input_array) {
std::vector<vision::PerceptionResult> results;
std::vector<FDTensor> inputs;
PyArrayToTensorList(input_array, &inputs, /*share_buffer=*/true);
if (!self.Run(inputs, &results)) {
throw std::runtime_error(
"Failed to postprocess the runtime result in "
"SmokePostprocessor.");
}
return results;
});
pybind11::class_<vision::perception::Smoke, FastDeployModel>(m, "Smoke")
.def(pybind11::init<std::string, std::string, std::string, RuntimeOption,
ModelFormat>())
.def("predict",
[](vision::perception::Smoke& self, pybind11::array& data) {
auto mat = PyArrayToCvMat(data);
vision::PerceptionResult res;
self.Predict(mat, &res);
return res;
})
.def("batch_predict",
[](vision::perception::Smoke& self,
std::vector<pybind11::array>& data) {
std::vector<cv::Mat> images;
for (size_t i = 0; i < data.size(); ++i) {
images.push_back(PyArrayToCvMat(data[i]));
}
std::vector<vision::PerceptionResult> results;
self.BatchPredict(images, &results);
return results;
})
.def_property_readonly("preprocessor",
&vision::perception::Smoke::GetPreprocessor)
.def_property_readonly("postprocessor",
&vision::perception::Smoke::GetPostprocessor);
}
} // namespace fastdeploy

View File

@@ -0,0 +1,26 @@
// Copyright (c) 2022 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.
#include "fastdeploy/pybind/main.h"
namespace fastdeploy {
void BindSmoke(pybind11::module& m);
void BindPerception(pybind11::module& m) {
auto perception_module =
m.def_submodule("perception", "3D object perception models.");
BindSmoke(perception_module);
}
} // namespace fastdeploy

View File

@@ -33,6 +33,7 @@ void BindHeadPose(pybind11::module& m);
void BindSR(pybind11::module& m);
void BindGeneration(pybind11::module& m);
void BindVisualize(pybind11::module& m);
void BindPerception(pybind11::module& m);
void BindVision(pybind11::module& m) {
pybind11::class_<vision::Mask>(m, "Mask")
@@ -108,6 +109,40 @@ void BindVision(pybind11::module& m) {
.def("__repr__", &vision::DetectionResult::Str)
.def("__str__", &vision::DetectionResult::Str);
pybind11::class_<vision::PerceptionResult>(m, "PerceptionResult")
.def(pybind11::init())
.def_readwrite("scores", &vision::PerceptionResult::scores)
.def_readwrite("label_ids", &vision::PerceptionResult::label_ids)
.def_readwrite("boxes", &vision::PerceptionResult::boxes)
.def_readwrite("center", &vision::PerceptionResult::center)
.def_readwrite("observation_angle",
&vision::PerceptionResult::observation_angle)
.def_readwrite("yaw_angle", &vision::PerceptionResult::yaw_angle)
.def_readwrite("velocity", &vision::PerceptionResult::velocity)
.def(pybind11::pickle(
[](const vision::PerceptionResult& d) {
return pybind11::make_tuple(d.scores, d.label_ids, d.boxes,
d.center, d.observation_angle,
d.yaw_angle, d.velocity);
},
[](pybind11::tuple t) {
if (t.size() != 7)
throw std::runtime_error(
"vision::PerceptionResult pickle with Invalid state!");
vision::PerceptionResult d;
d.scores = t[0].cast<std::vector<float>>();
d.label_ids = t[1].cast<std::vector<int32_t>>();
d.boxes = t[2].cast<std::vector<std::array<float, 7>>>();
d.center = t[3].cast<std::vector<std::array<float, 3>>>();
d.observation_angle = t[4].cast<std::vector<float>>();
d.yaw_angle = t[5].cast<std::vector<float>>();
d.velocity = t[6].cast<std::vector<std::array<float, 3>>>();
return d;
}))
.def("__repr__", &vision::PerceptionResult::Str)
.def("__str__", &vision::PerceptionResult::Str);
pybind11::class_<vision::OCRResult>(m, "OCRResult")
.def(pybind11::init())
.def_readwrite("boxes", &vision::OCRResult::boxes)
@@ -224,5 +259,6 @@ void BindVision(pybind11::module& m) {
BindSR(m);
BindGeneration(m);
BindVisualize(m);
BindPerception(m);
}
} // namespace fastdeploy

View File

@@ -0,0 +1,194 @@
// Copyright (c) 2022 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.
#include <algorithm>
#include "fastdeploy/vision/visualize/visualize.h"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "yaml-cpp/yaml.h"
namespace fastdeploy {
namespace vision {
using matrix = std::vector<std::vector<float>>;
matrix Multiple(const matrix a, const matrix b) {
const int m = a.size(); // a rows
if (m == 0) {
matrix c;
return c;
}
if (a[0].size() != b.size()) {
FDERROR << "A[m,n] * B[p,q], n must equal to p." << std::endl;
matrix c;
return c;
}
const int n = a[0].size(); // a cols
const int p = b[0].size(); // b cols
matrix c(m, std::vector<float>(p, 0));
for (auto i = 0; i < m; i++) {
for (auto j = 0; j < p; j++) {
for (auto k = 0; k < n; k++) c[i][j] += a[i][k] * b[k][j];
}
}
return c;
}
cv::Mat VisPerception(const cv::Mat& im, const PerceptionResult& result,
const std::string& config_file, float score_threshold,
int line_size, float font_size) {
if (result.scores.empty()) {
return im;
}
YAML::Node cfg;
try {
cfg = YAML::LoadFile(config_file);
} catch (YAML::BadFile& e) {
FDERROR << "Failed to load yaml file " << config_file
<< ", maybe you should check this file." << std::endl;
return im;
}
std::vector<int> target_size;
for (const auto& op : cfg["Preprocess"]) {
std::string op_name = op["type"].as<std::string>();
if (op_name == "Resize") {
target_size = op["target_size"].as<std::vector<int>>();
}
}
std::vector<float> vec_k_data = cfg["k_data"].as<std::vector<float>>();
if (vec_k_data.size() != 9) {
FDERROR
<< "The K data load from the yaml file: " << config_file
<< " is unexpected, the expected size is 9, but the loaded size is: "
<< vec_k_data.size() << " ,maybe you should check this file."
<< std::endl;
return im;
}
matrix k_data(3, std::vector<float>());
for (auto j = 0; j < 3; j++) {
k_data[j].insert(k_data[j].begin(), vec_k_data.begin() + j * 3,
vec_k_data.begin() + j * 3 + 3);
}
std::vector<double> rvec = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
std::vector<double> tvec = {0, 0, 0};
matrix connect_line_id = {{1, 0}, {2, 7}, {3, 6}, {4, 5}, {1, 2}, {2, 3},
{3, 4}, {4, 1}, {0, 7}, {7, 6}, {6, 5}, {5, 0}};
int max_label_id =
*std::max_element(result.label_ids.begin(), result.label_ids.end());
std::vector<int> color_map = GenerateColorMap(max_label_id);
int h = im.rows;
int w = im.cols;
cv::Mat vis_im = im.clone();
cv::resize(im, vis_im, cv::Size(target_size[1], target_size[0]), 0, 0, 0);
for (size_t i = 0; i < result.scores.size(); ++i) {
if (result.scores[i] < 0.5) {
continue;
}
float h = result.boxes[i][4];
float w = result.boxes[i][5];
float l = result.boxes[i][6];
float x = result.center[i][0];
float y = result.center[i][1];
float z = result.center[i][2];
std::vector<float> x_corners = {0, l, l, l, l, 0, 0, 0};
std::vector<float> y_corners = {0, 0, h, h, 0, 0, h, h};
std::vector<float> z_corners = {0, 0, 0, w, w, w, w, 0};
for (auto j = 0; j < x_corners.size(); j++) {
x_corners[j] = x_corners[j] - l / 2;
y_corners[j] = y_corners[j] - h;
z_corners[j] = z_corners[j] - w / 2;
}
matrix corners_3d = {x_corners, y_corners, z_corners};
float ry = result.yaw_angle[i];
matrix rot_mat = {
{cosf(ry), 0, sinf(ry)}, {0, 1, 0}, {sinf(ry), 0, cosf(ry)}};
matrix rot_corners_3d = Multiple(rot_mat, corners_3d);
for (auto j = 0; j < rot_corners_3d[0].size(); j++) {
rot_corners_3d[0][j] += x;
rot_corners_3d[1][j] += y;
rot_corners_3d[2][j] += z;
}
auto corners_2d = Multiple(k_data, rot_corners_3d);
for (auto j = 0; j < corners_2d[0].size(); j++) {
corners_2d[0][j] /= corners_2d[2][j];
corners_2d[1][j] /= corners_2d[2][j];
}
std::vector<float> box2d = {
*std::min_element(corners_2d[0].begin(), corners_2d[0].end()),
*std::min_element(corners_2d[1].begin(), corners_2d[1].end()),
*std::max_element(corners_2d[0].begin(), corners_2d[0].end()),
*std::max_element(corners_2d[1].begin(), corners_2d[1].end())};
if (box2d[0] == 0 && box2d[1] == 0 && box2d[2] == 0 && box2d[3] == 0) {
continue;
}
std::vector<cv::Point3f> points3d;
for (auto j = 0; j < rot_corners_3d[0].size(); j++) {
points3d.push_back(cv::Point3f(rot_corners_3d[0][j], rot_corners_3d[1][j],
rot_corners_3d[2][j]));
}
cv::Mat rVec(3, 3, cv::DataType<double>::type, rvec.data());
cv::Mat tVec(3, 1, cv::DataType<double>::type, tvec.data());
std::vector<float> vec_k;
for (auto&& v : k_data) {
vec_k.insert(vec_k.end(), v.begin(), v.end());
}
cv::Mat intrinsicMat(3, 3, cv::DataType<float>::type, vec_k.data());
cv::Mat distCoeffs(5, 1, cv::DataType<double>::type);
std::vector<cv::Point2f> projectedPoints;
cv::projectPoints(points3d, rVec, tVec, intrinsicMat, distCoeffs,
projectedPoints);
int c0 = color_map[3 * result.label_ids[i] + 0];
int c1 = color_map[3 * result.label_ids[i] + 1];
int c2 = color_map[3 * result.label_ids[i] + 2];
cv::Scalar color = cv::Scalar(c0, c1, c2);
for (auto id = 0; id < connect_line_id.size(); id++) {
int p1 = connect_line_id[id][0];
int p2 = connect_line_id[id][1];
cv::line(vis_im, projectedPoints[p1], projectedPoints[p2], color, 1);
}
int font = cv::FONT_HERSHEY_SIMPLEX;
std::string score = std::to_string(result.scores[i]);
if (score.size() > 4) {
score = score.substr(0, 4);
}
std::string text = std::to_string(result.label_ids[i]) + ", " + score;
cv::Point2f original;
original.x = box2d[0];
original.y = box2d[1];
cv::putText(vis_im, text, original, font, font_size,
cv::Scalar(255, 255, 255), 1);
}
return vis_im;
}
} // namespace vision
} // namespace fastdeploy

View File

@@ -32,6 +32,12 @@ class FASTDEPLOY_DECL Visualize {
static cv::Mat VisDetection(const cv::Mat& im, const DetectionResult& result,
float score_threshold = 0.0, int line_size = 1,
float font_size = 0.5f);
static cv::Mat VisPerception(const cv::Mat& im,
const PerceptionResult& result,
const std::string & config_file,
float score_threshold = 0.0,
int line_size = 1,
float font_size = 0.5f);
static cv::Mat VisFaceDetection(const cv::Mat& im,
const FaceDetectionResult& result,
int line_size = 1, float font_size = 0.5f);
@@ -82,6 +88,22 @@ FASTDEPLOY_DECL cv::Mat VisDetection(const cv::Mat& im,
const std::vector<std::string>& labels,
float score_threshold = 0.0,
int line_size = 1, float font_size = 0.5f);
/** \brief Show the visualized results with custom labels for detection models
*
* \param[in] im the input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format
* \param[in] result the result produced by model
* \param[in] labels the visualized result will show the bounding box contain class label
* \param[in] score_threshold threshold for result scores, the bounding box will not be shown if the score is less than score_threshold
* \param[in] line_size line size for bounding boxes
* \param[in] font_size font size for text
* \return cv::Mat type stores the visualized results
*/
FASTDEPLOY_DECL cv::Mat VisPerception(const cv::Mat& im,
const PerceptionResult& result,
const std::string & config_file,
float score_threshold = 0.0,
int line_size = 1 ,
float font_size = 0.5f);
/** \brief Show the visualized results for classification models
*
* \param[in] im the input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format

View File

@@ -33,6 +33,18 @@ void BindVisualize(pybind11::module& m) {
vision::Mat(vis_im).ShareWithTensor(&out);
return TensorToPyArray(out);
})
.def("vis_perception",
[](pybind11::array& im_data, vision::PerceptionResult& result,
const std::string& config_file, float score_threshold,
int line_size, float font_size) {
auto im = PyArrayToCvMat(im_data);
auto vis_im =
vision::VisPerception(im, result, config_file, score_threshold,
line_size, font_size);
FDTensor out;
vision::Mat(vis_im).ShareWithTensor(&out);
return TensorToPyArray(out);
})
.def("vis_face_detection",
[](pybind11::array& im_data, vision::FaceDetectionResult& result,
int line_size, float font_size) {

View File

@@ -484,6 +484,29 @@ class RuntimeOption:
return self._option.trt_option.set_shape(tensor_name, min_shape,
opt_shape, max_shape)
def set_trt_input_data(self,
tensor_name,
min_input_data,
opt_input_data=None,
max_input_data=None):
"""Set input data while using TensorRT backend with loadding a model contains dynamic input shape.
:param tensor_name: (str)Name of input which has dynamic shape
:param min_input_data: (list of int)Input data for Minimum shape of the input.
:param opt_input_data: (list of int)Input data for Optimize shape of the input, if set to None, it will keep same with min_input_data
:param max_input_data: (list of int)Input data for Maximum shape of the input, if set to None, it will keep same with the min_input_data
"""
logging.warning(
"`RuntimeOption.set_trt_input_data` will be deprecated in v1.2.0, please use `RuntimeOption.trt_option.set_input_data()` instead."
)
if opt_input_data is None and max_input_data is None:
opt_input_data = min_input_data
opt_input_data = min_input_data
else:
assert opt_input_data is not None and max_input_data is not None, "Set min_input_data only, or set min_input_data, opt_input_data, max_input_data both."
return self._option.trt_option.set_input_data(
tensor_name, min_input_data, opt_input_data, max_input_data)
def set_trt_cache_file(self, cache_file_path):
"""Set a cache file path while using TensorRT backend. While loading a Paddle/ONNX model with set_trt_cache_file("./tensorrt_cache/model.trt"), if file `./tensorrt_cache/model.trt` exists, it will skip building tensorrt engine and load the cache file directly; if file `./tensorrt_cache/model.trt` doesn't exist, it will building tensorrt engine and save the engine as binary string to the cache file.

View File

@@ -27,6 +27,7 @@ from . import headpose
from . import sr
from . import evaluation
from . import generation
from . import perception
from .utils import fd_result_to_json
from .visualize import *
from .. import C

0
python/fastdeploy/vision/detection/ppdet/__init__.py Normal file → Executable file
View File

View File

@@ -0,0 +1,16 @@
# Copyright (c) 2022 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.
from __future__ import absolute_import
from .paddle3d.smoke import *

View File

@@ -0,0 +1,15 @@
# Copyright (c) 2022 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.
from __future__ import absolute_import

View File

@@ -0,0 +1,106 @@
# Copyright (c) 2022 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.
from __future__ import absolute_import
import logging
from .... import FastDeployModel, ModelFormat
from .... import c_lib_wrap as C
class SmokePreprocessor:
def __init__(self, config_file):
"""Create a preprocessor for Smoke
"""
self._preprocessor = C.vision.perception.SmokePreprocessor(config_file)
def run(self, input_ims):
"""Preprocess input images for Smoke
:param: input_ims: (list of numpy.ndarray)The input image
:return: list of FDTensor
"""
return self._preprocessor.run(input_ims)
class SmokePostprocessor:
def __init__(self):
"""Create a postprocessor for Smoke
"""
self._postprocessor = C.vision.perception.SmokePostprocessor()
def run(self, runtime_results):
"""Postprocess the runtime results for Smoke
:param: runtime_results: (list of FDTensor)The output FDTensor results from runtime
:return: list of PerceptionResult(If the runtime_results is predict by batched samples, the length of this list equals to the batch size)
"""
return self._postprocessor.run(runtime_results)
class Smoke(FastDeployModel):
def __init__(self,
model_file,
params_file,
config_file,
runtime_option=None,
model_format=ModelFormat.PADDLE):
"""Load a SMoke model exported by Smoke.
:param model_file: (str)Path of model file, e.g ./smoke.pdmodel
:param params_file: (str)Path of parameters file, e.g ./smoke.pdiparams
:param config_file: (str)Path of config file, e.g ./infer_cfg.yaml
:param runtime_option: (fastdeploy.RuntimeOption)RuntimeOption for inference this model, if it's None, will use the default backend on CPU
:param model_format: (fastdeploy.ModelForamt)Model format of the loaded model
"""
super(Smoke, self).__init__(runtime_option)
self._model = C.vision.perception.Smoke(
model_file, params_file, config_file, self._runtime_option,
model_format)
assert self.initialized, "Smoke initialize failed."
def predict(self, input_image):
"""Detect an input image
:param input_image: (numpy.ndarray)The input image data, 3-D array with layout HWC, BGR format
:param conf_threshold: confidence threshold for postprocessing, default is 0.25
:param nms_iou_threshold: iou threshold for NMS, default is 0.5
:return: PerceptionResult
"""
return self._model.predict(input_image)
def batch_predict(self, images):
"""Classify a batch of input image
:param im: (list of numpy.ndarray) The input image list, each element is a 3-D array with layout HWC, BGR format
:return list of PerceptionResult
"""
return self._model.batch_predict(images)
@property
def preprocessor(self):
"""Get SmokePreprocessor object of the loaded model
:return SmokePreprocessor
"""
return self._model.preprocessor
@property
def postprocessor(self):
"""Get SmokePostprocessor object of the loaded model
:return SmokePostprocessor
"""
return self._model.postprocessor

27
python/fastdeploy/vision/utils.py Normal file → Executable file
View File

@@ -38,6 +38,19 @@ def detection_to_json(result):
return json.dumps(r_json)
def perception_to_json(result):
r_json = {
"scores": result.scores,
"label_ids": result.label_ids,
"boxes": result.boxes,
"center": result.center,
"observation_angle": result.observation_angle,
"yaw_angle": result.yaw_angle,
"velocity": result.velocity
}
return json.dumps(r_json)
def classify_to_json(result):
r_json = {
"label_ids": result.label_ids,
@@ -151,6 +164,8 @@ def fd_result_to_json(result):
return matting_to_json(result)
elif isinstance(result, C.vision.HeadPoseResult):
return head_pose_to_json(result)
elif isinstance(result, C.vision.PerceptionResult):
return perception_to_json(result)
else:
assert False, "{} Conversion to JSON format is not supported".format(
type(result))
@@ -177,6 +192,18 @@ def json_to_detection(result):
return det_result
def json_to_perception(result):
perception_result = C.vision.PerceptionResult()
perception_result.scores = result['scores']
perception_result.label_ids = result['label_ids']
perception_result.boxes = result['boxes']
perception_result.center = result['center']
perception_result.observation_angle = result['observation_angle']
perception_result.yaw_angle = result['yaw_angle']
perception_result.velocity = result['velocity']
return perception_result
def json_to_classify(result):
cls_result = C.vision.ClassifyResult()
cls_result.label_ids = result['label_ids']

View File

@@ -38,6 +38,26 @@ def vis_detection(im_data,
line_size, font_size)
def vis_perception(im_data,
det_result,
config_file,
score_threshold=0.0,
line_size=1,
font_size=0.5):
"""Show the visualized results for 3d detection models
:param im_data: (numpy.ndarray)The input image data, 3-D array with layout HWC, BGR format
:param det_result: the result produced by model
:param config_file: the config file for detection and visualization
:param score_threshold: (float) score_threshold threshold for result scores, the bounding box will not be shown if the score is less than score_threshold
:param line_size: (float) line_size line size for bounding boxes
:param font_size: (float) font_size font size for text
:return: (numpy.ndarray) image with visualized results
"""
return C.vision.vis_perception(im_data, det_result, config_file,
score_threshold, line_size, font_size)
def vis_keypoint_detection(im_data, keypoint_det_result, conf_threshold=0.5):
"""Show the visualized results for keypoint detection models

2
python/scripts/process_libraries.py.in Normal file → Executable file
View File

@@ -46,7 +46,7 @@ def process_on_linux(current_dir):
if len(items) != 4:
os.remove(os.path.join(root, f))
continue
if items[0].strip() not in ["libopencv_highgui", "libopencv_video", "libopencv_videoio", "libopencv_imgcodecs", "libopencv_imgproc", "libopencv_core"]:
if items[0].strip() not in ["libopencv_highgui", "libopencv_video", "libopencv_videoio", "libopencv_imgcodecs", "libopencv_imgproc", "libopencv_core", "libopencv_calib3d", "libopencv_features2d", "libopencv_flann"]:
os.remove(os.path.join(root, f))
all_libs_paths = [third_libs_path] + user_specified_dirs