[Model] Support PP-ShiTuV2 models for PaddleClas (#1900)

* [cmake] add faiss.cmake -> pp-shituv2

* [PP-ShiTuV2] Support PP-ShituV2-Det model

* [PP-ShiTuV2] Support PP-ShiTuV2-Det model

* [PP-ShiTuV2] Add PPShiTuV2Recognizer c++&python support

* [PP-ShiTuV2] Add PPShiTuV2Recognizer c++&python support

* [Bug Fix] fix ppshitu_pybind error

* [benchmark] Add ppshituv2-det c++ benchmark

* [examples] Add PP-ShiTuV2 det & rec examples

* [vision] Update vision classification result

* [Bug Fix] fix trt shapes setting errors
This commit is contained in:
DefTruth
2023-05-08 14:04:09 +08:00
committed by GitHub
parent df8dd3e3ac
commit 77cb9db6da
31 changed files with 1835 additions and 51 deletions

View File

@@ -40,6 +40,8 @@ add_executable(benchmark_ttfnet ${PROJECT_SOURCE_DIR}/benchmark_ttfnet.cc)
add_executable(benchmark ${PROJECT_SOURCE_DIR}/benchmark.cc)
add_executable(benchmark_ppdet ${PROJECT_SOURCE_DIR}/benchmark_ppdet.cc)
add_executable(benchmark_dino ${PROJECT_SOURCE_DIR}/benchmark_dino.cc)
add_executable(benchmark_ppshituv2_rec ${PROJECT_SOURCE_DIR}/benchmark_ppshituv2_rec.cc)
add_executable(benchmark_ppshituv2_det ${PROJECT_SOURCE_DIR}/benchmark_ppshituv2_det.cc)
if(UNIX AND (NOT APPLE) AND (NOT ANDROID))
target_link_libraries(benchmark_yolov5 ${FASTDEPLOY_LIBS} gflags pthread)
@@ -75,6 +77,8 @@ if(UNIX AND (NOT APPLE) AND (NOT ANDROID))
target_link_libraries(benchmark ${FASTDEPLOY_LIBS} gflags pthread)
target_link_libraries(benchmark_ppdet ${FASTDEPLOY_LIBS} gflags pthread)
target_link_libraries(benchmark_dino ${FASTDEPLOY_LIBS} gflags pthread)
target_link_libraries(benchmark_ppshituv2_rec ${FASTDEPLOY_LIBS} gflags pthread)
target_link_libraries(benchmark_ppshituv2_det ${FASTDEPLOY_LIBS} gflags pthread)
else()
target_link_libraries(benchmark_yolov5 ${FASTDEPLOY_LIBS} gflags)
target_link_libraries(benchmark_ppyolov5 ${FASTDEPLOY_LIBS} gflags)
@@ -109,6 +113,8 @@ else()
target_link_libraries(benchmark ${FASTDEPLOY_LIBS} gflags)
target_link_libraries(benchmark_ppdet ${FASTDEPLOY_LIBS} gflags)
target_link_libraries(benchmark_dino ${FASTDEPLOY_LIBS} gflags)
target_link_libraries(benchmark_ppshituv2_rec ${FASTDEPLOY_LIBS} gflags)
target_link_libraries(benchmark_ppshituv2_det ${FASTDEPLOY_LIBS} gflags)
endif()
# only for Android ADB test
if(ANDROID)

20
benchmark/cpp/benchmark.cc Executable file → Normal file
View File

@@ -33,11 +33,14 @@ DEFINE_string(tensors, "tensor_a.txt:tensor_b.txt",
"The paths to dumped tensors.");
DEFINE_bool(mem, false, "Whether to force to collect memory info.");
DEFINE_int32(interval, -1, "Sampling interval for collect memory info.");
DEFINE_string(model_file, "UNKNOWN", "Optional, set specific model file,"
DEFINE_string(model_file, "UNKNOWN",
"Optional, set specific model file,"
"eg, model.pdmodel, model.onnx");
DEFINE_string(params_file, "", "Optional, set specific params file,"
DEFINE_string(params_file, "",
"Optional, set specific params file,"
"eg, model.pdiparams.");
DEFINE_string(model_format, "PADDLE", "Optional, set specific model format,"
DEFINE_string(model_format, "PADDLE",
"Optional, set specific model format,"
"eg, PADDLE/ONNX/RKNN/TORCHSCRIPT/SOPHGO");
DEFINE_bool(disable_mkldnn, false, "disable mkldnn for paddle backend");
@@ -117,8 +120,8 @@ static void RuntimeProfiling(int argc, char* argv[]) {
model_file = FLAGS_model + sep + FLAGS_model_file;
params_file = FLAGS_model + sep + FLAGS_params_file;
model_format = GetModelFormat(FLAGS_model_format);
if (model_format == fastdeploy::ModelFormat::PADDLE
&& FLAGS_params_file == "") {
if (model_format == fastdeploy::ModelFormat::PADDLE &&
FLAGS_params_file == "") {
std::cout << "[ERROR] params_file can not be empty for PADDLE"
<< " format, Please, set your custom params_file manually."
<< std::endl;
@@ -256,6 +259,9 @@ static void showInputInfos(int argc, char* argv[]) {
if (!CreateRuntimeOption(&option, argc, argv, true)) {
return;
}
if (FLAGS_disable_mkldnn) {
option.paddle_infer_option.enable_mkldnn = false;
}
std::unordered_map<std::string, std::string> config_info;
benchmark::ResultManager::LoadBenchmarkConfig(FLAGS_config_path,
&config_info);
@@ -286,7 +292,9 @@ static void showInputInfos(int argc, char* argv[]) {
int main(int argc, char* argv[]) {
#if defined(ENABLE_BENCHMARK)
google::SetVersionString("0.0.0");
google::SetUsageMessage("./benchmark -[info|diff|check|dump|mem] -model xxx -config_path xxx -[shapes|dtypes|names|tensors] -[model_file|params_file|model_format]");
google::SetUsageMessage(
"./benchmark -[info|diff|check|dump|mem] -model xxx -config_path xxx "
"-[shapes|dtypes|names|tensors] -[model_file|params_file|model_format]");
google::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_diff) {
CheckTensorDiff(argc, argv);

5
benchmark/cpp/benchmark_picodet.cc Executable file → Normal file
View File

@@ -49,8 +49,7 @@ int main(int argc, char* argv[]) {
config_info["backend"] == "trt") {
option.trt_option.SetShape("image", {1, 3, 640, 640}, {1, 3, 640, 640},
{1, 3, 640, 640});
option.trt_option.SetShape("scale_factor", {1, 2}, {1, 2},
{1, 2});
option.trt_option.SetShape("scale_factor", {1, 2}, {1, 2}, {1, 2});
}
auto model_picodet = vision::detection::PicoDet(
model_file, params_file, config_file, option, model_format);
@@ -81,7 +80,7 @@ int main(int argc, char* argv[]) {
}
// Run profiling
BENCHMARK_MODEL(model_picodet, model_picodet.Predict(im, &res))
auto vis_im = vision::VisDetection(im, res);
auto vis_im = vision::VisDetection(im, res, 0.5f);
cv::imwrite("vis_result.jpg", vis_im);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
#endif

View File

@@ -0,0 +1,89 @@
// Copyright (c) 2023 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 "flags.h"
#include "macros.h"
#include "option.h"
namespace vision = fastdeploy::vision;
namespace benchmark = fastdeploy::benchmark;
DEFINE_bool(no_nms, false, "Whether the model contains nms.");
int main(int argc, char* argv[]) {
#if defined(ENABLE_BENCHMARK) && defined(ENABLE_VISION)
// Initialization
auto option = fastdeploy::RuntimeOption();
if (!CreateRuntimeOption(&option, argc, argv, true)) {
return -1;
}
auto im = cv::imread(FLAGS_image);
std::unordered_map<std::string, std::string> config_info;
benchmark::ResultManager::LoadBenchmarkConfig(FLAGS_config_path,
&config_info);
std::string model_name, params_name, config_name;
auto model_format = fastdeploy::ModelFormat::PADDLE;
if (!UpdateModelResourceName(&model_name, &params_name, &config_name,
&model_format, config_info)) {
return -1;
}
auto model_file = FLAGS_model + sep + model_name;
auto params_file = FLAGS_model + sep + params_name;
auto config_file = FLAGS_model + sep + config_name;
if (config_info["backend"] == "paddle_trt") {
option.paddle_infer_option.collect_trt_shape = true;
}
if (config_info["backend"] == "paddle_trt" ||
config_info["backend"] == "trt") {
option.trt_option.SetShape("image", {1, 3, 640, 640}, {1, 3, 640, 640},
{1, 3, 640, 640});
option.trt_option.SetShape("scale_factor", {1, 2}, {1, 2}, {1, 2});
option.trt_option.SetShape("im_shape", {1, 2}, {1, 2}, {1, 2});
}
auto model = vision::classification::PPShiTuV2Detector(
model_file, params_file, config_file, option, model_format);
if (FLAGS_no_nms) {
model.GetPostprocessor().ApplyNMS();
}
vision::DetectionResult res;
if (config_info["precision_compare"] == "true") {
// Run once at least
model.Predict(im, &res);
// 1. Test result diff
std::cout << "=============== Test result diff =================\n";
// Save result to -> disk.
std::string det_result_path = "ppshituv2_det_result.txt";
benchmark::ResultManager::SaveDetectionResult(res, det_result_path);
// Load result from <- disk.
vision::DetectionResult res_loaded;
benchmark::ResultManager::LoadDetectionResult(&res_loaded, det_result_path);
// Calculate diff between two results.
auto det_diff =
benchmark::ResultManager::CalculateDiffStatis(res, res_loaded);
std::cout << "Boxes diff: mean=" << det_diff.boxes.mean
<< ", max=" << det_diff.boxes.max
<< ", min=" << det_diff.boxes.min << std::endl;
std::cout << "Label_ids diff: mean=" << det_diff.labels.mean
<< ", max=" << det_diff.labels.max
<< ", min=" << det_diff.labels.min << std::endl;
}
// Run profiling
BENCHMARK_MODEL(model, model.Predict(im, &res))
auto vis_im = vision::VisDetection(im, res, 0.5f);
cv::imwrite("vis_result.jpg", vis_im);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
#endif
return 0;
}

View File

@@ -0,0 +1,93 @@
// Copyright (c) 2023 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 "flags.h"
#include "macros.h"
#include "option.h"
namespace vision = fastdeploy::vision;
namespace benchmark = fastdeploy::benchmark;
DEFINE_string(trt_shape, "1,3,224,224:1,3,224,224:1,3,224,224",
"Set min/opt/max shape for trt/paddle_trt backend."
"eg:--trt_shape 1,3,224,224:1,3,224,224:1,3,224,224");
DEFINE_string(input_name, "x",
"Set input name for trt/paddle_trt backend."
"eg:--input_names x");
int main(int argc, char* argv[]) {
#if defined(ENABLE_BENCHMARK) && defined(ENABLE_VISION)
// Initialization
auto option = fastdeploy::RuntimeOption();
if (!CreateRuntimeOption(&option, argc, argv, true)) {
return -1;
}
auto im = cv::imread(FLAGS_image);
std::unordered_map<std::string, std::string> config_info;
benchmark::ResultManager::LoadBenchmarkConfig(FLAGS_config_path,
&config_info);
// Set max_batch_size 1 for best performance
if (config_info["backend"] == "paddle_trt") {
option.trt_option.max_batch_size = 1;
}
std::string model_name, params_name, config_name;
auto model_format = fastdeploy::ModelFormat::PADDLE;
if (!UpdateModelResourceName(&model_name, &params_name, &config_name,
&model_format, config_info)) {
return -1;
}
auto model_file = FLAGS_model + sep + model_name;
auto params_file = FLAGS_model + sep + params_name;
auto config_file = FLAGS_model + sep + config_name;
if (config_info["backend"] == "paddle_trt") {
option.paddle_infer_option.collect_trt_shape = true;
}
if (config_info["backend"] == "paddle_trt" ||
config_info["backend"] == "trt") {
std::vector<std::vector<int32_t>> trt_shapes =
benchmark::ResultManager::GetInputShapes(FLAGS_trt_shape);
option.trt_option.SetShape(FLAGS_input_name, trt_shapes[0], trt_shapes[1],
trt_shapes[2]);
}
auto model = vision::classification::PPShiTuV2Recognizer(
model_file, params_file, config_file, option, model_format);
vision::ClassifyResult res;
if (config_info["precision_compare"] == "true") {
// Run once at least
model.Predict(im, &res);
// 1. Test result diff
std::cout << "=============== Test result diff =================\n";
// Save result to -> disk.
std::string cls_result_path = "ppcls_result.txt";
benchmark::ResultManager::SaveClassifyResult(res, cls_result_path);
// Load result from <- disk.
vision::ClassifyResult res_loaded;
benchmark::ResultManager::LoadClassifyResult(&res_loaded, cls_result_path);
// Calculate diff between two results.
auto cls_diff =
benchmark::ResultManager::CalculateDiffStatis(res, res_loaded);
std::cout << "Labels diff: mean=" << cls_diff.labels.mean
<< ", max=" << cls_diff.labels.max
<< ", min=" << cls_diff.labels.min << std::endl;
std::cout << "Scores diff: mean=" << cls_diff.scores.mean
<< ", max=" << cls_diff.scores.max
<< ", min=" << cls_diff.scores.min << std::endl;
}
BENCHMARK_MODEL(model, model.Predict(im, &res))
#endif
return 0;
}

163
cmake/faiss.cmake Normal file
View File

@@ -0,0 +1,163 @@
# 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(ExternalProject)
set(FAISS_PROJECT external_faiss_download)
set(FAISS_FILENAME faiss)
set(FAISS_PREFIX_DIR ${THIRD_LIBS_PATH}/${FAISS_FILENAME})
set(FAISS_SOURCE_DIR ${THIRD_LIBS_PATH}/${FAISS_FILENAME}/src/${FAISS_PROJECT})
set(FAISS_INSTALL_DIR ${THIRD_LIBS_PATH}/install/${FAISS_FILENAME})
set(FAISS_INC_DIR ${FAISS_INSTALL_DIR}/include CACHE PATH "faiss include directory." FORCE)
if(ANDROID)
set(FAISS_LIB_DIR ${FAISS_INSTALL_DIR}/lib/${ANDROID_ABI} CACHE PATH "faiss lib directory." FORCE)
else()
set(FAISS_LIB_DIR ${FAISS_INSTALL_DIR}/lib CACHE PATH "faiss lib directory." FORCE)
endif()
if(NOT WITH_FAISS_STATIC)
message(FATAL_ERROR "Not support WITH_FAISS_STATIC=OFF now!")
endif()
set(FAISS_URL_PREFIX "https://bj.bcebos.com/fastdeploy/test")
if(ANDROID)
# check ABI, toolchain
if((NOT ANDROID_ABI MATCHES "armeabi-v7a") AND (NOT ANDROID_ABI MATCHES "arm64-v8a"))
message(FATAL_ERROR "FAISS only support armeabi-v7a, arm64-v8a now.")
endif()
if(NOT ANDROID_TOOLCHAIN MATCHES "clang")
message(FATAL_ERROR "Currently, only support clang toolchain but found ${ANDROID_TOOLCHAIN}.")
endif()
endif()
set(FAISS_VERSION 1.7.3)
# URL
if(NOT FAISS_URL)
if(WIN32)
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-win-x64-${FAISS_VERSION}.zip")
elseif(APPLE)
if(CURRENT_OSX_ARCH MATCHES "arm64")
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-osx-arm64-${FAISS_VERSION}.tgz")
else()
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-osx-x64-${FAISS_VERSION}.tgz")
endif()
elseif(ANDROID)
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-android-${ANDROID_ABI}-${FAISS_VERSION}.tgz")
else() # Linux
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64")
message(FATAL_ERROR "Not support for Linux aarch64 now!")
else()
if(WITH_FAISS_GPU)
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-linux-x64-gpu-${FAISS_VERSION}.tgz")
else()
set(FAISS_URL "${FAISS_URL_PREFIX}/faiss-linux-x64-${FAISS_VERSION}.tgz")
endif()
endif()
endif()
endif()
# FAISS Headers
include_directories(${FAISS_INC_DIR})
# FAISS Libs paths
if(WIN32)
set(FAISS_LIB "${FAISS_LIB_DIR}/faiss.lib")
elseif(APPLE)
set(FAISS_LIB "${FAISS_LIB_DIR}/libfaiss.a")
elseif(ANDROID)
set(FAISS_LIB "${FAISS_LIB_DIR}/libfaiss.a")
else() # Linux
set(FAISS_LIB "${FAISS_LIB_DIR}/libfaiss.a")
endif()
# Download FAISS
if(ANDROID)
ExternalProject_Add(
${FAISS_PROJECT}
${EXTERNAL_PROJECT_LOG_ARGS}
URL ${FAISS_URL}
PREFIX ${FAISS_PREFIX_DIR}
DOWNLOAD_NO_PROGRESS 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
UPDATE_COMMAND ""
INSTALL_COMMAND
${CMAKE_COMMAND} -E remove_directory ${FAISS_INSTALL_DIR} &&
${CMAKE_COMMAND} -E make_directory ${FAISS_INSTALL_DIR} &&
${CMAKE_COMMAND} -E make_directory ${FAISS_INSTALL_DIR}/lib &&
${CMAKE_COMMAND} -E rename ${FAISS_SOURCE_DIR}/lib/ ${FAISS_INSTALL_DIR}/lib/${ANDROID_ABI} &&
${CMAKE_COMMAND} -E copy_directory ${FAISS_SOURCE_DIR}/include ${FAISS_INC_DIR}
BUILD_BYPRODUCTS ${FAISS_LIB})
else()
ExternalProject_Add(
${FAISS_PROJECT}
${EXTERNAL_PROJECT_LOG_ARGS}
URL ${FAISS_URL}
PREFIX ${FAISS_PREFIX_DIR}
DOWNLOAD_NO_PROGRESS 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
UPDATE_COMMAND ""
INSTALL_COMMAND
${CMAKE_COMMAND} -E remove_directory ${FAISS_INSTALL_DIR} &&
${CMAKE_COMMAND} -E make_directory ${FAISS_INSTALL_DIR} &&
${CMAKE_COMMAND} -E rename ${FAISS_SOURCE_DIR}/lib/ ${FAISS_INSTALL_DIR}/lib &&
${CMAKE_COMMAND} -E copy_directory ${FAISS_SOURCE_DIR}/include ${FAISS_INC_DIR}
BUILD_BYPRODUCTS ${FAISS_LIB})
endif()
set(FAISS_LIBRARIES)
add_library(external_faiss STATIC IMPORTED GLOBAL)
set_property(TARGET external_faiss PROPERTY IMPORTED_LOCATION ${FAISS_LIB})
add_dependencies(external_faiss ${FAISS_PROJECT})
list(APPEND FAISS_LIBRARIES external_faiss)
# Add BLAS/LAPACK/OpenBLAS (needed by FAISS)
if(WIN32)
add_library(external_blas STATIC IMPORTED GLOBAL)
set_property(TARGET external_blas PROPERTY IMPORTED_LOCATION ${FAISS_LIB_DIR}/BLAS.lib)
add_dependencies(external_blas ${FAISS_PROJECT})
list(APPEND FAISS_LIBRARIES external_blas)
add_library(external_lapack STATIC IMPORTED GLOBAL)
set_property(TARGET external_lapack PROPERTY IMPORTED_LOCATION ${FAISS_LIB_DIR}/LAPACK.lib)
add_dependencies(external_lapack ${FAISS_PROJECT})
list(APPEND FAISS_LIBRARIES external_lapack)
elseif(APPLE)
find_package(BLAS REQUIRED)
list(APPEND FAISS_LIBRARIES ${BLAS_LIBRARIES})
find_package(LAPACK REQUIRED)
list(APPEND FAISS_LIBRARIES ${LAPACK_LIBRARIES})
elseif(ANDROID)
# OpenBLAS static lib already merged into libfaiss.a
message(STATUS "For Android, OpenBLAS static lib was already merged into libfaiss.a")
else() # Linux
find_package(BLAS REQUIRED)
list(APPEND FAISS_LIBRARIES ${BLAS_LIBRARIES})
find_package(LAPACK REQUIRED)
list(APPEND FAISS_LIBRARIES ${LAPACK_LIBRARIES})
endif()
# Add OpenMP (REQUIRED), OpenMP must be avaliable.
find_package(OpenMP REQUIRED)
list(APPEND FAISS_LIBRARIES OpenMP::OpenMP_CXX)
set(FAISS_INCLUDE_DIRS ${FAISS_INC_DIR})
set(FAISS_LIBS ${FAISS_LIBRARIES})
set(FAISS_FOUND TRUE)

View File

@@ -0,0 +1,5 @@
[English](README.md) | 简体中文
## 详细部署的部署示例
- [Python部署](python)
- [C++部署](cpp)

View File

@@ -0,0 +1,14 @@
PROJECT(infer_demo C CXX)
CMAKE_MINIMUM_REQUIRED (VERSION 3.10)
option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.")
include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake)
include_directories(${FASTDEPLOY_INCS})
add_executable(infer_ppshituv2_det_demo ${PROJECT_SOURCE_DIR}/infer_ppshituv2_det.cc)
add_executable(infer_ppshituv2_rec_demo ${PROJECT_SOURCE_DIR}/infer_ppshituv2_rec.cc)
target_link_libraries(infer_ppshituv2_det_demo ${FASTDEPLOY_LIBS})
target_link_libraries(infer_ppshituv2_rec_demo ${FASTDEPLOY_LIBS})

View File

@@ -0,0 +1,89 @@
# PaddleClas CPU-GPU C++部署示例
本目录下提供`infer_shituv2_xxx.cc`快速完成PP-ShiTuV2系列模型在CPU/GPU以及GPU上通过TensorRT加速部署的示例。
## 1. 说明
PP-ShiTuV2支持利用FastDeploy在NVIDIA GPU、X86 CPU、飞腾CPU、ARM CPU、Intel GPU(独立显卡/集成显卡)硬件上快速部署图像分类模型.
## 2. 部署环境准备
在部署前,需确认软硬件环境,同时下载预编译部署库,参考[FastDeploy安装文档](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install#FastDeploy预编译库安装)安装FastDeploy预编译库.
## 3. 运行部署示例
以Linux上推理为例在本目录执行如下命令即可完成编译测试支持此模型需保证FastDeploy版本1.0.0以上(x.x.x>=1.0.0)
```bash
# 下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd FastDeploy/examples/vision/classification/ppshitu/cpu-gpu/cpp
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 -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar && tar -xf picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar
wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/PP-ShiTuV2/general_PPLCNetV2_base_pretrained_v1.0_infer.tar && tar -xf general_PPLCNetV2_base_pretrained_v1.0_infer.tar
wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/data/drink_dataset_v2.0.tar && tar -xf drink_dataset_v2.0.tar
# 在CPU上使用Paddle Inference推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 0
# 在CPU上使用OenVINO推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 1
# 在CPU上使用ONNX Runtime推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 2
# 在CPU上使用Paddle Lite推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 3
# 在GPU上使用Paddle Inference推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 4
# 在GPU上使用Paddle TensorRT推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 5
# 在GPU上使用ONNX Runtime推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 6
# 在GPU上使用Nvidia TensorRT推理
./infer_ppshituv2_det_demo picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer drink_dataset_v2.0/test_images/100.jpeg 7
```
以上命令只适用于Linux或MacOS, Windows下SDK的使用方式请参考:
- [如何在Windows中使用FastDeploy C++ SDK](../../../../../docs/cn/faq/use_sdk_on_windows.md)
## 4. 部署示例选项说明
在我们使用`infer_ppshituv2_det_demo`时, 输入了3个参数, 分别为分类模型, 预测图片, 与最后一位的数字选项.
现在下表将解释最后一位数字选项的含义.
|数字选项|含义|
|:---:|:---:|
|0| 在CPU上使用Paddle Inference推理 |
|1| 在CPU上使用OenVINO推理 |
|2| 在CPU上使用ONNX Runtime推理 |
|3| 在CPU上使用Paddle Lite推理 |
|4| 在GPU上使用Paddle Inference推理 |
|5| 在GPU上使用Paddle TensorRT推理 |
|6| 在GPU上使用ONNX Runtime推理 |
|7| 在GPU上使用Nvidia TensorRT推理 |
- 关于如何通过FastDeploy使用更多不同的推理后端以及如何使用不同的硬件请参考文档[如何切换模型推理后端引擎](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/how_to_change_backend.md)
## 5. 更多指南
- [PaddleClas系列 C++ API查阅](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/cpp/html/namespacefastdeploy_1_1vision_1_1classification.html)
- [PaddleClas Python部署](../python)
- [PaddleClas C 部署](../c)
- [PaddleClas C# 部署](../csharp)
## 6. 常见问题
- PaddleClas能在FastDeploy支持的多种后端上推理,支持情况如下表所示, 如何切换后端, 详见文档[如何切换模型推理后端引擎](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/how_to_change_backend.md)
|硬件类型|支持的后端|
|:---:|:---:|
|X86 CPU| Paddle Inference, ONNX Runtime, OpenVINO |
|ARM CPU| Paddle Lite |
|飞腾 CPU| ONNX Runtime |
|NVIDIA GPU| Paddle Inference, ONNX Runtime, TensorRT |
- [Intel GPU(独立显卡/集成显卡)的使用](https://github.com/PaddlePaddle/FastDeploy/blob/develop/tutorials/intel_gpu/README.md)
- [编译CPU部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/cpu.md)
- [编译GPU部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/gpu.md)
- [编译Jetson部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/jetson.md)

View File

@@ -0,0 +1,96 @@
// 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 + "inference.pdmodel";
auto params_file = model_dir + sep + "inference.pdiparams";
auto config_file = model_dir + sep + "infer_cfg.yml";
auto model = fastdeploy::vision::classification::PPShiTuV2Detector(
model_file, params_file, config_file, option);
if (!model.Initialized()) {
std::cerr << "Failed to initialize." << std::endl;
return;
}
auto im = cv::imread(image_file);
fastdeploy::vision::DetectionResult res;
if (!model.Predict(im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
// print res
std::cout << res.Str() << std::endl;
auto vis_im = fastdeploy::vision::VisDetection(im, res, 0.5);
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/model path/to/image run_option, "
"e.g ./infer_demo "
"./picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer ./test.jpeg 0"
<< std::endl;
return -1;
}
fastdeploy::RuntimeOption option;
int flag = std::atoi(argv[3]);
if (flag == 0) {
option.UseCpu();
option.UsePaddleBackend(); // Paddle Inference
} else if (flag == 1) {
option.UseCpu();
option.UseOpenVINOBackend(); // OpenVINO
} else if (flag == 2) {
option.UseCpu();
option.UseOrtBackend(); // ONNX Runtime
} else if (flag == 3) {
option.UseCpu();
option.UseLiteBackend(); // Paddle Lite
} else if (flag == 4) {
option.UseGpu();
option.UsePaddleBackend(); // Paddle Inference
} else if (flag == 5) {
option.UseGpu();
option.UsePaddleInferBackend();
option.paddle_infer_option.enable_trt = true;
option.trt_option.SetShape("image", {1, 3, 640, 640}, {1, 3, 640, 640},
{1, 3, 640, 640});
option.trt_option.SetShape("scale_factor", {1, 2}, {1, 2}, {1, 2});
option.trt_option.SetShape("im_shape", {1, 2}, {1, 2}, {1, 2});
} else if (flag == 6) {
option.UseGpu();
option.UseOrtBackend(); // ONNX Runtime
} else if (flag == 7) {
option.UseGpu();
option.UseTrtBackend(); // TensorRT
}
std::string model_dir = argv[1];
std::string image_dir = argv[2];
InitAndInfer(model_dir, image_dir, option);
}

View File

@@ -0,0 +1,89 @@
// 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 + "inference.pdmodel";
auto params_file = model_dir + sep + "inference.pdiparams";
auto config_file = model_dir + sep + "inference_cls.yaml";
auto model = fastdeploy::vision::classification::PPShiTuV2Recognizer(
model_file, params_file, config_file, option);
if (!model.Initialized()) {
std::cerr << "Failed to initialize." << std::endl;
return;
}
auto im = cv::imread(image_file);
fastdeploy::vision::ClassifyResult res;
if (!model.Predict(im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
// print res
std::cout << res.Str() << std::endl;
}
int main(int argc, char *argv[]) {
if (argc < 4) {
std::cout << "Usage: infer_demo path/to/model path/to/image run_option, "
"e.g ./infer_demo "
"./general_PPLCNetV2_base_pretrained_v1.0_infer ./test.jpeg 0"
<< std::endl;
return -1;
}
fastdeploy::RuntimeOption option;
int flag = std::atoi(argv[3]);
if (flag == 0) {
option.UseCpu();
option.UsePaddleBackend(); // Paddle Inference
} else if (flag == 1) {
option.UseCpu();
option.UseOpenVINOBackend(); // OpenVINO
} else if (flag == 2) {
option.UseCpu();
option.UseOrtBackend(); // ONNX Runtime
} else if (flag == 3) {
option.UseCpu();
option.UseLiteBackend(); // Paddle Lite
} else if (flag == 4) {
option.UseGpu();
option.UsePaddleBackend(); // Paddle Inference
} else if (flag == 5) {
option.UseGpu();
option.UsePaddleInferBackend();
option.paddle_infer_option.enable_trt = true;
} else if (flag == 6) {
option.UseGpu();
option.UseOrtBackend(); // ONNX Runtime
} else if (flag == 7) {
option.UseGpu();
option.UseTrtBackend(); // TensorRT
}
std::string model_dir = argv[1];
std::string image_dir = argv[2];
InitAndInfer(model_dir, image_dir, option);
}

View File

@@ -0,0 +1,75 @@
# PaddleClas CPU-GPU Python部署示例
本目录下提供`infer_ppshituv2_det.py`快速完成PP-ShiTuV2在CPU/GPU上部署的示例.
## 1. 说明
PP-ShiTuV2支持利用FastDeploy在NVIDIA GPU、X86 CPU、飞腾CPU、ARM CPU、Intel GPU(独立显卡/集成显卡)硬件上快速部署图像分类模型
## 2. 部署环境准备
在部署前,需确认软硬件环境,同时下载预编译部署库,参考[FastDeploy安装文档](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install#FastDeploy预编译库安装)安装FastDeploy预编译库.
## 3. 运行部署示例
```bash
# 安装FastDpeloy python包详细文档请参考`部署环境准备`
pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
conda config --add channels conda-forge && conda install cudatoolkit=11.2 cudnn=8.2
# 下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd FastDeploy/examples/vision/classification/ppshitu/cpu-gpu/python
# 下载模型文件和测试图片
wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar && tar -xf picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer.tar
wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/PP-ShiTuV2/general_PPLCNetV2_base_pretrained_v1.0_infer.tar && tar -xf general_PPLCNetV2_base_pretrained_v1.0_infer.tar
wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/data/drink_dataset_v2.0.tar && tar -xf drink_dataset_v2.0.tar
# 在CPU上使用Paddle Inference推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device cpu --backend paddle
# 在CPU上使用OenVINO推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device cpu --backend openvino
# 在CPU上使用ONNX Runtime推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device cpu --backend ort
# 在CPU上使用Paddle Lite推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device cpu --backend pplite
# 在GPU上使用Paddle Inference推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device gpu --backend paddle
# 在GPU上使用Paddle TensorRT推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device gpu --backend pptrt
# 在GPU上使用ONNX Runtime推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device gpu --backend ort
# 在GPU上使用Nvidia TensorRT推理
python infer_ppshituv2_det.py --model picodet_PPLCNet_x2_5_mainbody_lite_v1.0_infer --image drink_dataset_v2.0/test_images/100.jpeg --device gpu --backend trt
```
## 4. 部署示例选项说明
|参数|含义|默认值
|---|---|---|
|--model|指定模型文件夹所在的路径|None|
|--image|指定测试图片所在的路径|None|
|--device|指定即将运行的硬件类型,支持的值为`[cpu, gpu]`当设置为cpu时可运行在x86 cpu/arm cpu等cpu上|cpu|
|--device_id|使用gpu时, 指定设备号|0|
|--backend|部署模型时使用的后端, 支持的值为`[paddle,pptrt,pplite,ort,openvino,trt]` |openvino|
|--topk|返回的前topk准确率, 支持的为`1,5` |1|
关于如何通过FastDeploy使用更多不同的推理后端以及如何使用不同的硬件请参考文档[如何切换模型推理后端引擎](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/how_to_change_backend.md)
## 5. 更多指南
- [PaddleClas系列 Python API查阅](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/python/html/image_classification.html)
- [PaddleClas C++ 部署](../cpp)
- [PaddleClas C 部署](../c)
- [PaddleClas C# 部署](../csharp)
## 6. 常见问题
- PaddleClas能在FastDeploy支持的多种后端上推理,支持情况如下表所示, 如何切换后端, 详见文档[如何切换模型推理后端引擎](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/how_to_change_backend.md)
|硬件类型|支持的后端|
|:---:|:---:|
|X86 CPU| Paddle Inference, ONNX Runtime, OpenVINO |
|ARM CPU| Paddle Lite |
|飞腾 CPU| ONNX Runtime |
|NVIDIA GPU| Paddle Inference, ONNX Runtime, TensorRT |
- [Intel GPU(独立显卡/集成显卡)的使用](https://github.com/PaddlePaddle/FastDeploy/blob/develop/tutorials/intel_gpu/README.md)
- [编译CPU部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/cpu.md)
- [编译GPU部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/gpu.md)
- [编译Jetson部署库](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/jetson.md)

View File

@@ -0,0 +1,96 @@
import fastdeploy as fd
import cv2
import os
def parse_arguments():
import argparse
import ast
parser = argparse.ArgumentParser()
parser.add_argument(
"--model", required=True, help="Path of PP-ShiTuV2 detector model.")
parser.add_argument(
"--image", type=str, 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' or 'ipu' or 'kunlunxin' or 'ascend' ."
)
parser.add_argument(
"--device_id",
type=int,
default=0,
help="Define which GPU card used to run model.")
parser.add_argument(
"--backend",
type=str,
default="default",
help="Type of inference backend, support ort/trt/paddle/openvino, default 'openvino' for cpu, 'tensorrt' for gpu"
)
return parser.parse_args()
def build_option(args):
option = fd.RuntimeOption()
if args.device.lower() == "gpu":
option.use_gpu(args.device_id)
if args.backend.lower() == "trt":
assert args.device.lower(
) == "gpu", "TensorRT backend require inference on device GPU."
option.use_trt_backend()
elif args.backend.lower() == "pptrt":
assert args.device.lower(
) == "gpu", "Paddle-TensorRT backend require inference on device GPU."
option.use_paddle_infer_backend()
option.paddle_infer_option.enable_trt = True
option.paddle_infer_option.collect_trt_shape = True
option.trt_option.set_shape("image", [1, 3, 640, 640],
[1, 3, 640, 640], [1, 3, 640, 640])
option.trt_option.set_shape("scale_factor", [1, 2], [1, 2], [1, 2])
option.trt_option.set_shape("im_shape", [1, 2], [1, 2], [1, 2])
elif args.backend.lower() == "ort":
option.use_ort_backend()
elif args.backend.lower() == "paddle":
option.use_paddle_infer_backend()
elif args.backend.lower() == "openvino":
assert args.device.lower(
) == "cpu", "OpenVINO backend require inference on device CPU."
option.use_openvino_backend()
elif args.backend.lower() == "pplite":
assert args.device.lower(
) == "cpu", "Paddle Lite backend require inference on device CPU."
option.use_lite_backend()
return option
args = parse_arguments()
# 配置runtime加载模型
runtime_option = build_option(args)
model_file = os.path.join(args.model, "inference.pdmodel")
params_file = os.path.join(args.model, "inference.pdiparams")
config_file = os.path.join(args.model, "infer_cfg.yml")
model = fd.vision.classification.PPShiTuV2Detector(
model_file, params_file, config_file, runtime_option=runtime_option)
# 预测主体检测结果
im = cv2.imread(args.image)
result = model.predict(im)
# 预测结果可视化
vis_im = fd.vision.vis_detection(im, result, score_threshold=0.5)
cv2.imwrite("visualized_result.jpg", vis_im)
print("Visualized result save in ./visualized_result.jpg")
print(result)

View File

@@ -0,0 +1,85 @@
import fastdeploy as fd
import cv2
import os
def parse_arguments():
import argparse
import ast
parser = argparse.ArgumentParser()
parser.add_argument(
"--model", required=True, help="Path of PP-ShiTuV2 recognizer model.")
parser.add_argument(
"--image", type=str, 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' or 'ipu' or 'kunlunxin' or 'ascend' ."
)
parser.add_argument(
"--device_id",
type=int,
default=0,
help="Define which GPU card used to run model.")
parser.add_argument(
"--backend",
type=str,
default="default",
help="Type of inference backend, support ort/trt/paddle/openvino, default 'openvino' for cpu, 'tensorrt' for gpu"
)
return parser.parse_args()
def build_option(args):
option = fd.RuntimeOption()
if args.device.lower() == "gpu":
option.use_gpu(args.device_id)
if args.backend.lower() == "trt":
assert args.device.lower(
) == "gpu", "TensorRT backend require inference on device GPU."
option.use_trt_backend()
elif args.backend.lower() == "pptrt":
assert args.device.lower(
) == "gpu", "Paddle-TensorRT backend require inference on device GPU."
option.use_paddle_infer_backend()
option.paddle_infer_option.enable_trt = True
elif args.backend.lower() == "ort":
option.use_ort_backend()
elif args.backend.lower() == "paddle":
option.use_paddle_infer_backend()
elif args.backend.lower() == "openvino":
assert args.device.lower(
) == "cpu", "OpenVINO backend require inference on device CPU."
option.use_openvino_backend()
elif args.backend.lower() == "pplite":
assert args.device.lower(
) == "cpu", "Paddle Lite backend require inference on device CPU."
option.use_lite_backend()
return option
args = parse_arguments()
# 配置runtime加载模型
runtime_option = build_option(args)
model_file = os.path.join(args.model, "inference.pdmodel")
params_file = os.path.join(args.model, "inference.pdiparams")
config_file = os.path.join(args.model, "inference_cls.yaml")
model = fd.vision.classification.PPShiTuV2Recognizer(
model_file, params_file, config_file, runtime_option=runtime_option)
# 预测特征抽取结果
im = cv2.imread(args.image)
result = model.predict(im)
print(result)

View File

@@ -18,6 +18,8 @@
#include "fastdeploy/vision/classification/contrib/resnet.h"
#include "fastdeploy/vision/classification/contrib/yolov5cls/yolov5cls.h"
#include "fastdeploy/vision/classification/ppcls/model.h"
#include "fastdeploy/vision/classification/ppshitu/ppshituv2_rec.h"
#include "fastdeploy/vision/classification/ppshitu/ppshituv2_det.h"
#include "fastdeploy/vision/detection/contrib/nanodet_plus.h"
#include "fastdeploy/vision/detection/contrib/scaledyolov4.h"
#include "fastdeploy/vision/detection/contrib/yolor.h"

View File

@@ -18,12 +18,17 @@ namespace fastdeploy {
void BindYOLOv5Cls(pybind11::module& m);
void BindPaddleClas(pybind11::module& m);
void BindPPShiTuV2(pybind11::module& m);
void BindResNet(pybind11::module& m);
void BindClassification(pybind11::module& m) {
auto classification_module =
m.def_submodule("classification", "Image classification models.");
BindYOLOv5Cls(classification_module);
BindPaddleClas(classification_module);
BindPPShiTuV2(classification_module);
BindResNet(classification_module);
}
} // namespace fastdeploy

View File

@@ -0,0 +1,101 @@
// 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 BindPPShiTuV2(pybind11::module& m) {
pybind11::class_<vision::classification::PPShiTuV2RecognizerPreprocessor,
vision::ProcessorManager>(m,
"PPShiTuV2RecognizerPreprocessor")
.def(pybind11::init<std::string>())
.def("disable_normalize",
[](vision::classification::PPShiTuV2RecognizerPreprocessor& self) {
self.DisableNormalize();
})
.def("disable_permute",
[](vision::classification::PPShiTuV2RecognizerPreprocessor& self) {
self.DisablePermute();
})
.def("initial_resize_on_cpu",
[](vision::classification::PPShiTuV2RecognizerPreprocessor& self,
bool v) { self.InitialResizeOnCpu(v); });
pybind11::class_<vision::classification::PPShiTuV2RecognizerPostprocessor>(
m, "PPShiTuV2RecognizerPostprocessor")
.def(pybind11::init<>())
.def("run",
[](vision::classification::PPShiTuV2RecognizerPostprocessor& self,
std::vector<FDTensor>& inputs) {
std::vector<vision::ClassifyResult> results;
if (!self.Run(inputs, &results)) {
throw std::runtime_error(
"Failed to postprocess the runtime result in "
"PPShiTuV2RecognizerPostprocessor.");
}
return results;
})
.def("run",
[](vision::classification::PPShiTuV2RecognizerPostprocessor& self,
std::vector<pybind11::array>& input_array) {
std::vector<vision::ClassifyResult> 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 "
"PPShiTuV2RecognizerPostprocessor.");
}
return results;
})
.def_property("feature_norm",
&vision::classification::PPShiTuV2RecognizerPostprocessor::
GetFeatureNorm,
&vision::classification::PPShiTuV2RecognizerPostprocessor::
SetFeatureNorm);
pybind11::class_<vision::classification::PPShiTuV2Recognizer,
FastDeployModel>(m, "PPShiTuV2Recognizer")
.def(pybind11::init<std::string, std::string, std::string, RuntimeOption,
ModelFormat>())
.def("clone",
[](vision::classification::PPShiTuV2Recognizer& self) {
return self.Clone();
})
.def("predict",
[](vision::classification::PPShiTuV2Recognizer& self,
pybind11::array& data) {
cv::Mat im = PyArrayToCvMat(data);
vision::ClassifyResult result;
self.Predict(im, &result);
return result;
})
.def("batch_predict",
[](vision::classification::PPShiTuV2Recognizer& 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::ClassifyResult> results;
self.BatchPredict(images, &results);
return results;
})
.def_property_readonly(
"preprocessor",
&vision::classification::PPShiTuV2Recognizer::GetPreprocessor)
.def_property_readonly(
"postprocessor",
&vision::classification::PPShiTuV2Recognizer::GetPostprocessor);
}
} // namespace fastdeploy

View File

@@ -0,0 +1,26 @@
// Copyright (c) 2023 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/detection/ppdet/model.h"
namespace fastdeploy {
namespace vision {
namespace classification {
typedef detection::PicoDet PPShiTuV2Detector;
} // namespace classification
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,121 @@
// 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/classification/ppshitu/ppshituv2_rec.h"
#include "fastdeploy/utils/unique_ptr.h"
namespace fastdeploy {
namespace vision {
namespace classification {
PPShiTuV2Recognizer::PPShiTuV2Recognizer(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) {
if (model_format == ModelFormat::PADDLE) {
valid_cpu_backends = {Backend::OPENVINO, Backend::PDINFER, Backend::ORT,
Backend::LITE};
valid_gpu_backends = {Backend::ORT, Backend::PDINFER, Backend::TRT};
valid_timvx_backends = {Backend::LITE};
valid_ascend_backends = {Backend::LITE};
valid_kunlunxin_backends = {Backend::LITE};
valid_ipu_backends = {Backend::PDINFER};
valid_directml_backends = {Backend::ORT};
} else if (model_format == ModelFormat::SOPHGO) {
valid_sophgonpu_backends = {Backend::SOPHGOTPU};
} else {
valid_cpu_backends = {Backend::ORT, Backend::OPENVINO};
valid_gpu_backends = {Backend::ORT, Backend::TRT};
valid_rknpu_backends = {Backend::RKNPU2};
valid_directml_backends = {Backend::ORT};
}
runtime_option = custom_option;
runtime_option.model_format = model_format;
runtime_option.model_file = model_file;
runtime_option.params_file = params_file;
initialized = Initialize();
}
std::unique_ptr<PPShiTuV2Recognizer> PPShiTuV2Recognizer::Clone() const {
std::unique_ptr<PPShiTuV2Recognizer> clone_model =
utils::make_unique<PPShiTuV2Recognizer>(PPShiTuV2Recognizer(*this));
clone_model->SetRuntime(clone_model->CloneRuntime());
return clone_model;
}
bool PPShiTuV2Recognizer::Initialize() {
if (!InitRuntime()) {
FDERROR << "Failed to initialize fastdeploy backend." << std::endl;
return false;
}
return true;
}
bool PPShiTuV2Recognizer::Predict(cv::Mat* im, ClassifyResult* result) {
if (!Predict(*im, result)) {
return false;
}
return true;
}
bool PPShiTuV2Recognizer::Predict(const cv::Mat& im, ClassifyResult* result) {
FDMat mat = WrapMat(im);
return Predict(mat, result);
}
bool PPShiTuV2Recognizer::BatchPredict(const std::vector<cv::Mat>& images,
std::vector<ClassifyResult>* results) {
std::vector<FDMat> mats = WrapMat(images);
return BatchPredict(mats, results);
}
bool PPShiTuV2Recognizer::Predict(const FDMat& mat, ClassifyResult* result) {
std::vector<ClassifyResult> results;
std::vector<FDMat> mats = {mat};
if (!BatchPredict(mats, &results)) {
return false;
}
*result = std::move(results[0]);
return true;
}
bool PPShiTuV2Recognizer::BatchPredict(const std::vector<FDMat>& mats,
std::vector<ClassifyResult>* results) {
std::vector<FDMat> fd_mats = mats;
if (!preprocessor_.Run(&fd_mats, &reused_input_tensors_)) {
FDERROR << "Failed to preprocess the input image." << std::endl;
return false;
}
reused_input_tensors_[0].name = InputInfoOfRuntime(0).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 classification
} // namespace vision
} // namespace fastdeploy

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.
#pragma once
#include "fastdeploy/fastdeploy_model.h"
#include "fastdeploy/vision/classification/ppshitu/ppshituv2_rec_preprocessor.h"
#include "fastdeploy/vision/classification/ppshitu/ppshituv2_rec_postprocessor.h"
namespace fastdeploy {
namespace vision {
namespace classification {
/*! @brief PPShiTuV2Recognizer model object used when to load a PPShiTuV2Recognizer model exported by PP-ShiTuV2 Rec model.
*/
class FASTDEPLOY_DECL PPShiTuV2Recognizer : public FastDeployModel {
public:
/** \brief Set path of model file and configuration file, and the configuration of runtime
*
* \param[in] model_file Path of model file, e.g PPLCNet/inference.pdmodel
* \param[in] params_file Path of parameter file, e.g PPLCNet/inference.pdiparams, if the model format is ONNX, this parameter will be ignored
* \param[in] config_file Path of configuration file for deployment, e.g PPLCNet/inference_cls.yml
* \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
*/
PPShiTuV2Recognizer(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);
/** \brief Clone a new PPShiTuV2Recognizer with less memory usage when multiple instances of the same model are created
*
* \return new PPShiTuV2Recognizer* type unique pointer
*/
virtual std::unique_ptr<PPShiTuV2Recognizer> Clone() const;
/// Get model's name
virtual std::string ModelName() const { return "PPShiTuV2Recognizer"; }
/** \brief DEPRECATED Predict the feature vector result for an input image, remove at 1.0 version
*
* \param[in] im The input image data, comes from cv::imread()
* \param[in] result The output feature vector result will be writen to this structure
* \return true if the prediction successed, otherwise false
*/
virtual bool Predict(cv::Mat* im, ClassifyResult* result);
/** \brief Predict the classification result for an input image
*
* \param[in] img The input image data, comes from cv::imread()
* \param[in] result The output feature vector result
* \return true if the prediction successed, otherwise false
*/
virtual bool Predict(const cv::Mat& img, ClassifyResult* result);
/** \brief Predict the feature vector 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 feature vector(namely ClassifyResult.feature) result list
* \return true if the prediction successed, otherwise false
*/
virtual bool BatchPredict(const std::vector<cv::Mat>& imgs,
std::vector<ClassifyResult>* results);
/** \brief Predict the feature vector result for an input image
*
* \param[in] mat The input mat
* \param[in] result The output feature vector result
* \return true if the prediction successed, otherwise false
*/
virtual bool Predict(const FDMat& mat, ClassifyResult* result);
/** \brief Predict the feature vector results for a batch of input images
*
* \param[in] mats, The input mat list
* \param[in] results The output feature vector result list
* \return true if the prediction successed, otherwise false
*/
virtual bool BatchPredict(const std::vector<FDMat>& mats,
std::vector<ClassifyResult>* results);
/// Get preprocessor reference of PPShiTuV2Recognizer
virtual PPShiTuV2RecognizerPreprocessor& GetPreprocessor() {
return preprocessor_;
}
/// Get postprocessor reference of PPShiTuV2Recognizer
virtual PPShiTuV2RecognizerPostprocessor& GetPostprocessor() {
return postprocessor_;
}
protected:
bool Initialize();
PPShiTuV2RecognizerPreprocessor preprocessor_;
PPShiTuV2RecognizerPostprocessor postprocessor_;
};
} // namespace classification
} // namespace vision
} // namespace fastdeploy

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/classification/ppshitu/ppshituv2_rec_postprocessor.h"
#include <cmath>
#include <numeric>
#include "fastdeploy/vision/utils/utils.h"
namespace fastdeploy {
namespace vision {
namespace classification {
bool PPShiTuV2RecognizerPostprocessor::Run(
const std::vector<FDTensor>& tensors,
std::vector<ClassifyResult>* results) {
int batch = tensors[0].shape[0]; // e.g [batch, 512]
int num_feature = tensors[0].shape[1];
const float* tensor_data = reinterpret_cast<const float*>(tensors[0].Data());
results->resize(batch);
// post processing per batch=1
for (int i = 0; i < batch; ++i) {
(*results)[i].feature.resize(num_feature);
const float* tensor_data_i_start = tensor_data + i * num_feature;
std::memcpy((*results)[i].feature.data(), tensor_data_i_start,
num_feature * sizeof(float));
if (feature_norm_) {
FeatureNorm((*results)[i].feature);
}
}
return true;
}
void PPShiTuV2RecognizerPostprocessor::FeatureNorm(
std::vector<float>& feature) {
float feature_sqrt = std::sqrt(std::inner_product(
feature.begin(), feature.end(), feature.begin(), 0.0f));
for (int i = 0; i < feature.size(); ++i) {
feature[i] /= feature_sqrt;
}
}
} // namespace classification
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,49 @@
// Copyright (c) 2023 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 classification {
/*! @brief Postprocessor object for PP-ShiTuV2 Recognizer model.
*/
class FASTDEPLOY_DECL PPShiTuV2RecognizerPostprocessor {
public:
PPShiTuV2RecognizerPostprocessor() = default;
/** \brief Process the result of runtime and fill to ClassifyResult structure
*
* \param[in] tensors The inference result from runtime
* \param[in] result The output result of feature vector (see ClassifyResult.feature member)
* \return true if the postprocess successed, otherwise false
*/
bool Run(const std::vector<FDTensor>& tensors,
std::vector<ClassifyResult>* results);
/// Set the value of feature_norm_ for Postprocessor
void SetFeatureNorm(bool feature_norm) { feature_norm_ = feature_norm; }
/// Get the value of feature_norm_ from Postprocessor, default to true.
bool GetFeatureNorm() { return feature_norm_; }
private:
void FeatureNorm(std::vector<float> &feature);
bool feature_norm_ = true;
};
} // namespace classification
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,152 @@
// Copyright (c) 2023 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/classification/ppshitu/ppshituv2_rec_preprocessor.h"
#include "yaml-cpp/yaml.h"
namespace fastdeploy {
namespace vision {
namespace classification {
PPShiTuV2RecognizerPreprocessor::PPShiTuV2RecognizerPreprocessor(
const std::string& config_file) {
this->config_file_ = config_file;
FDASSERT(BuildPreprocessPipelineFromConfig(),
"Failed to create PPShiTuV2RecognizerPreprocessor.");
initialized_ = true;
}
bool PPShiTuV2RecognizerPreprocessor::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;
}
auto preprocess_cfg = cfg["PreProcess"]["transform_ops"];
processors_.push_back(std::make_shared<BGR2RGB>());
for (const auto& op : preprocess_cfg) {
FDASSERT(op.IsMap(),
"Require the transform information in yaml be Map type.");
auto op_name = op.begin()->first.as<std::string>();
if (op_name == "ResizeImage") {
if (op.begin()->second["resize_short"]) {
int target_size = op.begin()->second["resize_short"].as<int>();
bool use_scale = false;
int interp = 1;
processors_.push_back(
std::make_shared<ResizeByShort>(target_size, 1, use_scale));
} else if (op.begin()->second["size"]) {
int width = 0;
int height = 0;
if (op.begin()->second["size"].IsScalar()) {
auto size = op.begin()->second["size"].as<int>();
width = size;
height = size;
} else {
auto size = op.begin()->second["size"].as<std::vector<int>>();
width = size[0];
height = size[1];
}
processors_.push_back(
std::make_shared<Resize>(width, height, -1.0, -1.0, 1, false));
} else {
FDERROR << "Invalid params for ResizeImage for both 'size' and "
"'resize_short' are None"
<< std::endl;
}
} else if (op_name == "CropImage") {
int width = op.begin()->second["size"].as<int>();
int height = op.begin()->second["size"].as<int>();
processors_.push_back(std::make_shared<CenterCrop>(width, height));
} else if (op_name == "NormalizeImage") {
if (!disable_normalize_) {
auto mean = op.begin()->second["mean"].as<std::vector<float>>();
auto std = op.begin()->second["std"].as<std::vector<float>>();
auto scale = op.begin()->second["scale"].as<float>();
FDASSERT(
(scale - 0.00392157) < 1e-06 && (scale - 0.00392157) > -1e-06,
"Only support scale in Normalize be 0.00392157, means the pixel "
"is in range of [0, 255].");
processors_.push_back(std::make_shared<Normalize>(mean, std));
}
} else if (op_name == "ToCHWImage") {
if (!disable_permute_) {
processors_.push_back(std::make_shared<HWC2CHW>());
}
} else {
FDERROR << "Unexcepted preprocess operator: " << op_name << "."
<< std::endl;
return false;
}
}
// Fusion will improve performance
FuseTransforms(&processors_);
return true;
}
void PPShiTuV2RecognizerPreprocessor::DisableNormalize() {
this->disable_normalize_ = true;
// the DisableNormalize function will be invalid if the configuration file is
// loaded during preprocessing
if (!BuildPreprocessPipelineFromConfig()) {
FDERROR << "Failed to build preprocess pipeline from configuration file."
<< std::endl;
}
}
void PPShiTuV2RecognizerPreprocessor::DisablePermute() {
this->disable_permute_ = true;
// the DisablePermute function will be invalid if the configuration file is
// loaded during preprocessing
if (!BuildPreprocessPipelineFromConfig()) {
FDERROR << "Failed to build preprocess pipeline from configuration file."
<< std::endl;
}
}
bool PPShiTuV2RecognizerPreprocessor::Apply(FDMatBatch* image_batch,
std::vector<FDTensor>* outputs) {
if (!initialized_) {
FDERROR << "The preprocessor is not initialized." << std::endl;
return false;
}
for (size_t j = 0; j < processors_.size(); ++j) {
image_batch->proc_lib = proc_lib_;
if (initial_resize_on_cpu_ && j == 0 &&
processors_[j]->Name().find("Resize") == 0) {
image_batch->proc_lib = ProcLib::OPENCV;
}
if (!(*(processors_[j].get()))(image_batch)) {
FDERROR << "Failed to processs image in " << processors_[j]->Name() << "."
<< std::endl;
return false;
}
}
outputs->resize(1);
FDTensor* tensor = image_batch->Tensor();
(*outputs)[0].SetExternalData(tensor->Shape(), tensor->Dtype(),
tensor->Data(), tensor->device,
tensor->device_id);
return true;
}
} // namespace classification
} // namespace vision
} // namespace fastdeploy

View File

@@ -0,0 +1,72 @@
// Copyright (c) 2023 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 classification {
/*! @brief Preprocessor object for PP-ShiTuV2 Recognizer model.
*/
class FASTDEPLOY_DECL PPShiTuV2RecognizerPreprocessor : public ProcessorManager {
public:
/** \brief Create a preprocessor instance for PP-ShiTuV2 Recognizer model
*
* \param[in] config_file Path of configuration file for deployment, e.g PPLCNet/infer_cfg.yml
*/
explicit PPShiTuV2RecognizerPreprocessor(const std::string& config_file);
/** \brief Implement the virtual function of ProcessorManager, Apply() is the
* body of Run(). Apply() contains the main logic of preprocessing, Run() is
* called by users to execute preprocessing
*
* \param[in] image_batch The input image batch
* \param[in] outputs The output tensors which will feed in runtime
* \return true if the preprocess successed, otherwise false
*/
virtual bool Apply(FDMatBatch* image_batch,
std::vector<FDTensor>* outputs);
/// This function will disable normalize in preprocessing step.
void DisableNormalize();
/// This function will disable hwc2chw in preprocessing step.
void DisablePermute();
/** \brief When the initial operator is Resize, and input image size is large,
* maybe it's better to run resize on CPU, because the HostToDevice memcpy
* is time consuming. Set this true to run the initial resize on CPU.
*
* \param[in] v ture or false
*/
void InitialResizeOnCpu(bool v) { initial_resize_on_cpu_ = v; }
private:
bool BuildPreprocessPipelineFromConfig();
bool initialized_ = false;
std::vector<std::shared_ptr<Processor>> processors_;
// for recording the switch of hwc2chw
bool disable_permute_ = false;
// for recording the switch of normalize
bool disable_normalize_ = false;
// read config file
std::string config_file_;
bool initial_resize_on_cpu_ = false;
};
} // namespace classification
} // namespace vision
} // namespace fastdeploy

View File

@@ -19,16 +19,21 @@ namespace vision {
void ClassifyResult::Free() {
std::vector<int32_t>().swap(label_ids);
std::vector<float>().swap(scores);
std::vector<float>().swap(feature);
}
void ClassifyResult::Clear() {
label_ids.clear();
scores.clear();
feature.clear();
}
void ClassifyResult::Resize(int size) {
label_ids.resize(size);
scores.resize(size);
// TODO(qiuyanjun): feature not perform resize now.
// may need the code below for future.
// feature.resize(size);
}
std::string ClassifyResult::Str() {
@@ -38,9 +43,25 @@ std::string ClassifyResult::Str() {
out = out + std::to_string(label_ids[i]) + ", ";
}
out += "\nscores: ";
for (size_t i = 0; i < label_ids.size(); ++i) {
for (size_t i = 0; i < scores.size(); ++i) {
out = out + std::to_string(scores[i]) + ", ";
}
if (!feature.empty()) {
out += "\nfeature: size (";
out += std::to_string(feature.size()) + "), only show first 100 values.\n";
for (size_t i = 0; i < feature.size(); ++i) {
// only show first 100 values.
if ((i + 1) <= 100) {
out = out + std::to_string(feature[i]) + ", ";
if ((i + 1) % 10 == 0 && (i + 1) < 100) {
out += "\n";
}
if ((i + 1) == 100) {
out += "\n......";
}
}
}
}
out += "\n)";
return out;
}
@@ -49,6 +70,7 @@ ClassifyResult& ClassifyResult::operator=(ClassifyResult&& other) {
if (&other != this) {
label_ids = std::move(other.label_ids);
scores = std::move(other.scores);
feature = std::move(other.feature);
}
return *this;
}
@@ -154,14 +176,18 @@ std::string DetectionResult::Str() {
if (!contain_masks) {
out = "DetectionResult: [xmin, ymin, xmax, ymax, score, label_id]\n";
if (!rotated_boxes.empty()) {
out = "DetectionResult: [x1, y1, x2, y2, x3, y3, x4, y4, score, label_id]\n";
out =
"DetectionResult: [x1, y1, x2, y2, x3, y3, x4, y4, score, "
"label_id]\n";
}
} else {
out =
"DetectionResult: [xmin, ymin, xmax, ymax, score, label_id, "
"mask_shape]\n";
if (!rotated_boxes.empty()) {
out = "DetectionResult: [x1, y1, x2, y2, x3, y3, x4, y4, score, label_id, mask_shape]\n";
out =
"DetectionResult: [x1, y1, x2, y2, x3, y3, x4, y4, score, label_id, "
"mask_shape]\n";
}
}
for (size_t i = 0; i < boxes.size(); ++i) {
@@ -646,8 +672,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]) +
@@ -687,8 +713,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";
@@ -707,8 +733,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;
@@ -755,9 +781,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

@@ -49,6 +49,8 @@ struct FASTDEPLOY_DECL ClassifyResult : public BaseResult {
std::vector<int32_t> label_ids;
/// The confidence for each classify result
std::vector<float> scores;
/// The feature vector of recognizer, e.g, PP-ShiTuV2 Recognizer
std::vector<float> feature;
ResultType type = ResultType::CLASSIFY;
/// Resize ClassifyResult data buffer

18
fastdeploy/vision/detection/ppdet/base.cc Executable file → Normal file
View File

@@ -18,7 +18,6 @@ PPDetBase::PPDetBase(const std::string& model_file,
runtime_option.model_format = model_format;
runtime_option.model_file = model_file;
runtime_option.params_file = params_file;
}
std::unique_ptr<PPDetBase> PPDetBase::Clone() const {
@@ -83,8 +82,14 @@ bool PPDetBase::BatchPredict(const std::vector<cv::Mat>& imgs,
return true;
}
bool PPDetBase::CheckArch(){
std::vector<std::string> archs = {"SOLOv2","YOLO","SSD","RetinaNet","RCNN","Face","GFL","YOLOX","YOLOv5","YOLOv6","YOLOv7","RTMDet","FCOS","TTFNet","TOOD","DETR"};
bool PPDetBase::CheckArch() {
// Add "PicoDet" arch for backward compability with the
// old ppdet model, such as picodet from PaddleClas
// PP-ShiTuV2 pipeline.
std::vector<std::string> archs = {
"SOLOv2", "YOLO", "SSD", "RetinaNet", "RCNN", "Face",
"GFL", "YOLOX", "YOLOv5", "YOLOv6", "YOLOv7", "RTMDet",
"FCOS", "TTFNet", "TOOD", "DETR", "PicoDet"};
auto arch_ = preprocessor_.GetArch();
for (auto item : archs) {
if (arch_ == item) {
@@ -92,11 +97,10 @@ bool PPDetBase::CheckArch(){
}
}
FDWARNING << "Please set model arch,"
<< "support value : SOLOv2, YOLO, SSD, RetinaNet, RCNN, Face , GFL , RTMDet ,"\
<<"FCOS , TTFNet , TOOD , DETR." << std::endl;
<< "support value : SOLOv2, YOLO, SSD, RetinaNet, "
<< "RCNN, Face , GFL , RTMDet ,"
<< "FCOS , TTFNet , TOOD , DETR, PicoDet" << std::endl;
return false;
}
} // namespace detection

View File

@@ -443,7 +443,8 @@ class FASTDEPLOY_DECL GFL : public PPDetBase {
class FASTDEPLOY_DECL PaddleDetectionModel : public PPDetBase {
public:
PaddleDetectionModel(const std::string& model_file, const std::string& params_file,
PaddleDetectionModel(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)
@@ -472,8 +473,13 @@ class FASTDEPLOY_DECL PPYOLOER : public PPDetBase {
const ModelFormat& model_format = ModelFormat::PADDLE)
: PPDetBase(model_file, params_file, config_file, custom_option,
model_format) {
valid_cpu_backends = { Backend::PDINFER};
valid_gpu_backends = {Backend::PDINFER};
valid_cpu_backends = {Backend::PDINFER, Backend::OPENVINO, Backend::ORT,
Backend::LITE};
valid_gpu_backends = {Backend::PDINFER, Backend::ORT, Backend::TRT};
valid_timvx_backends = {Backend::LITE};
valid_kunlunxin_backends = {Backend::LITE};
valid_rknpu_backends = {Backend::RKNPU2};
valid_ascend_backends = {Backend::LITE};
valid_sophgonpu_backends = {Backend::SOPHGOTPU};
initialized = Initialize();
}

10
fastdeploy/vision/vision_pybind.cc Executable file → Normal file
View File

@@ -62,18 +62,26 @@ void BindVision(pybind11::module& m) {
.def(pybind11::init())
.def_readwrite("label_ids", &vision::ClassifyResult::label_ids)
.def_readwrite("scores", &vision::ClassifyResult::scores)
.def_readwrite("feature", &vision::ClassifyResult::feature)
.def(pybind11::pickle(
[](const vision::ClassifyResult& c) {
if (c.feature.empty()) {
return pybind11::make_tuple(c.label_ids, c.scores);
}
return pybind11::make_tuple(c.label_ids, c.scores, c.feature);
},
[](pybind11::tuple t) {
if (t.size() != 2)
if ((t.size() != 2) && (t.size() != 3)) {
throw std::runtime_error(
"vision::ClassifyResult pickle with invalid state!");
}
vision::ClassifyResult c;
c.label_ids = t[0].cast<std::vector<int32_t>>();
c.scores = t[1].cast<std::vector<float>>();
if (t.size() == 3) {
c.feature = t[2].cast<std::vector<float>>();
}
return c;
}))

View File

@@ -15,6 +15,10 @@ from __future__ import absolute_import
from .contrib.yolov5cls import YOLOv5Cls
from .ppcls import *
from .ppshitu import PPShiTuV2Detector
from .ppshitu import PPShiTuV2Recognizer
from .ppshitu import PPShiTuV2RecognizerPreprocessor
from .ppshitu import PPShiTuV2RecognizerPostprocessor
from .contrib.resnet import ResNet
PPLCNet = PaddleClasModel

View File

@@ -0,0 +1,131 @@
from __future__ import absolute_import
import logging
from .... import FastDeployModel, ModelFormat
from .... import c_lib_wrap as C
from ...common import ProcessorManager
from ...detection.ppdet import PicoDet
class PPShiTuV2Detector(PicoDet):
"""Detect main body from an input image.
"""
...
class PPShiTuV2RecognizerPreprocessor(ProcessorManager):
def __init__(self, config_file):
"""Create a preprocessor for PPShiTuV2Recognizer from configuration file
:param config_file: (str)Path of configuration file, e.g PPLCNet/inference_cls.yaml
"""
super(PPShiTuV2RecognizerPreprocessor, self).__init__()
self._manager = C.vision.classification.PPShiTuV2RecognizerPreprocessor(
config_file)
def disable_normalize(self):
"""
This function will disable normalize in preprocessing step.
"""
self._manager.disable_normalize()
def disable_permute(self):
"""
This function will disable hwc2chw in preprocessing step.
"""
self._manager.disable_permute()
def initial_resize_on_cpu(self, v):
"""
When the initial operator is Resize, and input image size is large,
maybe it's better to run resize on CPU, because the HostToDevice memcpy
is time consuming. Set this True to run the initial resize on CPU.
:param: v: True or False
"""
self._manager.initial_resize_on_cpu(v)
class PPShiTuV2RecognizerPostprocessor:
def __init__(self, topk=1):
"""Create a postprocessor for PPShiTuV2Recognizer
"""
self._postprocessor = C.vision.classification.PPShiTuV2RecognizerPostprocessor(
)
def run(self, runtime_results):
"""Postprocess the runtime results for PPShiTuV2Recognizer
:param: runtime_results: (list of FDTensor)The output FDTensor results from runtime
:return: list of ClassifyResult, the feature vector is ClassifyResult.feature (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 PPShiTuV2Recognizer(FastDeployModel):
def __init__(self,
model_file,
params_file,
config_file,
runtime_option=None,
model_format=ModelFormat.PADDLE):
"""Load a image PPShiTuV2Recognizer model exported by PaddleClas.
:param model_file: (str)Path of model file, e.g PPLCNet/inference.pdmodel
:param params_file: (str)Path of parameters file, e.g PPLCNet/inference.pdiparams, if the model_fomat is ModelFormat.ONNX, this param will be ignored, can be set as empty string
:param config_file: (str) Path of configuration file for deploy, e.g PPLCNet/inference_cls.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(PPShiTuV2Recognizer, self).__init__(runtime_option)
self._model = C.vision.classification.PPShiTuV2Recognizer(
model_file, params_file, config_file, self._runtime_option,
model_format)
assert self.initialized, "PPShiTuV2Recognizer model initialize failed."
def clone(self):
"""Clone PPShiTuV2Recognizer object
:return: a new PPShiTuV2Recognizer object
"""
class PPShiTuV2RecognizerCloneModel(PPShiTuV2Recognizer):
def __init__(self, model):
self._model = model
clone_model = PPShiTuV2RecognizerCloneModel(self._model.clone())
return clone_model
def predict(self, im):
"""Extract feature from an input image
:param im: (numpy.ndarray) The input image data, a 3-D array with layout HWC, BGR format
:return: ClassifyResult
"""
return self._model.predict(im)
def batch_predict(self, images):
"""Extract features from 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 ClassifyResult, the feature vector is ClassifyResult.feature
"""
return self._model.batch_predict(images)
@property
def preprocessor(self):
"""Get PPShiTuV2RecognizerPreprocessor object of the loaded model
:return PPShiTuV2RecognizerPreprocessor
"""
return self._model.preprocessor
@property
def postprocessor(self):
"""Get PPShiTuV2RecognizerPostprocessor object of the loaded model
:return PPShiTuV2RecognizerPostprocessor
"""
return self._model.postprocessor