diff --git a/.github/ISSUE_TEMPLATE/报告issue.md b/.github/ISSUE_TEMPLATE/报告issue.md index 898eee84b..34085055f 100644 --- a/.github/ISSUE_TEMPLATE/报告issue.md +++ b/.github/ISSUE_TEMPLATE/报告issue.md @@ -19,3 +19,7 @@ assignees: '' - 性能问题,描述清楚对比的方式 - - 注意性能测试,循环跑N次,取后80%的用时平均(模型启动时,刚开始受限于资源分配,速度会较慢) - - FastDeploy的Predict包含模型本身之外的数据前后处理用时 +- 模型部署出错 +- - 先执行`examples`下的部署示例,包括使用examples提供的模型,确认是否可以正确执行 +- - 如若`examples`下的代码可以运行,但自己的模型,或自己的代码不能运行 +- - - 提供自己的代码使用方式或自己的模型,供工程师快速定位问题 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index eb728c2f4..1b4727fd3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,7 +4,7 @@ ### PR types(PR类型) -### Describe +### Description diff --git a/CMakeLists.txt b/CMakeLists.txt index efc35b51c..667951e71 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake) if(NOT MSVC) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "-Wno-format") + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) endif(NOT MSVC) if(UNIX AND (NOT APPLE) AND (NOT ANDROID) AND (NOT ENABLE_TIMVX)) @@ -425,13 +426,6 @@ if(ENABLE_VISION) endif() endif() -if(ANDROID OR IOS) - if(ENABLE_TEXT) - set(ENABLE_TEXT OFF CACHE BOOL "Force ENABLE_TEXT OFF" FORCE) - message(STATUS "Found Android or IOS, force ENABLE_TEXT OFF. We do not support fast_tokenizer with Android/IOS now.") - endif() -endif() - if(ENABLE_TEXT) add_definitions(-DENABLE_TEXT) list(APPEND ALL_DEPLOY_SRCS ${DEPLOY_TEXT_SRCS}) @@ -488,6 +482,8 @@ set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION ${FASTDEPLOY_VERSION}) if(MSVC) # disable warnings for dll export target_compile_options(${LIBRARY_NAME} PRIVATE "$<$>:/wd4251>$<$>:-Xcompiler=/wd4251>") + file(GLOB FD_FILES_REQUIRE_BIGOBJ ${CSRCS_DIR_NAME}/fastdeploy/function/reduce.cc) + set_source_files_properties(${FD_FILES_REQUIRE_BIGOBJ} PROPERTIES COMPILE_FLAGS "/bigobj") endif() # extra depend libs for android @@ -506,8 +502,12 @@ target_link_libraries(${LIBRARY_NAME} ${DEPEND_LIBS}) if(WIN32) if(ENABLE_VISION) - add_custom_target(copy_yaml_library ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/third_party/yaml-cpp/Release ${CMAKE_CURRENT_BINARY_DIR}/third_libs/install/yaml-cpp/lib DEPENDS ${LIBRARY_NAME}) - add_custom_target(copy_yaml_include ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/third_party/yaml-cpp/include ${CMAKE_CURRENT_BINARY_DIR}/third_libs/install/yaml-cpp/include DEPENDS ${LIBRARY_NAME}) + if("${CMAKE_GENERATOR}" STREQUAL "Ninja") + add_custom_target(copy_yaml_library ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/third_party/yaml-cpp ${CMAKE_CURRENT_BINARY_DIR}/third_libs/install/yaml-cpp/lib DEPENDS ${LIBRARY_NAME}) + else() + add_custom_target(copy_yaml_library ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/third_party/yaml-cpp/Release ${CMAKE_CURRENT_BINARY_DIR}/third_libs/install/yaml-cpp/lib DEPENDS ${LIBRARY_NAME}) + add_custom_target(copy_yaml_include ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/third_party/yaml-cpp/include ${CMAKE_CURRENT_BINARY_DIR}/third_libs/install/yaml-cpp/include DEPENDS ${LIBRARY_NAME}) + endif() endif() endif() diff --git a/FastDeploy.cmake.in b/FastDeploy.cmake.in index 5e2eacf3a..fd0ea847a 100755 --- a/FastDeploy.cmake.in +++ b/FastDeploy.cmake.in @@ -35,9 +35,12 @@ list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/include) # Note(zhoushunjie): include some useful utils function include(${CMAKE_CURRENT_LIST_DIR}/utils.cmake) -if(NOT CMAKE_CXX_STANDARD) +# Set C++11 as standard for the whole project +if(NOT MSVC) set(CMAKE_CXX_STANDARD 11) -endif() + set(CMAKE_CXX_FLAGS "-Wno-format") + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) +endif(NOT MSVC) if(ANDROID) add_library(fastdeploy STATIC IMPORTED GLOBAL) @@ -210,11 +213,18 @@ endif() if (ENABLE_TEXT) if(ANDROID) - message(FATAL_ERROR "Not support fastdeploy text APIs with Android now!") + if(NOT ANDROID_TOOLCHAIN MATCHES "clang") + message(FATAL_ERROR "Currently, only support clang toolchain while cross compiling FastDeploy for Android with FastTokenizer, but found ${ANDROID_TOOLCHAIN}.") + endif() + add_library(core_tokenizers STATIC IMPORTED GLOBAL) + set_property(TARGET core_tokenizers PROPERTY IMPORTED_LOCATION + ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/lib/${ANDROID_ABI}/libcore_tokenizers.so) + list(APPEND FASTDEPLOY_LIBS core_tokenizers) + else() + # Add dependency libs later: Linux/Mac/Win/... + find_library(FAST_TOKENIZER_LIB core_tokenizers ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/lib NO_DEFAULT_PATH) + list(APPEND FASTDEPLOY_LIBS ${FAST_TOKENIZER_LIB}) endif() - # Add dependency libs later - find_library(FAST_TOKENIZER_LIB core_tokenizers ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/lib NO_DEFAULT_PATH) - list(APPEND FASTDEPLOY_LIBS ${FAST_TOKENIZER_LIB}) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/include) list(APPEND FASTDEPLOY_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/third_party/include) endif() diff --git a/README_CN.md b/README_CN.md old mode 100644 new mode 100755 index 2c06f61a8..8814215fe --- a/README_CN.md +++ b/README_CN.md @@ -35,87 +35,19 @@ | [**Pose Estimation**](examples/vision/keypointdetection) | [**Behavior Recognition**](https://github.com/PaddlePaddle/FastDeploy/issues/6) | [**NLP**](examples/text) | [**Speech**](examples/audio/pp-tts) | | | | |

**input** :早上好今天是2020
/10/29,最低温度是-3°C。

**output**: [](https://paddlespeech.bj.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/001.wav)

| -## 近期更新 -- 🔥 [**【三日部署直播课回放】**](https://aistudio.baidu.com/aistudio/course/introduce/27800) +## **社区交流** -- **社区交流** +* **Slack**:Join our [Slack community](https://join.slack.com/t/fastdeployworkspace/shared_invite/zt-1jznah134-3rxY~ytRb8rcPqkn9g~PDg) and chat with other community members about ideas - - **Slack**:Join our [Slack community](https://join.slack.com/t/fastdeployworkspace/shared_invite/zt-1hhvpb279-iw2pNPwrDaMBQ5OQhO3Siw) and chat with other community members about ideas +* **微信**:扫描二维码,填写问卷加入技术社区,与社区开发者探讨部署的痛点与方案 - - **微信**:扫描二维码,填写问卷加入技术社区,与社区开发者探讨部署的痛点与方案 - -
- -
- -- 🔥 **2022.11.23:Release FastDeploy [release v0.8.0](https://github.com/PaddlePaddle/FastDeploy/tree/release/0.8)** - - - **🖥️ 服务端部署:支持更多的模型,推理性能进一步提升** - - - 新增 PIPNet、FaceLandmark1000 [人脸对齐模型](./examples/vision/facealign)的部署支持; - - 新增[视频超分系列模型](./examples/vision/sr) PP-MSVSR、EDVR、BasicVSR 部署示例; - - 升级[YOLOv7部署代码](https://github.com/PaddlePaddle/FastDeploy/pull/611),支持 predict 及 batch_predict; - - 新增 [UIE服务化部署](./examples/text/uie) 案例; - - [测试功能] 新增OpenVINO后端Device设置,支持集显/独立显卡的调用; - - - **📲 移动端和端侧部署:支持更多模型** - - - 新增Android图像分类、目标检测、语义分割、OCR、人脸检测 APK工程及示例. - - | 图像分类 | 目标检测 | 语义分割 | 文字识别 | 人脸检测 | - |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------:| - | [工程代码](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification) | [工程代码](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection) | [工程代码](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation) | [工程代码](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr) | [工程代码](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet) | - | [扫码或点击链接
安装试用](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-MobileNetV1.apk)
| [扫码或点击链接
安装试用](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-PicoDet.apk)
| [扫码或点击链接
安装试用](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-Portrait-HumanSegV2-Lite.apk)
| [扫码或点击链接
安装试用](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-PP-OCRv2.apk)
| [扫码或点击链接
安装试用](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-SCRFD.apk)
| - | | | | | | - -- [**more releases information**](./releases) +
+ +
## 目录 -*
📖 文档教程(点击可收缩)
- - - 安装文档 - - - [预编译库下载安装](docs/cn/build_and_install/download_prebuilt_libraries.md) - - [GPU部署环境编译安装](docs/cn/build_and_install/gpu.md) - - [CPU部署环境编译安装](docs/cn/build_and_install/cpu.md) - - [IPU部署环境编译安装](docs/cn/build_and_install/ipu.md) - - [Jetson部署环境编译安装](docs/cn/build_and_install/jetson.md) - - [Android平台部署环境编译安装](docs/cn/build_and_install/android.md) - - - 快速使用 - - - [Python部署示例](docs/cn/quick_start/models/python.md) - - [C++部署示例](docs/cn/quick_start/models/cpp.md) - - [Runtime Python使用示例](docs/cn/quick_start/runtime/python.md) - - [Runtime C++使用示例](docs/cn/quick_start/runtime/cpp.md) - - - API文档(进行中) - - - [Python API文档](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/python/html/) - - [C++ API文档](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/cpp/html/) - - - 性能调优 - - - [量化加速](docs/cn/quantize.md) - - - 常见问题 - - - [1. 如何配置模型部署的推理后端](docs/cn/faq/how_to_change_backend.md) - - [2. Windows上C++ SDK如何使用](docs/cn/faq/use_sdk_on_windows.md) - - [3. Android上如何使用FastDeploy](java/android/README.md) - - [4. TensorRT使用中的一些技巧](docs/cn/faq/tensorrt_tricks.md) - - [5. 如何增加新的模型](docs/cn/faq/develop_a_new_model.md)(进行中) - - - 更多FastDeploy部署模块 - - - [服务化部署](./serving) - - - [Benchmark测试](./benchmark) - -
- * **🖥️ 服务器端部署** * [Python SDK快速开始](#fastdeploy-quick-start-python) @@ -124,24 +56,21 @@ * **📲 移动端和端侧部署** - * [Paddle Lite NPU部署](#fastdeploy-edge-sdk-npu) * [端侧模型支持列表](#fastdeploy-edge-models) * **🌐 Web和小程序部署** * [Web端模型支持列表](#fastdeploy-web-models) - -* [**社区交流**](#fastdeploy-community) - -* [**Acknowledge**](#fastdeploy-acknowledge) - -* [**License**](#fastdeploy-license) +* [Acknowledge](#fastdeploy-acknowledge) +* [License](#fastdeploy-license) ## 🖥️ 服务端部署
-
Python SDK快速开始(点开查看详情)
+
+ +Python SDK快速开始(点开查看详情)
#### 快速安装 @@ -180,11 +109,10 @@ wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/0000000 * 测试推理结果 - ```python - # GPU/TensorRT部署参考 examples/vision/detection/paddledetection/python - import cv2 - import fastdeploy.vision as vision - ``` +```python +# GPU/TensorRT部署参考 examples/vision/detection/paddledetection/python +import cv2 +import fastdeploy.vision as vision model = vision.detection.PPYOLOE("ppyoloe_crn_l_300e_coco/model.pdmodel", "ppyoloe_crn_l_300e_coco/model.pdiparams", @@ -197,11 +125,13 @@ vis_im = vision.vis_detection(im, result, score_threshold=0.5) cv2.imwrite("vis_image.jpg", vis_im) ``` +
-
+
+ C++ SDK快速开始(点开查看详情)
@@ -274,14 +204,14 @@ int main(int argc, char* argv[]) { | Classification | [PaddleClas/SqueeezeNetV1.1](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Classification | [PaddleClas/Inceptionv3](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | | Classification | [PaddleClas/PP-HGNet](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| Detection | [PaddleDetection/PP-YOLOE](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PicoDet](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/YOLOX](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/YOLOv3](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PP-YOLO](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PP-YOLOv2](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/Faster-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/Mask-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLOE](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PicoDet](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/YOLOX](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/YOLOv3](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLO](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLOv2](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/Faster-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/Mask-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | | Detection | [Megvii-BaseDetection/YOLOX](./examples/vision/detection/yolox) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Detection | [WongKinYiu/YOLOv7](./examples/vision/detection/yolov7) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Detection | [WongKinYiu/YOLOv7end2end_trt](./examples/vision/detection/yolov7end2end_trt) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | @@ -318,14 +248,14 @@ int main(int argc, char* argv[]) { | Matting | [ZHKKKe/MODNet](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Matting | [PeterL1n/RobustVideoMatting]() | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Matting | [PaddleSeg/PP-Matting](./examples/vision/matting/ppmatting) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -| Matting | [PaddleSeg/PP-HumanMatting](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | +| Matting | [PaddleSeg/PP-HumanMatting](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Matting | [PaddleSeg/ModNet](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/BasicVSR](./) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/EDVR](./examples/vision/sr/edvr) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/PP-MSVSR](./examples/vision/sr/ppmsvsr) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Information Extraction | [PaddleNLP/UIE](./examples/text/uie) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | | | NLP | [PaddleNLP/ERNIE-3.0](./examples/text/ernie-3.0) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | ❔ | ✅ | -| Speech | [PaddleSpeech/PP-TTS](./examples/text/uie) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -- | ✅ | +| Speech | [PaddleSpeech/PP-TTS](./examples/audio/pp-tts) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -- | ✅ |
@@ -344,7 +274,7 @@ int main(int argc, char* argv[]) {
-| 任务场景 | 模型 | 大小(MB) | Linux | Android | iOS | Linux | Linux | Linux | Linux | 更新中... | +| 任务场景 | 模型 | 大小(MB) | Linux | Android | Linux | Linux | Linux | Linux | Linux | 更新中... | |:------------------:|:-----------------------------------------------------------------------------------------:|:--------:|:-------:|:-------:|:-------:|:-----------------------:|:------------------------------:|:---------------------------:|:--------------------------------:|:-------:| | --- | --- | --- | ARM CPU | ARM CPU | 瑞芯微NPU
RK3568/RK3588 | 瑞芯微NPU
RV1109/RV1126/RK1808 | 晶晨NPU
A311D/S905D/C308X | 恩智浦NPU
i.MX 8M Plus | 更新中...| | | Classification | [PaddleClas/ResNet50](examples/vision/classification/paddleclas) | 98 | ✅ | ✅ | ❔ | ✅ | | | | @@ -392,15 +322,6 @@ int main(int argc, char* argv[]) {
-
- -## 社区交流 - -- **加入社区👬:** 微信扫描二维码,进入**FastDeploy技术交流群** - -
- -
diff --git a/README_EN.md b/README_EN.md old mode 100644 new mode 100755 index 99d69d1a0..1157caa7d --- a/README_EN.md +++ b/README_EN.md @@ -36,87 +36,19 @@ Including image classification, object detection, image segmentation, face detec | [**Pose Estimation**](examples/vision/keypointdetection) | [**Behavior Recognition**](https://github.com/PaddlePaddle/FastDeploy/issues/6) | [**NLP**](examples/text) | [**Speech**](examples/audio/pp-tts) | | | | |

**input**:Life was like a box
of chocolates, you never
know what you're
gonna get.

**output**: [](https://paddlespeech.bj.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_1.wav)

| -## 📣 Recent Updates +## 👬 Community -- **Community** + - **Slack**:Join our [Slack community](https://join.slack.com/t/fastdeployworkspace/shared_invite/zt-1jznah134-3rxY~ytRb8rcPqkn9g~PDg) and chat with other community members about ideas. - - **Slack**:Join our [Slack community](https://join.slack.com/t/fastdeployworkspace/shared_invite/zt-1hhvpb279-iw2pNPwrDaMBQ5OQhO3Siw) and chat with other community members about ideas. - - - **WeChat**:Scan the QR code below using WeChat, follow the PaddlePaddle official account and fill out the questionnaire to join the WeChat group. + - **WeChat**:Scan the QR code below using WeChat, follow the PaddlePaddle official account and fill out the questionnaire to join the WeChat group.
- +
-- 🔥 **2022.11.23:Release FastDeploy [release v0.8.0](https://github.com/PaddlePaddle/FastDeploy/tree/release/0.8.0)**
- - - **🖥️ Server-side and Cloud Deployment: Support more CV models, improve deployment performance** - - - Support [PIPNet](./examples/vision/facealign/pipnet), [FaceLandmark1000](./examples/vision/facealign/face_landmark_1000) face alignment models deployment; - - Support [Video Super-Resolution](./examples/vision/sr) series model PP-MSVSR、EDVR、BasicVSR; - - Upgrade YOLOv7 deployment code to add `batch_predict` deployment; - - Support [UIE service-based](./examples/text/uie) deployment; - - Add Python API to_dlpack interface for FDTensor to support copyless transfer of FDTensor between frameworks. - - - **📱 Mobile and Edge Device Deployment: support more CV model** - - - Support Android image classification, target detection, semantic segmentation, OCR, face detection APK projects and examples. - - | Image Classification | Object Detection | Semantic Segmentation | OCR | Face Detection | - |:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| - | [Project Code](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification) | [Project Code](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection) | [Project Code](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation) | [Project Code](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr) | [Project Code](https://github.com/PaddlePaddle/FastDeploy/tree/develop/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet) | - | [Scan the code
or click on the link
to install](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-MobileNetV1.apk)
| [Scan the code
or click on the link
to install](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-PicoDet.apk)
| [Scan the code
or click on the link
to install](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-Portrait-HumanSegV2-Lite.apk)
| [Scan the code
or click on the link
to install](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-PP-OCRv2.apk)
| [Scan the code
or click on the link
to install](https://bj.bcebos.com/fastdeploy/release/android/FastDeploy-SCRFD.apk)
| - | | | | | | - -- [**more releases information**](./releases) - ## Contents -*
📖 Tutorials(click to fold)
- - - Install - - - [Install FastDeploy Prebuilt Libraries](docs/en/build_and_install/download_prebuilt_libraries.md) - - [Build and Install FastDeploy Library on GPU Platform](docs/en/build_and_install/gpu.md) - - [Build and Install FastDeploy Library on CPU Platform](docs/en/build_and_install/cpu.md) - - [Build and Install FastDeploy Library on IPU Platform](docs/en/build_and_install/ipu.md) - - [Build and Install FastDeploy Library on Nvidia Jetson Platform](docs/en/build_and_install/jetson.md) - - [Build and Install FastDeploy Library on Android Platform](docs/en/build_and_install/android.md) - - - A Quick Start - Demos - - - [Python Deployment Demo](docs/en/quick_start/models/python.md) - - [C++ Deployment Demo](docs/en/quick_start/models/cpp.md) - - [A Quick Start on Runtime Python](docs/en/quick_start/runtime/python.md) - - [A Quick Start on Runtime C++](docs/en/quick_start/runtime/cpp.md) - - - API (To be continued) - - - [Python API](https://baidu-paddle.github.io/fastdeploy-api/python/html/) - - [C++ API](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/) - - - Performance Optimization - - - [Quantization Acceleration](docs/en/quantize.md) - - - Frequent Q&As - - - [1. How to Change Inference Backends](docs/en/faq/how_to_change_backend.md) - - [2. How to Use FastDeploy C++ SDK on Windows Platform](docs/en/faq/use_sdk_on_windows.md) - - [3. How to Use FastDeploy C++ SDK on Android Platform](java/android/README_EN.md)(To be Continued) - - [4. Tricks of TensorRT](docs/en/faq/tensorrt_tricks.md) - - [5. How to Develop a New Model](docs/en/faq/develop_a_new_model.md)(To be Continued) - - - More FastDeploy Deployment Module - - - [deployment AI Model as a Service](./serving) - - - [Benchmark Testing](./benchmark) - -
- * **🖥️ Server-side and Cloud Deployment** - * [A Quick Start for Python SDK](#fastdeploy-quick-start-python) * [A Quick Start for C++ SDK](#fastdeploy-quick-start-cpp) * [Supported Server-side and Cloud Model List](#fastdeploy-server-models) @@ -129,11 +61,9 @@ Including image classification, object detection, image segmentation, face detec * [Supported Web and Mini Program Model List](#fastdeploy-web-models) -* [**Community**](#fastdeploy-community) +* [Acknowledge](#fastdeploy-acknowledge) -* [**Acknowledge**](#fastdeploy-acknowledge) - -* [**License**](#fastdeploy-license) +* [License](#fastdeploy-license) ## 🖥️ Server-side and Cloud Deployment @@ -272,15 +202,14 @@ Notes: ✅: already supported; ❔: to be supported in the future; N/A: Not Ava | Classification | [PaddleClas/SqueeezeNetV1.1](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Classification | [PaddleClas/Inceptionv3](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | | Classification | [PaddleClas/PP-HGNet](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| Classification | [PaddleClas/SwinTransformer](./examples/vision/classification/paddleclas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PP-YOLOE](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PicoDet](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/YOLOX](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/YOLOv3](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PP-YOLO](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/PP-YOLOv2](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/Faster-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | -| Detection | [PaddleDetection/Mask-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLOE](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PicoDet](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/YOLOX](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/YOLOv3](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLO](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/PP-YOLOv2](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/Faster-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | +| Detection | [PaddleDetection/Mask-RCNN](./examples/vision/detection/paddledetection) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | | Detection | [Megvii-BaseDetection/YOLOX](./examples/vision/detection/yolox) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Detection | [WongKinYiu/YOLOv7](./examples/vision/detection/yolov7) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Detection | [WongKinYiu/YOLOv7end2end_trt](./examples/vision/detection/yolov7end2end_trt) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | @@ -317,14 +246,14 @@ Notes: ✅: already supported; ❔: to be supported in the future; N/A: Not Ava | Matting | [ZHKKKe/MODNet](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Matting | [PeterL1n/RobustVideoMatting]() | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Matting | [PaddleSeg/PP-Matting](./examples/vision/matting/ppmatting) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -| Matting | [PaddleSeg/PP-HumanMatting](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | +| Matting | [PaddleSeg/PP-HumanMatting](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Matting | [PaddleSeg/ModNet](./examples/vision/matting/modnet) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/BasicVSR](./) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/EDVR](./examples/vision/sr/edvr) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Video Super-Resolution | [PaddleGAN/PP-MSVSR](./examples/vision/sr/ppmsvsr) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | | Information Extraction | [PaddleNLP/UIE](./examples/text/uie) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | | | NLP | [PaddleNLP/ERNIE-3.0](./examples/text/ernie-3.0) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | ❔ | ✅ | -| Speech | [PaddleSpeech/PP-TTS](./examples/text/uie) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -- | ✅ | +| Speech | [PaddleSpeech/PP-TTS](./examples/audio/pp-tts) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | -- | ✅ | @@ -390,18 +319,6 @@ Notes: ✅: already supported; ❔: to be supported in the future; N/A: Not Ava -## Community - -
- -- If you have any question or suggestion, please give us your valuable input via GitHub Issues -- **Join Us👬:** - - **Slack**:Join our [Slack community](https://join.slack.com/t/fastdeployworkspace/shared_invite/zt-1hhvpb279-iw2pNPwrDaMBQ5OQhO3Siw) and chat with other community members about ideas - - **WeChat**:join our **WeChat community** and chat with other community members about ideas - -
- -
## Acknowledge diff --git a/benchmark/benchmark_ppcls.py b/benchmark/benchmark_ppcls.py index 8eeeb8cfc..6b88658ee 100755 --- a/benchmark/benchmark_ppcls.py +++ b/benchmark/benchmark_ppcls.py @@ -75,6 +75,11 @@ def build_option(args): option.use_ort_backend() elif backend == "paddle": option.use_paddle_backend() + elif backend == "ov": + option.use_openvino_backend() + option.set_openvino_device(name="GPU") + # change name and shape for models + option.set_openvino_shape_info({"x": [1, 3, 224, 224]}) elif backend in ["trt", "paddle_trt"]: option.use_trt_backend() if backend == "paddle_trt": @@ -108,27 +113,109 @@ def build_option(args): return option -def get_current_memory_mb(gpu_id=None): - import pynvml - import psutil - pid = os.getpid() - p = psutil.Process(pid) - info = p.memory_full_info() - cpu_mem = info.uss / 1024. / 1024. - gpu_mem = 0 - if gpu_id is not None: - pynvml.nvmlInit() - handle = pynvml.nvmlDeviceGetHandleByIndex(0) - meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle) - gpu_mem = meminfo.used / 1024. / 1024. - return cpu_mem, gpu_mem +class StatBase(object): + """StatBase""" + nvidia_smi_path = "nvidia-smi" + gpu_keys = ('index', 'uuid', 'name', 'timestamp', 'memory.total', + 'memory.free', 'memory.used', 'utilization.gpu', + 'utilization.memory') + nu_opt = ',nounits' + cpu_keys = ('cpu.util', 'memory.util', 'memory.used') -def get_current_gputil(gpu_id): - import GPUtil - GPUs = GPUtil.getGPUs() - gpu_load = GPUs[gpu_id].load - return gpu_load +class Monitor(StatBase): + """Monitor""" + + def __init__(self, use_gpu=False, gpu_id=0, interval=0.1): + self.result = {} + self.gpu_id = gpu_id + self.use_gpu = use_gpu + self.interval = interval + self.cpu_stat_q = multiprocessing.Queue() + + def start(self): + cmd = '%s --id=%s --query-gpu=%s --format=csv,noheader%s -lms 50' % ( + StatBase.nvidia_smi_path, self.gpu_id, ','.join(StatBase.gpu_keys), + StatBase.nu_opt) + if self.use_gpu: + self.gpu_stat_worker = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + shell=True, + close_fds=True, + preexec_fn=os.setsid) + # cpu stat + pid = os.getpid() + self.cpu_stat_worker = multiprocessing.Process( + target=self.cpu_stat_func, + args=(self.cpu_stat_q, pid, self.interval)) + self.cpu_stat_worker.start() + + def stop(self): + try: + if self.use_gpu: + os.killpg(self.gpu_stat_worker.pid, signal.SIGUSR1) + # os.killpg(p.pid, signal.SIGTERM) + self.cpu_stat_worker.terminate() + self.cpu_stat_worker.join(timeout=0.01) + except Exception as e: + print(e) + return + + # gpu + if self.use_gpu: + lines = self.gpu_stat_worker.stdout.readlines() + lines = [ + line.strip().decode("utf-8") for line in lines + if line.strip() != '' + ] + gpu_info_list = [{ + k: v + for k, v in zip(StatBase.gpu_keys, line.split(', ')) + } for line in lines] + if len(gpu_info_list) == 0: + return + result = gpu_info_list[0] + for item in gpu_info_list: + for k in item.keys(): + if k not in ["name", "uuid", "timestamp"]: + result[k] = max(int(result[k]), int(item[k])) + else: + result[k] = max(result[k], item[k]) + self.result['gpu'] = result + + # cpu + cpu_result = {} + if self.cpu_stat_q.qsize() > 0: + cpu_result = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + while not self.cpu_stat_q.empty(): + item = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + for k in StatBase.cpu_keys: + cpu_result[k] = max(cpu_result[k], item[k]) + cpu_result['name'] = cpuinfo.get_cpu_info()['brand_raw'] + self.result['cpu'] = cpu_result + + def output(self): + return self.result + + def cpu_stat_func(self, q, pid, interval=0.0): + """cpu stat function""" + stat_info = psutil.Process(pid) + while True: + # pid = os.getpid() + cpu_util, mem_util, mem_use = stat_info.cpu_percent( + ), stat_info.memory_percent(), round(stat_info.memory_info().rss / + 1024.0 / 1024.0, 4) + q.put([cpu_util, mem_util, mem_use]) + time.sleep(interval) + return if __name__ == '__main__': @@ -141,6 +228,7 @@ if __name__ == '__main__': gpu_id = args.device_id enable_collect_memory_info = args.enable_collect_memory_info + dump_result = dict() end2end_statis = list() cpu_mem = list() gpu_mem = list() @@ -160,6 +248,16 @@ if __name__ == '__main__': try: model = fd.vision.classification.PaddleClasModel( model_file, params_file, config_file, runtime_option=option) + if enable_collect_memory_info: + import multiprocessing + import subprocess + import psutil + import signal + import cpuinfo + enable_gpu = args.device == "gpu" + monitor = Monitor(enable_gpu, gpu_id) + monitor.start() + model.enable_record_time_of_runtime() im_ori = cv2.imread(args.image) for i in range(args.iter_num): @@ -167,31 +265,28 @@ if __name__ == '__main__': start = time.time() result = model.predict(im) end2end_statis.append(time.time() - start) - if enable_collect_memory_info: - gpu_util.append(get_current_gputil(gpu_id)) - cm, gm = get_current_memory_mb(gpu_id) - cpu_mem.append(cm) - gpu_mem.append(gm) runtime_statis = model.print_statis_info_of_runtime() warmup_iter = args.iter_num // 5 end2end_statis_repeat = end2end_statis[warmup_iter:] if enable_collect_memory_info: - cpu_mem_repeat = cpu_mem[warmup_iter:] - gpu_mem_repeat = gpu_mem[warmup_iter:] - gpu_util_repeat = gpu_util[warmup_iter:] + monitor.stop() + mem_info = monitor.output() + dump_result["cpu_rss_mb"] = mem_info['cpu'][ + 'memory.used'] if 'cpu' in mem_info else 0 + dump_result["gpu_rss_mb"] = mem_info['gpu'][ + 'memory.used'] if 'gpu' in mem_info else 0 + dump_result["gpu_util"] = mem_info['gpu'][ + 'utilization.gpu'] if 'gpu' in mem_info else 0 - dump_result = dict() dump_result["runtime"] = runtime_statis["avg_time"] * 1000 dump_result["end2end"] = np.mean(end2end_statis_repeat) * 1000 - if enable_collect_memory_info: - dump_result["cpu_rss_mb"] = np.mean(cpu_mem_repeat) - dump_result["gpu_rss_mb"] = np.mean(gpu_mem_repeat) - dump_result["gpu_util"] = np.mean(gpu_util_repeat) f.writelines("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) f.writelines("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + print("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + print("End2End(ms): {} \n".format(str(dump_result["end2end"]))) if enable_collect_memory_info: f.writelines("cpu_rss_mb: {} \n".format( str(dump_result["cpu_rss_mb"]))) @@ -199,6 +294,9 @@ if __name__ == '__main__': str(dump_result["gpu_rss_mb"]))) f.writelines("gpu_util: {} \n".format( str(dump_result["gpu_util"]))) + print("cpu_rss_mb: {} \n".format(str(dump_result["cpu_rss_mb"]))) + print("gpu_rss_mb: {} \n".format(str(dump_result["gpu_rss_mb"]))) + print("gpu_util: {} \n".format(str(dump_result["gpu_util"]))) except: f.writelines("!!!!!Infer Failed\n") diff --git a/benchmark/benchmark_ppdet.py b/benchmark/benchmark_ppdet.py index 6d08aafb8..8f7033db4 100755 --- a/benchmark/benchmark_ppdet.py +++ b/benchmark/benchmark_ppdet.py @@ -75,6 +75,17 @@ def build_option(args): option.use_ort_backend() elif backend == "paddle": option.use_paddle_backend() + elif backend == "ov": + option.use_openvino_backend() + # Using GPU and CPU heterogeneous execution mode + option.set_openvino_device("HETERO:GPU,CPU") + # change name and shape for models + option.set_openvino_shape_info({ + "image": [1, 3, 320, 320], + "scale_factor": [1, 2] + }) + # Set CPU up operator + option.set_openvino_cpu_operators(["MulticlassNms"]) elif backend in ["trt", "paddle_trt"]: option.use_trt_backend() if backend == "paddle_trt": @@ -108,27 +119,109 @@ def build_option(args): return option -def get_current_memory_mb(gpu_id=None): - import pynvml - import psutil - pid = os.getpid() - p = psutil.Process(pid) - info = p.memory_full_info() - cpu_mem = info.uss / 1024. / 1024. - gpu_mem = 0 - if gpu_id is not None: - pynvml.nvmlInit() - handle = pynvml.nvmlDeviceGetHandleByIndex(0) - meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle) - gpu_mem = meminfo.used / 1024. / 1024. - return cpu_mem, gpu_mem +class StatBase(object): + """StatBase""" + nvidia_smi_path = "nvidia-smi" + gpu_keys = ('index', 'uuid', 'name', 'timestamp', 'memory.total', + 'memory.free', 'memory.used', 'utilization.gpu', + 'utilization.memory') + nu_opt = ',nounits' + cpu_keys = ('cpu.util', 'memory.util', 'memory.used') -def get_current_gputil(gpu_id): - import GPUtil - GPUs = GPUtil.getGPUs() - gpu_load = GPUs[gpu_id].load - return gpu_load +class Monitor(StatBase): + """Monitor""" + + def __init__(self, use_gpu=False, gpu_id=0, interval=0.1): + self.result = {} + self.gpu_id = gpu_id + self.use_gpu = use_gpu + self.interval = interval + self.cpu_stat_q = multiprocessing.Queue() + + def start(self): + cmd = '%s --id=%s --query-gpu=%s --format=csv,noheader%s -lms 50' % ( + StatBase.nvidia_smi_path, self.gpu_id, ','.join(StatBase.gpu_keys), + StatBase.nu_opt) + if self.use_gpu: + self.gpu_stat_worker = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + shell=True, + close_fds=True, + preexec_fn=os.setsid) + # cpu stat + pid = os.getpid() + self.cpu_stat_worker = multiprocessing.Process( + target=self.cpu_stat_func, + args=(self.cpu_stat_q, pid, self.interval)) + self.cpu_stat_worker.start() + + def stop(self): + try: + if self.use_gpu: + os.killpg(self.gpu_stat_worker.pid, signal.SIGUSR1) + # os.killpg(p.pid, signal.SIGTERM) + self.cpu_stat_worker.terminate() + self.cpu_stat_worker.join(timeout=0.01) + except Exception as e: + print(e) + return + + # gpu + if self.use_gpu: + lines = self.gpu_stat_worker.stdout.readlines() + lines = [ + line.strip().decode("utf-8") for line in lines + if line.strip() != '' + ] + gpu_info_list = [{ + k: v + for k, v in zip(StatBase.gpu_keys, line.split(', ')) + } for line in lines] + if len(gpu_info_list) == 0: + return + result = gpu_info_list[0] + for item in gpu_info_list: + for k in item.keys(): + if k not in ["name", "uuid", "timestamp"]: + result[k] = max(int(result[k]), int(item[k])) + else: + result[k] = max(result[k], item[k]) + self.result['gpu'] = result + + # cpu + cpu_result = {} + if self.cpu_stat_q.qsize() > 0: + cpu_result = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + while not self.cpu_stat_q.empty(): + item = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + for k in StatBase.cpu_keys: + cpu_result[k] = max(cpu_result[k], item[k]) + cpu_result['name'] = cpuinfo.get_cpu_info()['brand_raw'] + self.result['cpu'] = cpu_result + + def output(self): + return self.result + + def cpu_stat_func(self, q, pid, interval=0.0): + """cpu stat function""" + stat_info = psutil.Process(pid) + while True: + # pid = os.getpid() + cpu_util, mem_util, mem_use = stat_info.cpu_percent( + ), stat_info.memory_percent(), round(stat_info.memory_info().rss / + 1024.0 / 1024.0, 4) + q.put([cpu_util, mem_util, mem_use]) + time.sleep(interval) + return if __name__ == '__main__': @@ -141,6 +234,7 @@ if __name__ == '__main__': gpu_id = args.device_id enable_collect_memory_info = args.enable_collect_memory_info + dump_result = dict() end2end_statis = list() cpu_mem = list() gpu_mem = list() @@ -178,6 +272,16 @@ if __name__ == '__main__': else: raise Exception("model {} not support now in ppdet series".format( args.model)) + if enable_collect_memory_info: + import multiprocessing + import subprocess + import psutil + import signal + import cpuinfo + enable_gpu = args.device == "gpu" + monitor = Monitor(enable_gpu, gpu_id) + monitor.start() + model.enable_record_time_of_runtime() im_ori = cv2.imread(args.image) for i in range(args.iter_num): @@ -185,31 +289,28 @@ if __name__ == '__main__': start = time.time() result = model.predict(im) end2end_statis.append(time.time() - start) - if enable_collect_memory_info: - gpu_util.append(get_current_gputil(gpu_id)) - cm, gm = get_current_memory_mb(gpu_id) - cpu_mem.append(cm) - gpu_mem.append(gm) runtime_statis = model.print_statis_info_of_runtime() warmup_iter = args.iter_num // 5 end2end_statis_repeat = end2end_statis[warmup_iter:] if enable_collect_memory_info: - cpu_mem_repeat = cpu_mem[warmup_iter:] - gpu_mem_repeat = gpu_mem[warmup_iter:] - gpu_util_repeat = gpu_util[warmup_iter:] + monitor.stop() + mem_info = monitor.output() + dump_result["cpu_rss_mb"] = mem_info['cpu'][ + 'memory.used'] if 'cpu' in mem_info else 0 + dump_result["gpu_rss_mb"] = mem_info['gpu'][ + 'memory.used'] if 'gpu' in mem_info else 0 + dump_result["gpu_util"] = mem_info['gpu'][ + 'utilization.gpu'] if 'gpu' in mem_info else 0 - dump_result = dict() dump_result["runtime"] = runtime_statis["avg_time"] * 1000 dump_result["end2end"] = np.mean(end2end_statis_repeat) * 1000 - if enable_collect_memory_info: - dump_result["cpu_rss_mb"] = np.mean(cpu_mem_repeat) - dump_result["gpu_rss_mb"] = np.mean(gpu_mem_repeat) - dump_result["gpu_util"] = np.mean(gpu_util_repeat) f.writelines("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) f.writelines("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + print("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + print("End2End(ms): {} \n".format(str(dump_result["end2end"]))) if enable_collect_memory_info: f.writelines("cpu_rss_mb: {} \n".format( str(dump_result["cpu_rss_mb"]))) @@ -217,6 +318,9 @@ if __name__ == '__main__': str(dump_result["gpu_rss_mb"]))) f.writelines("gpu_util: {} \n".format( str(dump_result["gpu_util"]))) + print("cpu_rss_mb: {} \n".format(str(dump_result["cpu_rss_mb"]))) + print("gpu_rss_mb: {} \n".format(str(dump_result["gpu_rss_mb"]))) + print("gpu_util: {} \n".format(str(dump_result["gpu_util"]))) except: f.writelines("!!!!!Infer Failed\n") diff --git a/benchmark/benchmark_ppocr.py b/benchmark/benchmark_ppocr.py new file mode 100644 index 000000000..885f9a5a5 --- /dev/null +++ b/benchmark/benchmark_ppocr.py @@ -0,0 +1,377 @@ +# 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 fastdeploy as fd +import cv2 +import os +import numpy as np +import time + + +def parse_arguments(): + import argparse + import ast + parser = argparse.ArgumentParser() + parser.add_argument( + "--model_dir", required=True, help="Model dir of PPOCR.") + parser.add_argument( + "--det_model", required=True, help="Path of Detection model of PPOCR.") + parser.add_argument( + "--cls_model", + required=True, + help="Path of Classification model of PPOCR.") + parser.add_argument( + "--rec_model", + required=True, + help="Path of Recognization model of PPOCR.") + parser.add_argument( + "--rec_label_file", + required=True, + help="Path of Recognization model of PPOCR.") + parser.add_argument( + "--image", type=str, required=False, help="Path of test image file.") + parser.add_argument( + "--cpu_num_thread", + type=int, + default=8, + help="default number of cpu thread.") + parser.add_argument( + "--device_id", type=int, default=0, help="device(gpu) id") + parser.add_argument( + "--iter_num", + required=True, + type=int, + default=300, + help="number of iterations for computing performace.") + parser.add_argument( + "--device", + default="cpu", + help="Type of inference device, support 'cpu' or 'gpu'.") + parser.add_argument( + "--backend", + type=str, + default="default", + help="inference backend, default, ort, ov, trt, paddle, paddle_trt.") + parser.add_argument( + "--enable_trt_fp16", + type=ast.literal_eval, + default=False, + help="whether enable fp16 in trt backend") + parser.add_argument( + "--enable_collect_memory_info", + type=ast.literal_eval, + default=False, + help="whether enable collect memory info") + args = parser.parse_args() + return args + + +def build_option(args): + option = fd.RuntimeOption() + device = args.device + backend = args.backend + enable_trt_fp16 = args.enable_trt_fp16 + option.set_cpu_thread_num(args.cpu_num_thread) + if device == "gpu": + option.use_gpu() + if backend == "ort": + option.use_ort_backend() + elif backend == "paddle": + option.use_paddle_backend() + elif backend in ["trt", "paddle_trt"]: + option.use_trt_backend() + if backend == "paddle_trt": + option.enable_paddle_to_trt() + if enable_trt_fp16: + option.enable_trt_fp16() + elif backend == "default": + return option + else: + raise Exception( + "While inference with GPU, only support default/ort/paddle/trt/paddle_trt now, {} is not supported.". + format(backend)) + elif device == "cpu": + if backend == "ort": + option.use_ort_backend() + elif backend == "ov": + option.use_openvino_backend() + elif backend == "paddle": + option.use_paddle_backend() + elif backend == "default": + return option + else: + raise Exception( + "While inference with CPU, only support default/ort/ov/paddle now, {} is not supported.". + format(backend)) + else: + raise Exception( + "Only support device CPU/GPU now, {} is not supported.".format( + device)) + + return option + + +class StatBase(object): + """StatBase""" + nvidia_smi_path = "nvidia-smi" + gpu_keys = ('index', 'uuid', 'name', 'timestamp', 'memory.total', + 'memory.free', 'memory.used', 'utilization.gpu', + 'utilization.memory') + nu_opt = ',nounits' + cpu_keys = ('cpu.util', 'memory.util', 'memory.used') + + +class Monitor(StatBase): + """Monitor""" + + def __init__(self, use_gpu=False, gpu_id=0, interval=0.1): + self.result = {} + self.gpu_id = gpu_id + self.use_gpu = use_gpu + self.interval = interval + self.cpu_stat_q = multiprocessing.Queue() + + def start(self): + cmd = '%s --id=%s --query-gpu=%s --format=csv,noheader%s -lms 50' % ( + StatBase.nvidia_smi_path, self.gpu_id, ','.join(StatBase.gpu_keys), + StatBase.nu_opt) + if self.use_gpu: + self.gpu_stat_worker = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + shell=True, + close_fds=True, + preexec_fn=os.setsid) + # cpu stat + pid = os.getpid() + self.cpu_stat_worker = multiprocessing.Process( + target=self.cpu_stat_func, + args=(self.cpu_stat_q, pid, self.interval)) + self.cpu_stat_worker.start() + + def stop(self): + try: + if self.use_gpu: + os.killpg(self.gpu_stat_worker.pid, signal.SIGUSR1) + # os.killpg(p.pid, signal.SIGTERM) + self.cpu_stat_worker.terminate() + self.cpu_stat_worker.join(timeout=0.01) + except Exception as e: + print(e) + return + + # gpu + if self.use_gpu: + lines = self.gpu_stat_worker.stdout.readlines() + lines = [ + line.strip().decode("utf-8") for line in lines + if line.strip() != '' + ] + gpu_info_list = [{ + k: v + for k, v in zip(StatBase.gpu_keys, line.split(', ')) + } for line in lines] + if len(gpu_info_list) == 0: + return + result = gpu_info_list[0] + for item in gpu_info_list: + for k in item.keys(): + if k not in ["name", "uuid", "timestamp"]: + result[k] = max(int(result[k]), int(item[k])) + else: + result[k] = max(result[k], item[k]) + self.result['gpu'] = result + + # cpu + cpu_result = {} + if self.cpu_stat_q.qsize() > 0: + cpu_result = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + while not self.cpu_stat_q.empty(): + item = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + for k in StatBase.cpu_keys: + cpu_result[k] = max(cpu_result[k], item[k]) + cpu_result['name'] = cpuinfo.get_cpu_info()['brand_raw'] + self.result['cpu'] = cpu_result + + def output(self): + return self.result + + def cpu_stat_func(self, q, pid, interval=0.0): + """cpu stat function""" + stat_info = psutil.Process(pid) + while True: + # pid = os.getpid() + cpu_util, mem_util, mem_use = stat_info.cpu_percent( + ), stat_info.memory_percent(), round(stat_info.memory_info().rss / + 1024.0 / 1024.0, 4) + q.put([cpu_util, mem_util, mem_use]) + time.sleep(interval) + return + + +if __name__ == '__main__': + + args = parse_arguments() + option = build_option(args) + # Detection Model + det_model_file = os.path.join(args.model_dir, args.det_model, + "inference.pdmodel") + det_params_file = os.path.join(args.model_dir, args.det_model, + "inference.pdiparams") + # Classification Model + cls_model_file = os.path.join(args.model_dir, args.cls_model, + "inference.pdmodel") + cls_params_file = os.path.join(args.model_dir, args.cls_model, + "inference.pdiparams") + # Recognition Model + rec_model_file = os.path.join(args.model_dir, args.rec_model, + "inference.pdmodel") + rec_params_file = os.path.join(args.model_dir, args.rec_model, + "inference.pdiparams") + rec_label_file = os.path.join(args.model_dir, args.rec_label_file) + + gpu_id = args.device_id + enable_collect_memory_info = args.enable_collect_memory_info + dump_result = dict() + end2end_statis = list() + cpu_mem = list() + gpu_mem = list() + gpu_util = list() + if args.device == "cpu": + file_path = args.model_dir + "_model_" + args.backend + "_" + \ + args.device + "_" + str(args.cpu_num_thread) + ".txt" + else: + if args.enable_trt_fp16: + file_path = args.model_dir + "_model_" + args.backend + "_fp16_" + args.device + ".txt" + else: + file_path = args.model_dir + "_model_" + args.backend + "_" + args.device + ".txt" + f = open(file_path, "w") + f.writelines("===={}====: \n".format(os.path.split(file_path)[-1][:-4])) + + try: + rec_option = option + if "OCRv2" in args.model_dir: + det_option = option + if args.backend in ["trt", "paddle_trt"]: + det_option.set_trt_input_shape( + "x", [1, 3, 64, 64], [1, 3, 640, 640], [1, 3, 960, 960]) + det_model = fd.vision.ocr.DBDetector( + det_model_file, det_params_file, runtime_option=det_option) + cls_option = option + if args.backend in ["trt", "paddle_trt"]: + cls_option.set_trt_input_shape( + "x", [1, 3, 48, 10], [10, 3, 48, 320], [64, 3, 48, 1024]) + cls_model = fd.vision.ocr.Classifier( + cls_model_file, cls_params_file, runtime_option=cls_option) + rec_option = option + if args.backend in ["trt", "paddle_trt"]: + rec_option.set_trt_input_shape( + "x", [1, 3, 32, 10], [10, 3, 32, 320], [32, 3, 32, 2304]) + rec_model = fd.vision.ocr.Recognizer( + rec_model_file, + rec_params_file, + rec_label_file, + runtime_option=rec_option) + model = fd.vision.ocr.PPOCRv2( + det_model=det_model, cls_model=cls_model, rec_model=rec_model) + elif "OCRv3" in args.model_dir: + if args.backend in ["trt", "paddle_trt"]: + det_option.set_trt_input_shape( + "x", [1, 3, 64, 64], [1, 3, 640, 640], [1, 3, 960, 960]) + det_model = fd.vision.ocr.DBDetector( + det_model_file, det_params_file, runtime_option=det_option) + if args.backend in ["trt", "paddle_trt"]: + cls_option.set_trt_input_shape( + "x", [1, 3, 48, 10], [10, 3, 48, 320], [64, 3, 48, 1024]) + cls_model = fd.vision.ocr.Classifier( + cls_model_file, cls_params_file, runtime_option=cls_option) + if args.backend in ["trt", "paddle_trt"]: + rec_option.set_trt_input_shape( + "x", [1, 3, 48, 10], [10, 3, 48, 320], [64, 3, 48, 2304]) + rec_model = fd.vision.ocr.Recognizer( + rec_model_file, + rec_params_file, + rec_label_file, + runtime_option=rec_option) + model = fd.vision.ocr.PPOCRv3( + det_model=det_model, cls_model=cls_model, rec_model=rec_model) + else: + raise Exception("model {} not support now in ppocr series".format( + args.model_dir)) + if enable_collect_memory_info: + import multiprocessing + import subprocess + import psutil + import signal + import cpuinfo + enable_gpu = args.device == "gpu" + monitor = Monitor(enable_gpu, gpu_id) + monitor.start() + + det_model.enable_record_time_of_runtime() + cls_model.enable_record_time_of_runtime() + rec_model.enable_record_time_of_runtime() + im_ori = cv2.imread(args.image) + for i in range(args.iter_num): + im = im_ori + start = time.time() + result = model.predict(im) + end2end_statis.append(time.time() - start) + + runtime_statis_det = det_model.print_statis_info_of_runtime() + runtime_statis_cls = cls_model.print_statis_info_of_runtime() + runtime_statis_rec = rec_model.print_statis_info_of_runtime() + + warmup_iter = args.iter_num // 5 + end2end_statis_repeat = end2end_statis[warmup_iter:] + if enable_collect_memory_info: + monitor.stop() + mem_info = monitor.output() + dump_result["cpu_rss_mb"] = mem_info['cpu'][ + 'memory.used'] if 'cpu' in mem_info else 0 + dump_result["gpu_rss_mb"] = mem_info['gpu'][ + 'memory.used'] if 'gpu' in mem_info else 0 + dump_result["gpu_util"] = mem_info['gpu'][ + 'utilization.gpu'] if 'gpu' in mem_info else 0 + + dump_result["runtime"] = ( + runtime_statis_det["avg_time"] + runtime_statis_cls["avg_time"] + + runtime_statis_rec["avg_time"]) * 1000 + dump_result["end2end"] = np.mean(end2end_statis_repeat) * 1000 + + f.writelines("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + f.writelines("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + print("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + print("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + if enable_collect_memory_info: + f.writelines("cpu_rss_mb: {} \n".format( + str(dump_result["cpu_rss_mb"]))) + f.writelines("gpu_rss_mb: {} \n".format( + str(dump_result["gpu_rss_mb"]))) + f.writelines("gpu_util: {} \n".format( + str(dump_result["gpu_util"]))) + print("cpu_rss_mb: {} \n".format(str(dump_result["cpu_rss_mb"]))) + print("gpu_rss_mb: {} \n".format(str(dump_result["gpu_rss_mb"]))) + print("gpu_util: {} \n".format(str(dump_result["gpu_util"]))) + except: + f.writelines("!!!!!Infer Failed\n") + + f.close() diff --git a/benchmark/benchmark_ppseg.py b/benchmark/benchmark_ppseg.py index 7d9df9f07..3c7a9847e 100755 --- a/benchmark/benchmark_ppseg.py +++ b/benchmark/benchmark_ppseg.py @@ -75,6 +75,11 @@ def build_option(args): option.use_ort_backend() elif backend == "paddle": option.use_paddle_backend() + elif backend == "ov": + option.use_openvino_backend() + option.set_openvino_device(name="GPU") # use gpu + # change name and shape for models + option.set_openvino_shape_info({"x": [1, 3, 512, 512]}) elif backend in ["trt", "paddle_trt"]: option.use_trt_backend() if backend == "paddle_trt": @@ -108,27 +113,109 @@ def build_option(args): return option -def get_current_memory_mb(gpu_id=None): - import pynvml - import psutil - pid = os.getpid() - p = psutil.Process(pid) - info = p.memory_full_info() - cpu_mem = info.uss / 1024. / 1024. - gpu_mem = 0 - if gpu_id is not None: - pynvml.nvmlInit() - handle = pynvml.nvmlDeviceGetHandleByIndex(0) - meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle) - gpu_mem = meminfo.used / 1024. / 1024. - return cpu_mem, gpu_mem +class StatBase(object): + """StatBase""" + nvidia_smi_path = "nvidia-smi" + gpu_keys = ('index', 'uuid', 'name', 'timestamp', 'memory.total', + 'memory.free', 'memory.used', 'utilization.gpu', + 'utilization.memory') + nu_opt = ',nounits' + cpu_keys = ('cpu.util', 'memory.util', 'memory.used') -def get_current_gputil(gpu_id): - import GPUtil - GPUs = GPUtil.getGPUs() - gpu_load = GPUs[gpu_id].load - return gpu_load +class Monitor(StatBase): + """Monitor""" + + def __init__(self, use_gpu=False, gpu_id=0, interval=0.1): + self.result = {} + self.gpu_id = gpu_id + self.use_gpu = use_gpu + self.interval = interval + self.cpu_stat_q = multiprocessing.Queue() + + def start(self): + cmd = '%s --id=%s --query-gpu=%s --format=csv,noheader%s -lms 50' % ( + StatBase.nvidia_smi_path, self.gpu_id, ','.join(StatBase.gpu_keys), + StatBase.nu_opt) + if self.use_gpu: + self.gpu_stat_worker = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + shell=True, + close_fds=True, + preexec_fn=os.setsid) + # cpu stat + pid = os.getpid() + self.cpu_stat_worker = multiprocessing.Process( + target=self.cpu_stat_func, + args=(self.cpu_stat_q, pid, self.interval)) + self.cpu_stat_worker.start() + + def stop(self): + try: + if self.use_gpu: + os.killpg(self.gpu_stat_worker.pid, signal.SIGUSR1) + # os.killpg(p.pid, signal.SIGTERM) + self.cpu_stat_worker.terminate() + self.cpu_stat_worker.join(timeout=0.01) + except Exception as e: + print(e) + return + + # gpu + if self.use_gpu: + lines = self.gpu_stat_worker.stdout.readlines() + lines = [ + line.strip().decode("utf-8") for line in lines + if line.strip() != '' + ] + gpu_info_list = [{ + k: v + for k, v in zip(StatBase.gpu_keys, line.split(', ')) + } for line in lines] + if len(gpu_info_list) == 0: + return + result = gpu_info_list[0] + for item in gpu_info_list: + for k in item.keys(): + if k not in ["name", "uuid", "timestamp"]: + result[k] = max(int(result[k]), int(item[k])) + else: + result[k] = max(result[k], item[k]) + self.result['gpu'] = result + + # cpu + cpu_result = {} + if self.cpu_stat_q.qsize() > 0: + cpu_result = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + while not self.cpu_stat_q.empty(): + item = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + for k in StatBase.cpu_keys: + cpu_result[k] = max(cpu_result[k], item[k]) + cpu_result['name'] = cpuinfo.get_cpu_info()['brand_raw'] + self.result['cpu'] = cpu_result + + def output(self): + return self.result + + def cpu_stat_func(self, q, pid, interval=0.0): + """cpu stat function""" + stat_info = psutil.Process(pid) + while True: + # pid = os.getpid() + cpu_util, mem_util, mem_use = stat_info.cpu_percent( + ), stat_info.memory_percent(), round(stat_info.memory_info().rss / + 1024.0 / 1024.0, 4) + q.put([cpu_util, mem_util, mem_use]) + time.sleep(interval) + return if __name__ == '__main__': @@ -141,6 +228,7 @@ if __name__ == '__main__': gpu_id = args.device_id enable_collect_memory_info = args.enable_collect_memory_info + dump_result = dict() end2end_statis = list() cpu_mem = list() gpu_mem = list() @@ -159,6 +247,16 @@ if __name__ == '__main__': try: model = fd.vision.segmentation.PaddleSegModel( model_file, params_file, config_file, runtime_option=option) + if enable_collect_memory_info: + import multiprocessing + import subprocess + import psutil + import signal + import cpuinfo + enable_gpu = args.device == "gpu" + monitor = Monitor(enable_gpu, gpu_id) + monitor.start() + model.enable_record_time_of_runtime() im_ori = cv2.imread(args.image) for i in range(args.iter_num): @@ -166,31 +264,28 @@ if __name__ == '__main__': start = time.time() result = model.predict(im) end2end_statis.append(time.time() - start) - if enable_collect_memory_info: - gpu_util.append(get_current_gputil(gpu_id)) - cm, gm = get_current_memory_mb(gpu_id) - cpu_mem.append(cm) - gpu_mem.append(gm) runtime_statis = model.print_statis_info_of_runtime() warmup_iter = args.iter_num // 5 end2end_statis_repeat = end2end_statis[warmup_iter:] if enable_collect_memory_info: - cpu_mem_repeat = cpu_mem[warmup_iter:] - gpu_mem_repeat = gpu_mem[warmup_iter:] - gpu_util_repeat = gpu_util[warmup_iter:] + monitor.stop() + mem_info = monitor.output() + dump_result["cpu_rss_mb"] = mem_info['cpu'][ + 'memory.used'] if 'cpu' in mem_info else 0 + dump_result["gpu_rss_mb"] = mem_info['gpu'][ + 'memory.used'] if 'gpu' in mem_info else 0 + dump_result["gpu_util"] = mem_info['gpu'][ + 'utilization.gpu'] if 'gpu' in mem_info else 0 - dump_result = dict() dump_result["runtime"] = runtime_statis["avg_time"] * 1000 dump_result["end2end"] = np.mean(end2end_statis_repeat) * 1000 - if enable_collect_memory_info: - dump_result["cpu_rss_mb"] = np.mean(cpu_mem_repeat) - dump_result["gpu_rss_mb"] = np.mean(gpu_mem_repeat) - dump_result["gpu_util"] = np.mean(gpu_util_repeat) f.writelines("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) f.writelines("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + print("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + print("End2End(ms): {} \n".format(str(dump_result["end2end"]))) if enable_collect_memory_info: f.writelines("cpu_rss_mb: {} \n".format( str(dump_result["cpu_rss_mb"]))) @@ -198,6 +293,9 @@ if __name__ == '__main__': str(dump_result["gpu_rss_mb"]))) f.writelines("gpu_util: {} \n".format( str(dump_result["gpu_util"]))) + print("cpu_rss_mb: {} \n".format(str(dump_result["cpu_rss_mb"]))) + print("gpu_rss_mb: {} \n".format(str(dump_result["gpu_rss_mb"]))) + print("gpu_util: {} \n".format(str(dump_result["gpu_util"]))) except: f.writelines("!!!!!Infer Failed\n") diff --git a/benchmark/benchmark_yolo.py b/benchmark/benchmark_yolo.py index dd63cefb6..8fccad8e0 100755 --- a/benchmark/benchmark_yolo.py +++ b/benchmark/benchmark_yolo.py @@ -75,6 +75,11 @@ def build_option(args): option.use_ort_backend() elif backend == "paddle": option.use_paddle_backend() + elif backend == "ov": + option.use_openvino_backend() + option.set_openvino_device(name="GPU") + # change name and shape for models + option.set_openvino_shape_info({"images": [1, 3, 640, 640]}) elif backend in ["trt", "paddle_trt"]: option.use_trt_backend() if backend == "paddle_trt": @@ -108,27 +113,109 @@ def build_option(args): return option -def get_current_memory_mb(gpu_id=None): - import pynvml - import psutil - pid = os.getpid() - p = psutil.Process(pid) - info = p.memory_full_info() - cpu_mem = info.uss / 1024. / 1024. - gpu_mem = 0 - if gpu_id is not None: - pynvml.nvmlInit() - handle = pynvml.nvmlDeviceGetHandleByIndex(0) - meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle) - gpu_mem = meminfo.used / 1024. / 1024. - return cpu_mem, gpu_mem +class StatBase(object): + """StatBase""" + nvidia_smi_path = "nvidia-smi" + gpu_keys = ('index', 'uuid', 'name', 'timestamp', 'memory.total', + 'memory.free', 'memory.used', 'utilization.gpu', + 'utilization.memory') + nu_opt = ',nounits' + cpu_keys = ('cpu.util', 'memory.util', 'memory.used') -def get_current_gputil(gpu_id): - import GPUtil - GPUs = GPUtil.getGPUs() - gpu_load = GPUs[gpu_id].load - return gpu_load +class Monitor(StatBase): + """Monitor""" + + def __init__(self, use_gpu=False, gpu_id=0, interval=0.1): + self.result = {} + self.gpu_id = gpu_id + self.use_gpu = use_gpu + self.interval = interval + self.cpu_stat_q = multiprocessing.Queue() + + def start(self): + cmd = '%s --id=%s --query-gpu=%s --format=csv,noheader%s -lms 50' % ( + StatBase.nvidia_smi_path, self.gpu_id, ','.join(StatBase.gpu_keys), + StatBase.nu_opt) + if self.use_gpu: + self.gpu_stat_worker = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + shell=True, + close_fds=True, + preexec_fn=os.setsid) + # cpu stat + pid = os.getpid() + self.cpu_stat_worker = multiprocessing.Process( + target=self.cpu_stat_func, + args=(self.cpu_stat_q, pid, self.interval)) + self.cpu_stat_worker.start() + + def stop(self): + try: + if self.use_gpu: + os.killpg(self.gpu_stat_worker.pid, signal.SIGUSR1) + # os.killpg(p.pid, signal.SIGTERM) + self.cpu_stat_worker.terminate() + self.cpu_stat_worker.join(timeout=0.01) + except Exception as e: + print(e) + return + + # gpu + if self.use_gpu: + lines = self.gpu_stat_worker.stdout.readlines() + lines = [ + line.strip().decode("utf-8") for line in lines + if line.strip() != '' + ] + gpu_info_list = [{ + k: v + for k, v in zip(StatBase.gpu_keys, line.split(', ')) + } for line in lines] + if len(gpu_info_list) == 0: + return + result = gpu_info_list[0] + for item in gpu_info_list: + for k in item.keys(): + if k not in ["name", "uuid", "timestamp"]: + result[k] = max(int(result[k]), int(item[k])) + else: + result[k] = max(result[k], item[k]) + self.result['gpu'] = result + + # cpu + cpu_result = {} + if self.cpu_stat_q.qsize() > 0: + cpu_result = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + while not self.cpu_stat_q.empty(): + item = { + k: v + for k, v in zip(StatBase.cpu_keys, self.cpu_stat_q.get()) + } + for k in StatBase.cpu_keys: + cpu_result[k] = max(cpu_result[k], item[k]) + cpu_result['name'] = cpuinfo.get_cpu_info()['brand_raw'] + self.result['cpu'] = cpu_result + + def output(self): + return self.result + + def cpu_stat_func(self, q, pid, interval=0.0): + """cpu stat function""" + stat_info = psutil.Process(pid) + while True: + # pid = os.getpid() + cpu_util, mem_util, mem_use = stat_info.cpu_percent( + ), stat_info.memory_percent(), round(stat_info.memory_info().rss / + 1024.0 / 1024.0, 4) + q.put([cpu_util, mem_util, mem_use]) + time.sleep(interval) + return if __name__ == '__main__': @@ -139,6 +226,7 @@ if __name__ == '__main__': gpu_id = args.device_id enable_collect_memory_info = args.enable_collect_memory_info + dump_result = dict() end2end_statis = list() cpu_mem = list() gpu_mem = list() @@ -170,6 +258,16 @@ if __name__ == '__main__': else: raise Exception("model {} not support now in yolo series".format( args.model)) + if enable_collect_memory_info: + import multiprocessing + import subprocess + import psutil + import signal + import cpuinfo + enable_gpu = args.device == "gpu" + monitor = Monitor(enable_gpu, gpu_id) + monitor.start() + model.enable_record_time_of_runtime() im_ori = cv2.imread(args.image) for i in range(args.iter_num): @@ -177,31 +275,28 @@ if __name__ == '__main__': start = time.time() result = model.predict(im) end2end_statis.append(time.time() - start) - if enable_collect_memory_info: - gpu_util.append(get_current_gputil(gpu_id)) - cm, gm = get_current_memory_mb(gpu_id) - cpu_mem.append(cm) - gpu_mem.append(gm) runtime_statis = model.print_statis_info_of_runtime() warmup_iter = args.iter_num // 5 end2end_statis_repeat = end2end_statis[warmup_iter:] if enable_collect_memory_info: - cpu_mem_repeat = cpu_mem[warmup_iter:] - gpu_mem_repeat = gpu_mem[warmup_iter:] - gpu_util_repeat = gpu_util[warmup_iter:] + monitor.stop() + mem_info = monitor.output() + dump_result["cpu_rss_mb"] = mem_info['cpu'][ + 'memory.used'] if 'cpu' in mem_info else 0 + dump_result["gpu_rss_mb"] = mem_info['gpu'][ + 'memory.used'] if 'gpu' in mem_info else 0 + dump_result["gpu_util"] = mem_info['gpu'][ + 'utilization.gpu'] if 'gpu' in mem_info else 0 - dump_result = dict() dump_result["runtime"] = runtime_statis["avg_time"] * 1000 dump_result["end2end"] = np.mean(end2end_statis_repeat) * 1000 - if enable_collect_memory_info: - dump_result["cpu_rss_mb"] = np.mean(cpu_mem_repeat) - dump_result["gpu_rss_mb"] = np.mean(gpu_mem_repeat) - dump_result["gpu_util"] = np.mean(gpu_util_repeat) f.writelines("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) f.writelines("End2End(ms): {} \n".format(str(dump_result["end2end"]))) + print("Runtime(ms): {} \n".format(str(dump_result["runtime"]))) + print("End2End(ms): {} \n".format(str(dump_result["end2end"]))) if enable_collect_memory_info: f.writelines("cpu_rss_mb: {} \n".format( str(dump_result["cpu_rss_mb"]))) @@ -209,6 +304,9 @@ if __name__ == '__main__': str(dump_result["gpu_rss_mb"]))) f.writelines("gpu_util: {} \n".format( str(dump_result["gpu_util"]))) + print("cpu_rss_mb: {} \n".format(str(dump_result["cpu_rss_mb"]))) + print("gpu_rss_mb: {} \n".format(str(dump_result["gpu_rss_mb"]))) + print("gpu_util: {} \n".format(str(dump_result["gpu_util"]))) except: f.writelines("!!!!!Infer Failed\n") diff --git a/benchmark/convert_info.py b/benchmark/convert_info.py index 338a0cec5..e5942e1f7 100644 --- a/benchmark/convert_info.py +++ b/benchmark/convert_info.py @@ -70,10 +70,8 @@ for i in range(line_nums): cpu_rss_mb_list = cpu_rss_mb_ori.split(".") cpu_rss_mb = cpu_rss_mb_list[0] + "." + cpu_rss_mb_list[1][:2] if "gpu_rss_mb" in lines[i + 4]: - gpu_rss_mb_ori = lines[i + 4].split(": ")[1] - # two decimal places - gpu_rss_mb_list = gpu_rss_mb_ori.split(".") - gpu_rss_mb = gpu_rss_mb_list[0] + "." + gpu_rss_mb_list[1][:2] + gpu_rss_mb_ori = lines[i + 4].split(": ")[1].strip() + gpu_rss_mb = str(gpu_rss_mb_ori) + ".0" if "ort_cpu_1" in lines[i]: ort_cpu_thread1[ model_name] = runtime + "\t" + end2end + "\t" + cpu_rss_mb @@ -111,7 +109,7 @@ for i in range(line_nums): f2 = open("struct_cpu_" + domain + ".txt", "w") f2.writelines( - "model_name\tthread_nums\tort_run\tort_end2end\tcpu_rss_mb\tov_run\tov_end2end\tcpu_rss_mb\tpaddle_run\tpaddle_end2end\tcpu_rss_mb\n" + "model_name\tthread_nums\tort_run\tort_end2end\tcpu_mem\tov_run\tov_end2end\tcpu_mem\tpaddle_run\tpaddle_end2end\tcpu_mem\n" ) for model_name in model_name_set: lines1 = model_name + '\t1\t' @@ -148,7 +146,7 @@ f2.close() f3 = open("struct_gpu_" + domain + ".txt", "w") f3.writelines( - "model_name\tort_run\tort_end2end\tgpu_rss_mb\tpaddle_run\tpaddle_end2end\tgpu_rss_mb\tpaddle_trt_run\tpaddle_trt_end2end\tgpu_rss_mb\tpaddle_trt_fp16_run\tpaddle_trt_fp16_end2end\tgpu_rss_mb\ttrt_run\ttrt_end2end\tgpu_rss_mb\ttrt_fp16_run\ttrt_fp16_end2end\tgpu_rss_mb\n" + "model_name\tort_run\tort_end2end\tgpu_mem\tpaddle_run\tpaddle_end2end\tgpu_mem\tpaddle_trt_run\tpaddle_trt_end2end\tgpu_mem\tpaddle_trt_fp16_run\tpaddle_trt_fp16_end2end\tgpu_mem\ttrt_run\ttrt_end2end\tgpu_mem\ttrt_fp16_run\ttrt_fp16_end2end\tgpu_mem\n" ) for model_name in model_name_set: lines1 = model_name + '\t' diff --git a/benchmark/run_benchmark_ppocr.sh b/benchmark/run_benchmark_ppocr.sh new file mode 100644 index 000000000..c9f24afd7 --- /dev/null +++ b/benchmark/run_benchmark_ppocr.sh @@ -0,0 +1,23 @@ +echo "[FastDeploy] Running PPOCR benchmark..." + +# for PPOCRv2 +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend ort --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend paddle --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend ov --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend ort --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle_trt --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle_trt --enable_trt_fp16 True --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend trt --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv2 --det_model ch_PP-OCRv2_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv2_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend trt --enable_trt_fp16 True --enable_collect_memory_info True + +# for PPOCRv3 +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend ort --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend paddle --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --cpu_num_thread 8 --iter_num 2000 --backend ov --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend ort --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle_trt --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend paddle_trt --enable_trt_fp16 True --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend trt --enable_collect_memory_info True +python benchmark_ppocr.py --model_dir ch_PP-OCRv3 --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image 12.jpg --device gpu --iter_num 2000 --backend trt --enable_trt_fp16 True --enable_collect_memory_info True diff --git a/cmake/fast_tokenizer.cmake b/cmake/fast_tokenizer.cmake index ba3849283..d8ab4d502 100644 --- a/cmake/fast_tokenizer.cmake +++ b/cmake/fast_tokenizer.cmake @@ -24,9 +24,16 @@ set(FASTTOKENIZER_INC_DIR "${FASTTOKENIZER_INSTALL_DIR}/include" "${FASTTOKENIZER_INSTALL_DIR}/third_party/include" CACHE PATH "fast_tokenizer include directory." FORCE) -set(FASTTOKENIZER_LIB_DIR - "${FASTTOKENIZER_INSTALL_DIR}/lib/" - CACHE PATH "fast_tokenizer lib directory." FORCE) +if(ANDROID) + set(FASTTOKENIZER_LIB_DIR + "${FASTTOKENIZER_INSTALL_DIR}/lib/${ANDROID_ABI}" + CACHE PATH "fast_tokenizer lib directory." FORCE) +else() + set(FASTTOKENIZER_LIB_DIR + "${FASTTOKENIZER_INSTALL_DIR}/lib/" + CACHE PATH "fast_tokenizer lib directory." FORCE) +endif() + set(FASTTOKENIZER_THIRD_LIB_DIR "${FASTTOKENIZER_INSTALL_DIR}/third_party/lib/" CACHE PATH "fast_tokenizer lib directory." FORCE) @@ -37,21 +44,21 @@ include_directories(${FASTTOKENIZER_INC_DIR}) # Set lib path if(WIN32) -set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/core_tokenizers.lib" - CACHE FILEPATH "fast_tokenizer compile library." FORCE) -message("FASTTOKENIZER_COMPILE_LIB = ${FASTTOKENIZER_COMPILE_LIB}") -set(ICUDT_LIB "${FASTTOKENIZER_THIRD_LIB_DIR}/icudt.lib") -set(ICUUC_LIB "${FASTTOKENIZER_THIRD_LIB_DIR}/icuuc.lib") - + set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/core_tokenizers.lib" + CACHE FILEPATH "fast_tokenizer compile library." FORCE) + set(ICUDT_LIB "${FASTTOKENIZER_THIRD_LIB_DIR}/icudt.lib") + set(ICUUC_LIB "${FASTTOKENIZER_THIRD_LIB_DIR}/icuuc.lib") elseif(APPLE) -set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/libcore_tokenizers.dylib" - CACHE FILEPATH "fast_tokenizer compile library." FORCE) + set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/libcore_tokenizers.dylib" + CACHE FILEPATH "fast_tokenizer compile library." FORCE) +elseif(ANDROID) + set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/libcore_tokenizers.so" + CACHE FILEPATH "fast_tokenizer compile library." FORCE) else() - -set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/libcore_tokenizers.so" - CACHE FILEPATH "fast_tokenizer compile library." FORCE) -message("FASTTOKENIZER_COMPILE_LIB = ${FASTTOKENIZER_COMPILE_LIB}") + set(FASTTOKENIZER_COMPILE_LIB "${FASTTOKENIZER_LIB_DIR}/libcore_tokenizers.so" + CACHE FILEPATH "fast_tokenizer compile library." FORCE) endif(WIN32) +message("FASTTOKENIZER_COMPILE_LIB = ${FASTTOKENIZER_COMPILE_LIB}") set(FASTTOKENIZER_URL_BASE "https://bj.bcebos.com/paddlenlp/fast_tokenizer/") set(FASTTOKENIZER_VERSION "1.0.0") @@ -68,6 +75,15 @@ elseif(APPLE) else() set(FASTTOKENIZER_FILE "fast_tokenizer-osx-x86_64-${FASTTOKENIZER_VERSION}.tgz") endif() +elseif(ANDROID) + # check ABI, toolchain + if((NOT ANDROID_ABI MATCHES "armeabi-v7a") AND (NOT ANDROID_ABI MATCHES "arm64-v8a")) + message(FATAL_ERROR "FastDeploy with FastTokenizer on Android only support armeabi-v7a, arm64-v8a now.") + endif() + if(NOT ANDROID_TOOLCHAIN MATCHES "clang") + message(FATAL_ERROR "Currently, only support clang toolchain while cross compiling FastDeploy for Android with FastTokenizer, but found ${ANDROID_TOOLCHAIN}.") + endif() + set(FASTTOKENIZER_FILE "fast_tokenizer-android-${ANDROID_ABI}-${FASTTOKENIZER_VERSION}.tgz") else() if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") set(FASTTOKENIZER_FILE "fast_tokenizer-linux-aarch64-${FASTTOKENIZER_VERSION}.tgz") @@ -77,18 +93,39 @@ else() endif() set(FASTTOKENIZER_URL "${FASTTOKENIZER_URL_BASE}${FASTTOKENIZER_FILE}") -ExternalProject_Add( - ${FASTTOKENIZER_PROJECT} - ${EXTERNAL_PROJECT_LOG_ARGS} - URL ${FASTTOKENIZER_URL} - PREFIX ${FASTTOKENIZER_PREFIX_DIR} - DOWNLOAD_NO_PROGRESS 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - UPDATE_COMMAND "" - INSTALL_COMMAND - ${CMAKE_COMMAND} -E copy_directory ${FASTTOKENIZER_SOURCE_DIR} ${FASTTOKENIZER_INSTALL_DIR} - BUILD_BYPRODUCTS ${FASTTOKENIZER_COMPILE_LIB}) +if(ANDROID) + ExternalProject_Add( + ${FASTTOKENIZER_PROJECT} + ${EXTERNAL_PROJECT_LOG_ARGS} + URL ${FASTTOKENIZER_URL} + PREFIX ${FASTTOKENIZER_PREFIX_DIR} + DOWNLOAD_NO_PROGRESS 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND + ${CMAKE_COMMAND} -E remove_directory ${FASTTOKENIZER_INSTALL_DIR} && + ${CMAKE_COMMAND} -E make_directory ${FASTTOKENIZER_INSTALL_DIR} && + ${CMAKE_COMMAND} -E make_directory ${FASTTOKENIZER_INSTALL_DIR}/lib && + ${CMAKE_COMMAND} -E make_directory ${FASTTOKENIZER_INSTALL_DIR}/third_party && + ${CMAKE_COMMAND} -E rename ${FASTTOKENIZER_SOURCE_DIR}/lib/ ${FASTTOKENIZER_INSTALL_DIR}/lib/${ANDROID_ABI} && + ${CMAKE_COMMAND} -E copy_directory ${FASTTOKENIZER_SOURCE_DIR}/include ${FASTTOKENIZER_INSTALL_DIR}/include && + ${CMAKE_COMMAND} -E copy_directory ${FASTTOKENIZER_SOURCE_DIR}/third_party/include ${FASTTOKENIZER_INSTALL_DIR}/third_party/include + BUILD_BYPRODUCTS ${FASTTOKENIZER_COMPILE_LIB}) +else() + ExternalProject_Add( + ${FASTTOKENIZER_PROJECT} + ${EXTERNAL_PROJECT_LOG_ARGS} + URL ${FASTTOKENIZER_URL} + PREFIX ${FASTTOKENIZER_PREFIX_DIR} + DOWNLOAD_NO_PROGRESS 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND + ${CMAKE_COMMAND} -E copy_directory ${FASTTOKENIZER_SOURCE_DIR} ${FASTTOKENIZER_INSTALL_DIR} + BUILD_BYPRODUCTS ${FASTTOKENIZER_COMPILE_LIB}) +endif() add_library(fast_tokenizer STATIC IMPORTED GLOBAL) set_property(TARGET fast_tokenizer PROPERTY IMPORTED_LOCATION ${FASTTOKENIZER_COMPILE_LIB}) diff --git a/cmake/opencv.cmake b/cmake/opencv.cmake index 912cf2917..87f8c8bcd 100755 --- a/cmake/opencv.cmake +++ b/cmake/opencv.cmake @@ -41,10 +41,12 @@ elseif(IOS) else() if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") set(OPENCV_FILENAME "opencv-linux-aarch64-3.4.14") - elseif(TARGET_ABI MATCHES "armhf") - set(OPENCV_FILENAME "opencv-armv7hf") else() - set(OPENCV_FILENAME "opencv-linux-x64-3.4.16") + if(ENABLE_TIMVX) + set(OPENCV_FILENAME "opencv-armv7hf") + else() + set(OPENCV_FILENAME "opencv-linux-x64-3.4.16") + endif() endif() if(ENABLE_OPENCV_CUDA) if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") @@ -57,7 +59,7 @@ endif() set(OPENCV_INSTALL_DIR ${THIRD_PARTY_PATH}/install/) if(ANDROID) set(OPENCV_URL_PREFIX "https://bj.bcebos.com/fastdeploy/third_libs") -elseif(TARGET_ABI MATCHES "armhf") +elseif(ENABLE_TIMVX) set(OPENCV_URL_PREFIX "https://bj.bcebos.com/fastdeploy/test") else() # TODO: use fastdeploy/third_libs instead. set(OPENCV_URL_PREFIX "https://bj.bcebos.com/paddle2onnx/libs") @@ -185,7 +187,7 @@ else() file(RENAME ${THIRD_PARTY_PATH}/install/${OPENCV_FILENAME}/ ${THIRD_PARTY_PATH}/install/opencv) set(OPENCV_FILENAME opencv) set(OpenCV_DIR ${THIRD_PARTY_PATH}/install/${OPENCV_FILENAME}) - if(TARGET_ABI MATCHES "armhf") + if(ENABLE_TIMVX) set(OpenCV_DIR ${OpenCV_DIR}/lib/cmake/opencv4) endif() if (WIN32) diff --git a/cmake/paddle2onnx.cmake b/cmake/paddle2onnx.cmake index ee5c46c55..baaac8759 100755 --- a/cmake/paddle2onnx.cmake +++ b/cmake/paddle2onnx.cmake @@ -43,7 +43,7 @@ else() endif(WIN32) set(PADDLE2ONNX_URL_BASE "https://bj.bcebos.com/fastdeploy/third_libs/") -set(PADDLE2ONNX_VERSION "1.0.4rc0") +set(PADDLE2ONNX_VERSION "1.0.5") if(WIN32) set(PADDLE2ONNX_FILE "paddle2onnx-win-x64-${PADDLE2ONNX_VERSION}.zip") if(NOT CMAKE_CL_64) diff --git a/cmake/paddle_inference.cmake b/cmake/paddle_inference.cmake index f1b5ee6c7..3ab45454a 100644 --- a/cmake/paddle_inference.cmake +++ b/cmake/paddle_inference.cmake @@ -13,6 +13,8 @@ # limitations under the License. include(ExternalProject) +option(PADDLEINFERENCE_DIRECTORY "Directory of Paddle Inference library" OFF) + set(PADDLEINFERENCE_PROJECT "extern_paddle_inference") set(PADDLEINFERENCE_PREFIX_DIR ${THIRD_PARTY_PATH}/paddle_inference) set(PADDLEINFERENCE_SOURCE_DIR @@ -27,6 +29,10 @@ set(PADDLEINFERENCE_LIB_DIR set(CMAKE_BUILD_RPATH "${CMAKE_BUILD_RPATH}" "${PADDLEINFERENCE_LIB_DIR}") +if(PADDLEINFERENCE_DIRECTORY) + set(PADDLEINFERENCE_INC_DIR ${PADDLEINFERENCE_DIRECTORY}/paddle/include) +endif() + include_directories(${PADDLEINFERENCE_INC_DIR}) if(WIN32) set(PADDLEINFERENCE_COMPILE_LIB @@ -47,50 +53,59 @@ else() endif(WIN32) -set(PADDLEINFERENCE_URL_BASE "https://bj.bcebos.com/fastdeploy/third_libs/") -set(PADDLEINFERENCE_VERSION "2.4-dev3") -if(WIN32) - if (WITH_GPU) - set(PADDLEINFERENCE_FILE "paddle_inference-win-x64-gpu-trt-${PADDLEINFERENCE_VERSION}.zip") - else() - set(PADDLEINFERENCE_FILE "paddle_inference-win-x64-${PADDLEINFERENCE_VERSION}.zip") - endif() -elseif(APPLE) - if(CURRENT_OSX_ARCH MATCHES "arm64") - message(FATAL_ERROR "Paddle Backend doesn't support Mac OSX with Arm64 now.") - set(PADDLEINFERENCE_FILE "paddle_inference-osx-arm64-${PADDLEINFERENCE_VERSION}.tgz") - else() - set(PADDLEINFERENCE_FILE "paddle_inference-osx-x86_64-${PADDLEINFERENCE_VERSION}.tgz") +if(PADDLEINFERENCE_DIRECTORY) + if(EXISTS "${THIRD_PARTY_PATH}/install/paddle_inference") + file(REMOVE_RECURSE "${THIRD_PARTY_PATH}/install/paddle_inference") endif() + find_package(Python COMPONENTS Interpreter Development REQUIRED) + message(STATUS "Copying ${PADDLEINFERENCE_DIRECTORY} to ${THIRD_PARTY_PATH}/install/paddle_inference ...") + execute_process(COMMAND ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/copy_directory.py ${PADDLEINFERENCE_DIRECTORY} ${THIRD_PARTY_PATH}/install/paddle_inference) else() - if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") - message(FATAL_ERROR "Paddle Backend doesn't support linux aarch64 now.") - set(PADDLEINFERENCE_FILE "paddle_inference-linux-aarch64-${PADDLEINFERENCE_VERSION}.tgz") - else() - set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-${PADDLEINFERENCE_VERSION}.tgz") - if(WITH_GPU) - set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-gpu-trt-${PADDLEINFERENCE_VERSION}.tgz") + set(PADDLEINFERENCE_URL_BASE "https://bj.bcebos.com/fastdeploy/third_libs/") + set(PADDLEINFERENCE_VERSION "2.4-dev3") + if(WIN32) + if (WITH_GPU) + set(PADDLEINFERENCE_FILE "paddle_inference-win-x64-gpu-trt-${PADDLEINFERENCE_VERSION}.zip") + else() + set(PADDLEINFERENCE_FILE "paddle_inference-win-x64-${PADDLEINFERENCE_VERSION}.zip") endif() - if (WITH_IPU) - set(PADDLEINFERENCE_VERSION "2.4-dev1") - set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-ipu-${PADDLEINFERENCE_VERSION}.tgz") + elseif(APPLE) + if(CURRENT_OSX_ARCH MATCHES "arm64") + message(FATAL_ERROR "Paddle Backend doesn't support Mac OSX with Arm64 now.") + set(PADDLEINFERENCE_FILE "paddle_inference-osx-arm64-${PADDLEINFERENCE_VERSION}.tgz") + else() + set(PADDLEINFERENCE_FILE "paddle_inference-osx-x86_64-${PADDLEINFERENCE_VERSION}.tgz") + endif() + else() + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") + message(FATAL_ERROR "Paddle Backend doesn't support linux aarch64 now.") + set(PADDLEINFERENCE_FILE "paddle_inference-linux-aarch64-${PADDLEINFERENCE_VERSION}.tgz") + else() + set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-${PADDLEINFERENCE_VERSION}.tgz") + if(WITH_GPU) + set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-gpu-trt-${PADDLEINFERENCE_VERSION}.tgz") + endif() + if (WITH_IPU) + set(PADDLEINFERENCE_VERSION "2.4-dev1") + set(PADDLEINFERENCE_FILE "paddle_inference-linux-x64-ipu-${PADDLEINFERENCE_VERSION}.tgz") + endif() endif() endif() -endif() -set(PADDLEINFERENCE_URL "${PADDLEINFERENCE_URL_BASE}${PADDLEINFERENCE_FILE}") - -ExternalProject_Add( - ${PADDLEINFERENCE_PROJECT} - ${EXTERNAL_PROJECT_LOG_ARGS} - URL ${PADDLEINFERENCE_URL} - PREFIX ${PADDLEINFERENCE_PREFIX_DIR} - DOWNLOAD_NO_PROGRESS 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - UPDATE_COMMAND "" - INSTALL_COMMAND - ${CMAKE_COMMAND} -E copy_directory ${PADDLEINFERENCE_SOURCE_DIR} ${PADDLEINFERENCE_INSTALL_DIR} - BUILD_BYPRODUCTS ${PADDLEINFERENCE_COMPILE_LIB}) + set(PADDLEINFERENCE_URL "${PADDLEINFERENCE_URL_BASE}${PADDLEINFERENCE_FILE}") + + ExternalProject_Add( + ${PADDLEINFERENCE_PROJECT} + ${EXTERNAL_PROJECT_LOG_ARGS} + URL ${PADDLEINFERENCE_URL} + PREFIX ${PADDLEINFERENCE_PREFIX_DIR} + DOWNLOAD_NO_PROGRESS 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND + ${CMAKE_COMMAND} -E copy_directory ${PADDLEINFERENCE_SOURCE_DIR} ${PADDLEINFERENCE_INSTALL_DIR} + BUILD_BYPRODUCTS ${PADDLEINFERENCE_COMPILE_LIB}) +endif(PADDLEINFERENCE_DIRECTORY) if(UNIX AND (NOT APPLE) AND (NOT ANDROID)) add_custom_target(patchelf_paddle_inference ALL COMMAND bash -c "PATCHELF_EXE=${PATCHELF_EXE} python ${PROJECT_SOURCE_DIR}/scripts/patch_paddle_inference.py ${PADDLEINFERENCE_INSTALL_DIR}/paddle/lib/libpaddle_inference.so" DEPENDS ${LIBRARY_NAME}) diff --git a/cmake/paddlelite.cmake b/cmake/paddlelite.cmake index d86ccf2d1..bcc0eb470 100755 --- a/cmake/paddlelite.cmake +++ b/cmake/paddlelite.cmake @@ -52,17 +52,19 @@ endif() if(WIN32 OR APPLE OR IOS) message(FATAL_ERROR "Doesn't support windows/mac/ios platform with backend Paddle Lite now.") elseif(ANDROID) - set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-android-${ANDROID_ABI}-latest.tgz") + set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-android-${ANDROID_ABI}-latest-dev.tgz") if(ANDROID_ABI MATCHES "arm64-v8a") - set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-android-${ANDROID_ABI}-fp16-latest.tgz") + set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-android-${ANDROID_ABI}-fp16-latest-dev.tgz") endif() else() # Linux if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") - set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-linux-arm64-20220920.tgz") - elseif(TARGET_ABI MATCHES "armhf") - set(PADDLELITE_URL "https://bj.bcebos.com/fastdeploy/test/lite-linux_armhf_1101.tgz") + set(PADDLELITE_URL "${PADDLELITE_URL_PREFIX}/lite-linux-arm64-20221209.tgz") else() - message(FATAL_ERROR "Only support Linux aarch64 now, x64 is not supported with backend Paddle Lite.") + if(ENABLE_TIMVX) + set(PADDLELITE_URL "https://bj.bcebos.com/fastdeploy/test/lite-linux_armhf_1130.tgz") + else() + message(FATAL_ERROR "Only support Linux aarch64 or ENABLE_TIMVX now, x64 is not supported with backend Paddle Lite.") + endif() endif() endif() diff --git a/cmake/timvx.cmake b/cmake/timvx.cmake index 153f0de19..c6a7d54d2 100755 --- a/cmake/timvx.cmake +++ b/cmake/timvx.cmake @@ -1,11 +1,10 @@ -if (NOT DEFINED TARGET_ABI) +if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_C_COMPILER "arm-linux-gnueabihf-gcc") set(CMAKE_CXX_COMPILER "arm-linux-gnueabihf-g++") set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_C_FLAGS}" ) - set(TARGET_ABI armhf) set(CMAKE_BUILD_TYPE MinSizeRel) else() if(NOT ${ENABLE_LITE_BACKEND}) diff --git a/docs/README_CN.md b/docs/README_CN.md index 43e6e3059..5fb8b2127 100644 --- a/docs/README_CN.md +++ b/docs/README_CN.md @@ -10,6 +10,7 @@ - [IPU部署环境编译安装](cn/build_and_install/ipu.md) - [Jetson部署环境编译安装](cn/build_and_install/jetson.md) - [Android平台部署环境编译安装](cn/build_and_install/android.md) +- [服务化部署镜像编译安装](../serving/docs/zh_CN/compile.md) ## 快速使用 @@ -22,6 +23,7 @@ - [Python API文档](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/python/html/) - [C++ API文档](https://www.paddlepaddle.org.cn/fastdeploy-api-doc/cpp/html/) +- [Android Java API文档](../java/android) ## 性能调优 @@ -31,9 +33,9 @@ - [1. 如何配置模型部署的推理后端](cn/faq/how_to_change_backend.md) - [2. Windows上C++ SDK如何使用](cn/faq/use_sdk_on_windows.md) -- [3. Android上如何使用FastDeploy](cn/faq/use_sdk_on_android.md)(进行中) +- [3. Android上如何使用FastDeploy C++ SDK](cn/faq/use_cpp_sdk_on_android.md) - [4. TensorRT使用中的一些技巧](cn/faq/tensorrt_tricks.md) -- [5. 如何增加新的模型](cn/faq/develop_a_new_model.md)(进行中) +- [5. 如何增加新的模型](cn/faq/develop_a_new_model.md) ## 更多FastDeploy部署模块 diff --git a/docs/README_EN.md b/docs/README_EN.md index e995e3024..c4f9adfa3 100644 --- a/docs/README_EN.md +++ b/docs/README_EN.md @@ -4,12 +4,13 @@ ## Install -- [How to Install FastDeploy Prebuilt Libraries](en/build_and_install/download_prebuilt_libraries.md) -- [How to Build and Install FastDeploy Library on GPU Platform](en/build_and_install/gpu.md) -- [How to Build and Install FastDeploy Library on CPU Platform](en/build_and_install/cpu.md) -- [How to Build and Install FastDeploy Library on IPU Platform](en/build_and_install/ipu.md) -- [How to Build and Install FastDeploy Library on Nvidia Jetson Platform](en/build_and_install/jetson.md) -- [How to Build and Install FastDeploy Library on Android Platform](en/build_and_install/android.md) +- [Install FastDeploy Prebuilt Libraries](en/build_and_install/download_prebuilt_libraries.md) +- [Build and Install FastDeploy Library on GPU Platform](en/build_and_install/gpu.md) +- [Build and Install FastDeploy Library on CPU Platform](en/build_and_install/cpu.md) +- [Build and Install FastDeploy Library on IPU Platform](en/build_and_install/ipu.md) +- [Build and Install FastDeploy Library on Nvidia Jetson Platform](en/build_and_install/jetson.md) +- [Build and Install FastDeploy Library on Android Platform](en/build_and_install/android.md) +- [Build and Install FastDeploy Serving Deployment Image](../serving/docs/EN/compile-en.md) ## A Quick Start - Demos @@ -21,7 +22,8 @@ ## API - [Python API](https://baidu-paddle.github.io/fastdeploy-api/python/html/) -- [C++ API](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/) +- [C++ API](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/) +- [Android Java API](../java/android) ## Performance Optimization @@ -31,11 +33,11 @@ - [1. How to Change Inference Backends](en/faq/how_to_change_backend.md) - [2. How to Use FastDeploy C++ SDK on Windows Platform](en/faq/use_sdk_on_windows.md) -- [3. How to Use FastDeploy C++ SDK on Android Platform](en/faq/use_sdk_on_android.md) +- [3. How to Use FastDeploy C++ SDK on Android Platform](en/faq/use_cpp_sdk_on_android.md) - [4. Tricks of TensorRT](en/faq/tensorrt_tricks.md) - [5. How to Develop a New Model](en/faq/develop_a_new_model.md) ## More FastDeploy Deployment Module -- [deployment AI Model as a Service](../serving) +- [Deployment AI Model as a Service](../serving) - [Benchmark Testing](../benchmark) diff --git a/docs/api_docs/cpp/Doxyfile b/docs/api_docs/cpp/Doxyfile index 4bd48f09d..afd956162 100644 --- a/docs/api_docs/cpp/Doxyfile +++ b/docs/api_docs/cpp/Doxyfile @@ -2100,7 +2100,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = protected=private +PREDEFINED = protected=private ENABLE_VISION_VISUALIZE=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/docs/api_docs/cpp/main_page.md b/docs/api_docs/cpp/main_page.md index 585e6d428..fef288971 100644 --- a/docs/api_docs/cpp/main_page.md +++ b/docs/api_docs/cpp/main_page.md @@ -1,31 +1,7 @@ # FastDeploy C++ API Summary -## Runtime - -FastDeploy Runtime can be used as an inference engine with the same code, we can deploy Paddle/ONNX model on different device by different backends. -Currently, FastDeploy supported backends listed as below, - -| Backend | Hardware | Support Model Format | Platform | -| :------ | :------- | :------------------- | :------- | -| Paddle Inference | CPU/Nvidia GPU | Paddle | Windows(x64)/Linux(x64) | -| ONNX Runtime | CPU/Nvidia GPU | Paddle/ONNX | Windows(x64)/Linux(x64/aarch64)/Mac(x86/arm64) | -| TensorRT | Nvidia GPU | Paddle/ONNX | Windows(x64)/Linux(x64)/Jetson | -| OpenVINO | CPU | Paddle/ONNX | Windows(x64)/Linux(x64)/Mac(x86) | -| Poros | CPU/Nvidia GPU | TorchScript | Linux(x64) | - -### Example code -- [Python examples](./) -- [C++ examples](./) - -### Related APIs -- [RuntimeOption](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/structfastdeploy_1_1RuntimeOption.html) -- [Runtime](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/structfastdeploy_1_1Runtime.html) - -## Vision Models - -| Task | Model | API | Example | -| :---- | :---- | :---- | :----- | -| object detection | PaddleDetection/PPYOLOE | [fastdeploy::vision::detection::PPYOLOE](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/classfastdeploy_1_1vision_1_1detection_1_1PPYOLOE.html) | [C++](./)/[Python](./) | -| keypoint detection | PaddleDetection/PPTinyPose | [fastdeploy::vision::keypointdetection::PPTinyPose](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/classfastdeploy_1_1pipeline_1_1PPTinyPose.html) | [C++](./)/[Python](./) | -| image classification | PaddleClassification serials | [fastdeploy::vision::classification::PaddleClasModel](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/classfastdeploy_1_1vision_1_1classification_1_1PaddleClasModel.html) | [C++](./)/[Python](./) | -| semantic segmentation | PaddleSegmentation serials | [fastdeploy::vision::classification::PaddleSegModel](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/classfastdeploy_1_1vision_1_1segmentation_1_1PaddleSegModel.html) | [C++](./)/[Python](./) | +- Github: [https://github.com/PaddlePaddle/FastDeploy](https://github.com/PaddlePaddle/FastDeploy) +- [Installation](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/en/build_and_install) +- [Usage Documents](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/README_EN.md) +- [Release Notes](https://github.com/PaddlePaddle/FastDeploy/releases) +- [Examples](https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples) diff --git a/docs/api_docs/python/semantic_segmentation.md b/docs/api_docs/python/semantic_segmentation.md index 6d224e085..7a0eb6ca9 100644 --- a/docs/api_docs/python/semantic_segmentation.md +++ b/docs/api_docs/python/semantic_segmentation.md @@ -1,5 +1,14 @@ # Semantic Segmentation(语义分割) + +## fastdeploy.vision.segmentation.PaddleSegPreprocessor + +```{eval-rst} +.. autoclass:: fastdeploy.vision.segmentation.PaddleSegPreprocessor + :members: + :inherited-members: +``` + ## fastdeploy.vision.segmentation.PaddleSegModel ```{eval-rst} @@ -7,3 +16,11 @@ :members: :inherited-members: ``` + +## fastdeploy.vision.segmentation.PaddleSegPostprocessor + +```{eval-rst} +.. autoclass:: fastdeploy.vision.segmentation.PaddleSegPostprocessor + :members: + :inherited-members: +``` diff --git a/docs/api_docs/python/visualize.md b/docs/api_docs/python/visualize.md new file mode 100644 index 000000000..2170eb453 --- /dev/null +++ b/docs/api_docs/python/visualize.md @@ -0,0 +1,57 @@ +# Visaulize(可视化) + +## fastdeploy.vision.vis_detection + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_detection + :members: + :inherited-members: +``` + +## fastdeploy.vision.vis_segmentation + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_segmentation + :members: + :inherited-members: +``` + +## fastdeploy.vision.vis_keypoint_detection + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_keypoint_detection + :members: + :inherited-members: +``` +## fastdeploy.vision.vis_face_detection + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_face_detection + :members: + :inherited-members: +``` + + +## fastdeploy.vision.vis_face_alignment + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_face_alignment + :members: + :inherited-members: +``` + +## fastdeploy.vision.vis_matting + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_matting + :members: + :inherited-members: +``` + +## fastdeploy.vision.vis_ppocr + +```{eval-rst} +.. autoclass:: fastdeploy.vision.vis_ppocr + :members: + :inherited-members: +``` diff --git a/docs/cn/build_and_install/README.md b/docs/cn/build_and_install/README.md index a40d571f5..8be1f745a 100755 --- a/docs/cn/build_and_install/README.md +++ b/docs/cn/build_and_install/README.md @@ -8,10 +8,10 @@ ## 自行编译安装 - [GPU部署环境](gpu.md) - [CPU部署环境](cpu.md) -- [CPU部署环境](ipu.md) +- [IPU部署环境](ipu.md) - [Jetson部署环境](jetson.md) - [Android平台部署环境](android.md) -- [瑞芯微RK1126部署环境](rk1126.md) +- [瑞芯微RV1126部署环境](rv1126.md) ## FastDeploy编译选项说明 @@ -22,6 +22,7 @@ | ENABLE_PADDLE_BACKEND | 默认OFF,是否编译集成Paddle Inference后端(CPU/GPU上推荐打开) | | ENABLE_LITE_BACKEND | 默认OFF,是否编译集成Paddle Lite后端(编译Android库时需要设置为ON) | | ENABLE_RKNPU2_BACKEND | 默认OFF,是否编译集成RKNPU2后端(RK3588/RK3568/RK3566上推荐打开) | +| ENABLE_TIMVX | 默认OFF,需要在RV1126/RV1109上部署时,需设置为ON | | ENABLE_TRT_BACKEND | 默认OFF,是否编译集成TensorRT后端(GPU上推荐打开) | | ENABLE_OPENVINO_BACKEND | 默认OFF,是否编译集成OpenVINO后端(CPU上推荐打开) | | ENABLE_VISION | 默认OFF,是否编译集成视觉模型的部署模块 | diff --git a/docs/cn/build_and_install/cpu.md b/docs/cn/build_and_install/cpu.md index c6fb2a893..b0057e677 100644 --- a/docs/cn/build_and_install/cpu.md +++ b/docs/cn/build_and_install/cpu.md @@ -27,6 +27,11 @@ Linux上编译需满足 - gcc/g++ >= 5.4(推荐8.2) - cmake >= 3.18.0 +此外更推荐开发者自行安装,编译时通过`-DOPENCV_DIRECTORY`来指定环境中的OpenCV(如若不指定-DOPENCV_DIRECTORY,会自动下载FastDeploy提供的预编译的OpenCV,但在**Linux平台**无法支持Video的读取,以及imshow等可视化界面功能) +``` +sudo apt-get install libopencv-dev +``` + ```bash git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy @@ -36,6 +41,7 @@ cmake .. -DENABLE_ORT_BACKEND=ON \ -DENABLE_OPENVINO_BACKEND=ON \ -DCMAKE_INSTALL_PREFIX=${PWD}/compiled_fastdeploy_sdk \ -DENABLE_VISION=ON \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 \ -DENABLE_TEXT=ON make -j12 make install @@ -90,6 +96,8 @@ export ENABLE_PADDLE_BACKEND=ON export ENABLE_OPENVINO_BACKEND=ON export ENABLE_VISION=ON export ENABLE_TEXT=ON +# OPENCV_DIRECTORY可选,不指定会自动下载FastDeploy提供的预编译OpenCV库 +export OPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 python setup.py build python setup.py bdist_wheel diff --git a/docs/cn/build_and_install/download_prebuilt_libraries.md b/docs/cn/build_and_install/download_prebuilt_libraries.md index 87ee4aa7e..1a2c4f94e 100755 --- a/docs/cn/build_and_install/download_prebuilt_libraries.md +++ b/docs/cn/build_and_install/download_prebuilt_libraries.md @@ -20,7 +20,7 @@ FastDeploy提供各平台预编译库,供开发者直接下载安装使用。 ### Python安装 -Release版本(当前最新0.8.0)安装 +Release版本(当前最新1.0.1)安装 ```bash pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html ``` @@ -41,8 +41,8 @@ Release版本 | 平台 | 文件 | 说明 | | :--- | :--- | :---- | -| Linux x64 | [fastdeploy-linux-x64-gpu-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-gpu-0.8.0.tgz) | g++ 8.2, CUDA 11.2, cuDNN 8.2编译产出 | -| Windows x64 | [fastdeploy-win-x64-gpu-0.8.0.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-gpu-0.8.0.zip) | Visual Studio 16 2019, CUDA 11.2, cuDNN 8.2编译产出 | +| Linux x64 | [fastdeploy-linux-x64-gpu-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-gpu-1.0.1.tgz) | g++ 8.2, CUDA 11.2, cuDNN 8.2编译产出 | +| Windows x64 | [fastdeploy-win-x64-gpu-1.0.1.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-gpu-1.0.1.zip) | Visual Studio 16 2019, CUDA 11.2, cuDNN 8.2编译产出 | Develop版本(Nightly build) @@ -63,7 +63,7 @@ Develop版本(Nightly build) ### Python安装 -Release版本(当前最新0.7.0)安装 +Release版本(当前最新1.0.1)安装 ```bash pip install fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html ``` @@ -79,16 +79,16 @@ Release版本 | 平台 | 文件 | 说明 | | :--- | :--- | :---- | -| Linux x64 | [fastdeploy-linux-x64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-0.8.0.tgz) | g++ 8.2编译产出 | -| Windows x64 | [fastdeploy-win-x64-0.8.0.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-0.8.0.zip) | Visual Studio 16 2019编译产出 | -| Mac OSX x64 | [fastdeploy-osx-x86_64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-x86_64-0.8.0.tgz) | clang++ 10.0.0编译产出| -| Mac OSX arm64 | [fastdeploy-osx-arm64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-arm64-0.8.0.tgz) | clang++ 13.0.0编译产出 | -| Linux aarch64 | - | 自行编译,可集成ONNX Runtime、Paddle Lite后端 | +| Linux x64 | [fastdeploy-linux-x64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-1.0.1.tgz) | g++ 8.2编译产出 | +| Windows x64 | [fastdeploy-win-x64-1.0.1.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-1.0.1.zip) | Visual Studio 16 2019编译产出 | +| Mac OSX x64 | [fastdeploy-osx-x86_64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-x86_64-1.0.1.tgz) | clang++ 10.0.0编译产出| +| Mac OSX arm64 | [fastdeploy-osx-arm64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-arm64-1.0.1.tgz) | clang++ 13.0.0编译产出 | +| Linux aarch64 | [fastdeploy-osx-arm64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-aarch64-1.0.1.tgz) | gcc 6.3编译产出 | | Android armv7&v8 | [fastdeploy-android-1.0.0-shared.tgz](https://bj.bcebos.com/fastdeploy/release/android/fastdeploy-android-1.0.0-shared.tgz) | NDK 25及clang++编译产出, 支持arm64-v8a及armeabi-v7a | ## Java SDK安装 -Release版本(Java SDK 目前仅支持Android,版本为1.0.0 pre-release) +Release版本(Java SDK 目前仅支持Android,版本为1.0.0) | 平台 | 文件 | 说明 | | :--- | :--- | :---- | diff --git a/docs/cn/build_and_install/gpu.md b/docs/cn/build_and_install/gpu.md index 3d6aba116..1e9a0d26f 100644 --- a/docs/cn/build_and_install/gpu.md +++ b/docs/cn/build_and_install/gpu.md @@ -33,6 +33,11 @@ Linux上编译需满足 - cuda >= 11.2 - cudnn >= 8.2 +此外更推荐开发者自行安装,编译时通过`-DOPENCV_DIRECTORY`来指定环境中的OpenCV(如若不指定-DOPENCV_DIRECTORY,会自动下载FastDeploy提供的预编译的OpenCV,但在**Linux平台**无法支持Video的读取,以及imshow等可视化界面功能) +``` +sudo apt-get install libopencv-dev +``` + ```bash git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy @@ -46,6 +51,7 @@ cmake .. -DENABLE_ORT_BACKEND=ON \ -DCUDA_DIRECTORY=/usr/local/cuda \ -DCMAKE_INSTALL_PREFIX=${PWD}/compiled_fastdeploy_sdk \ -DENABLE_VISION=ON \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 \ -DENABLE_TEXT=ON make -j12 make install @@ -115,6 +121,8 @@ export ENABLE_TRT_BACKEND=ON export WITH_GPU=ON export TRT_DIRECTORY=/Paddle/TensorRT-8.4.1.5 export CUDA_DIRECTORY=/usr/local/cuda +# OPENCV_DIRECTORY可选,不指定会在编译过程下载FastDeploy预编译的OpenCV库 +export OPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 \ python setup.py build python setup.py bdist_wheel diff --git a/docs/cn/build_and_install/jetson.md b/docs/cn/build_and_install/jetson.md index f60aa280c..97ab59083 100644 --- a/docs/cn/build_and_install/jetson.md +++ b/docs/cn/build_and_install/jetson.md @@ -1,7 +1,7 @@ # Jetson部署库编译 -FastDeploy当前在Jetson仅支持ONNX Runtime CPU和TensorRT GPU两种后端推理 +FastDeploy当前在Jetson仅支持ONNX Runtime CPU和TensorRT GPU/Paddle Inference两种后端推理 ## C++ SDK编译安装 @@ -10,12 +10,17 @@ FastDeploy当前在Jetson仅支持ONNX Runtime CPU和TensorRT GPU两种后端推 - cmake >= 3.10.0 - jetpack >= 4.6.1 + +如果需要集成Paddle Inference后端,在[Paddle Inference预编译库](https://www.paddlepaddle.org.cn/inference/v2.4/guides/install/download_lib.html#c)页面根据开发环境选择对应的Jetpack C++包下载,并解压。 + ```bash git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy mkdir build && cd build cmake .. -DBUILD_ON_JETSON=ON \ -DENABLE_VISION=ON \ + -DENABLE_PADDLE_BACKEND=ON \ # 可选项,如若不需要Paddle Inference后端,可关闭 + -DPADDLEINFERENCE_DIRECTORY=/Download/paddle_inference_jetson \ -DCMAKE_INSTALL_PREFIX=${PWD}/installed_fastdeploy make -j8 make install @@ -34,6 +39,8 @@ make install Python打包依赖`wheel`,编译前请先执行`pip install wheel` +如果需要集成Paddle Inference后端,在[Paddle Inference预编译库](https://www.paddlepaddle.org.cn/inference/v2.4/guides/install/download_lib.html#c)页面根据开发环境选择对应的Jetpack C++包下载,并解压。 + 所有编译选项通过环境变量导入 ```bash @@ -42,6 +49,10 @@ cd FastDeploy/python export BUILD_ON_JETSON=ON export ENABLE_VISION=ON +# ENABLE_PADDLE_BACKEND & PADDLEINFERENCE_DIRECTORY为可选项 +export ENABLE_PADDLE_BACKEND=ON +export PADDLEINFERENCE_DIRECTORY=/Download/paddle_inference_jetson + python setup.py build python setup.py bdist_wheel ``` diff --git a/docs/cn/build_and_install/rk1126.md b/docs/cn/build_and_install/rk1126.md deleted file mode 100755 index 4eda01981..000000000 --- a/docs/cn/build_and_install/rk1126.md +++ /dev/null @@ -1,63 +0,0 @@ -# 瑞芯微 RK1126 部署环境编译安装 - -FastDeploy基于 Paddle-Lite 后端支持在瑞芯微(Rockchip)Soc 上进行部署推理。 -更多详细的信息请参考:[PaddleLite部署示例](https://paddle-lite.readthedocs.io/zh/develop/demo_guides/verisilicon_timvx.html)。 - -本文档介绍如何编译基于 PaddleLite 的 C++ FastDeploy 交叉编译库。 - -相关编译选项说明如下: -|编译选项|默认值|说明|备注| -|:---|:---|:---|:---| -|ENABLE_LITE_BACKEND|OFF|编译RK库时需要设置为ON| - | - -更多编译选项请参考[FastDeploy编译选项说明](./README.md) - -## 交叉编译环境搭建 - -### 宿主机环境需求 -- os:Ubuntu == 16.04 -- cmake: version >= 3.10.0 - -### 环境搭建 -```bash - # 1. Install basic software -apt update -apt-get install -y --no-install-recommends \ - gcc g++ git make wget python unzip - -# 2. Install arm gcc toolchains -apt-get install -y --no-install-recommends \ - g++-arm-linux-gnueabi gcc-arm-linux-gnueabi \ - g++-arm-linux-gnueabihf gcc-arm-linux-gnueabihf \ - gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - -# 3. Install cmake 3.10 or above -wget -c https://mms-res.cdn.bcebos.com/cmake-3.10.3-Linux-x86_64.tar.gz && \ - tar xzf cmake-3.10.3-Linux-x86_64.tar.gz && \ - mv cmake-3.10.3-Linux-x86_64 /opt/cmake-3.10 && \ - ln -s /opt/cmake-3.10/bin/cmake /usr/bin/cmake && \ - ln -s /opt/cmake-3.10/bin/ccmake /usr/bin/ccmake -``` - -## 基于 PaddleLite 的 FastDeploy 交叉编译库编译 -搭建好交叉编译环境之后,编译命令如下: -```bash -# Download the latest source code -git clone https://github.com/PaddlePaddle/FastDeploy.git -cd FastDeploy -mkdir build && cd build - -# CMake configuration with RK toolchain -cmake -DCMAKE_TOOLCHAIN_FILE=./../cmake/timvx.cmake \ - -DENABLE_TIMVX=ON \ - -DCMAKE_INSTALL_PREFIX=fastdeploy-tmivx \ - -DENABLE_VISION=ON \ # 是否编译集成视觉模型的部署模块,可选择开启 - -Wno-dev .. - -# Build FastDeploy RK1126 C++ SDK -make -j8 -make install -``` -编译完成之后,会生成 fastdeploy-tmivx 目录,表示基于 PadddleLite TIM-VX 的 FastDeploy 库编译完成。 - -RK1126 上部署 PaddleClas 分类模型请参考:[PaddleClas RK1126开发板 C++ 部署示例](../../../examples/vision/classification/paddleclas/rk1126/README.md) diff --git a/docs/cn/build_and_install/rv1126.md b/docs/cn/build_and_install/rv1126.md new file mode 100755 index 000000000..f3cd4ed6a --- /dev/null +++ b/docs/cn/build_and_install/rv1126.md @@ -0,0 +1,100 @@ +# 瑞芯微 RV1126 部署环境编译安装 + +FastDeploy基于 Paddle-Lite 后端支持在瑞芯微(Rockchip)Soc 上进行部署推理。 +更多详细的信息请参考:[PaddleLite部署示例](https://www.paddlepaddle.org.cn/lite/develop/demo_guides/verisilicon_timvx.html)。 + +本文档介绍如何编译基于 PaddleLite 的 C++ FastDeploy 交叉编译库。 + +相关编译选项说明如下: +|编译选项|默认值|说明|备注| +|:---|:---|:---|:---| +|ENABLE_LITE_BACKEND|OFF|编译RK库时需要设置为ON| - | +|ENABLE_TIMVX|OFF|编译RK库时需要设置为ON| - | + +更多编译选项请参考[FastDeploy编译选项说明](./README.md) + +## 交叉编译环境搭建 + +### 宿主机环境需求 +- os:Ubuntu == 16.04 +- cmake: version >= 3.10.0 + +### 环境搭建 +```bash + # 1. Install basic software +apt update +apt-get install -y --no-install-recommends \ + gcc g++ git make wget python unzip + +# 2. Install arm gcc toolchains +apt-get install -y --no-install-recommends \ + g++-arm-linux-gnueabi gcc-arm-linux-gnueabi \ + g++-arm-linux-gnueabihf gcc-arm-linux-gnueabihf \ + gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + +# 3. Install cmake 3.10 or above +wget -c https://mms-res.cdn.bcebos.com/cmake-3.10.3-Linux-x86_64.tar.gz && \ + tar xzf cmake-3.10.3-Linux-x86_64.tar.gz && \ + mv cmake-3.10.3-Linux-x86_64 /opt/cmake-3.10 && \ + ln -s /opt/cmake-3.10/bin/cmake /usr/bin/cmake && \ + ln -s /opt/cmake-3.10/bin/ccmake /usr/bin/ccmake +``` + +## 基于 PaddleLite 的 FastDeploy 交叉编译库编译 +搭建好交叉编译环境之后,编译命令如下: +```bash +# Download the latest source code +git clone https://github.com/PaddlePaddle/FastDeploy.git +cd FastDeploy +mkdir build && cd build + +# CMake configuration with RK toolchain +cmake -DCMAKE_TOOLCHAIN_FILE=./../cmake/timvx.cmake \ + -DENABLE_TIMVX=ON \ + -DCMAKE_INSTALL_PREFIX=fastdeploy-tmivx \ + -DENABLE_VISION=ON \ # 是否编译集成视觉模型的部署模块,可选择开启 + -Wno-dev .. + +# Build FastDeploy RV1126 C++ SDK +make -j8 +make install +``` +编译完成之后,会生成 fastdeploy-tmivx 目录,表示基于 PadddleLite TIM-VX 的 FastDeploy 库编译完成。 + +## 准备设备运行环境 +部署前要保证芯原 Linux Kernel NPU 驱动 galcore.so 版本及所适用的芯片型号与依赖库保持一致,在部署前,请登录开发板,并通过命令行输入以下命令查询 NPU 驱动版本,Rockchip建议的驱动版本为: 6.4.6.5 +```bash +dmesg | grep Galcore +``` + +如果当前版本不符合上述,请用户仔细阅读以下内容,以保证底层 NPU 驱动环境正确。 + +有两种方式可以修改当前的 NPU 驱动版本: +1. 手动替换 NPU 驱动版本。(推荐) +2. 刷机,刷取 NPU 驱动版本符合要求的固件。 + +### 手动替换 NPU 驱动版本 +1. 使用如下命令下载解压 PaddleLite demo,其中提供了现成的驱动文件 +```bash +wget https://paddlelite-demo.bj.bcebos.com/devices/generic/PaddleLite-generic-demo.tar.gz +tar -xf PaddleLite-generic-demo.tar.gz +``` +2. 使用 `uname -a` 查看 `Linux Kernel` 版本,确定为 `Linux` 系统 4.19.111 版本, +3. 将 `PaddleLite-generic-demo/libs/PaddleLite/linux/armhf/lib/verisilicon_timvx/viv_sdk_6_4_6_5/lib/1126/4.19.111/` 路径下的 `galcore.ko` 上传至开发板。 + +4. 登录开发板,命令行输入 `sudo rmmod galcore` 来卸载原始驱动,输入 `sudo insmod galcore.ko` 来加载传上设备的驱动。(是否需要 sudo 根据开发板实际情况,部分 adb 链接的设备请提前 adb root)。此步骤如果操作失败,请跳转至方法 2。 +5. 在开发板中输入 `dmesg | grep Galcore` 查询 NPU 驱动版本,确定为:6.4.6.5 + +### 刷机 +根据具体的开发板型号,向开发板卖家或官网客服索要 6.4.6.5 版本 NPU 驱动对应的固件和刷机方法。 + +更多细节请参考:[PaddleLite准备设备环境](https://www.paddlepaddle.org.cn/lite/develop/demo_guides/verisilicon_timvx.html#zhunbeishebeihuanjing) + +## 基于 FastDeploy 在 RV1126 上的部署示例 +1. RV1126 上部署 PaddleClas 分类模型请参考:[PaddleClas 分类模型在 RV1126 上的 C++ 部署示例](../../../examples/vision/classification/paddleclas/rv1126/README.md) + +2. RV1126 上部署 PPYOLOE 检测模型请参考:[PPYOLOE 检测模型在 RV1126 上的 C++ 部署示例](../../../examples/vision/detection/paddledetection/rv1126/README.md) + +3. RV1126 上部署 YOLOv5 检测模型请参考:[YOLOv5 检测模型在 RV1126 上的 C++ 部署示例](../../../examples/vision/detection/yolov5/rv1126/README.md) + +4. RV1126 上部署 PP-LiteSeg 分割模型请参考:[PP-LiteSeg 分割模型在 RV1126 上的 C++ 部署示例](../../../examples/vision/segmentation/paddleseg/rv1126/README.md) diff --git a/docs/cn/faq/custom_opencv.md b/docs/cn/faq/custom_opencv.md new file mode 100644 index 000000000..2f697a0a1 --- /dev/null +++ b/docs/cn/faq/custom_opencv.md @@ -0,0 +1,35 @@ +[English](../../en/faq/custom_opencv.md) | 中文 + +# 自定义OpenCV版本 + +受限于不同平台限制,目前FastDeploy提供的预编译包在**Linux平台**内置的OpenCV无法读取视频,或调用`imshow`等操作。对于有这类需求的开发者,可根据本文档来自行编译FastDeploy。 + +FastDeploy目前支持通过`-DOPENCV_DIRECTORY`来指定环境中的OpenCV版本,以Ubuntu为例,我们可以按照如下方式编译安装。 + + +## CPU C++ SDK + +### 1. 安装Opencv +``` +sudo apt-get install libopencv-dev +``` + +### 2. 指定OpenCV编译FastDeploy +``` +git clone https://github.com/PaddlePaddle/FastDeploy +cd FastDeploy +mkdir build && cd build +cmake .. -DENABLE_ORT_BACKEND=ON \ + -DENABLE_PADDLE_BACKEND=ON \ + -DENABLE_OPENVINO_BACKEND=ON \ + -DENABLE_VISION=ON \ + -DCMAKE_INSTALL_PREFIX=${PWD}/installed_fastdeploy \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 +make -j8 +make install +``` +编译完成的C++ SDK即为当前目录下的`installed_fastdeploy`,使用这个新的SDK即可。 + +其它部署硬件上的编译方式同理,通过`-DOPENCV_DIRECTORY`指定环境中的OpenCV编译即可, 注意此处的路径`/usr/lib/x86_64-linux-gnu/cmake/opencv4`需根据你的实际环境路径来设定,此目录下包含`OpenCVConfig-version.cmake`、`OpenCVConfig.cmake`等文件。 + +- [FastDeploy更多部署环境的编译](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/README_CN.md) diff --git a/docs/cn/quantize.md b/docs/cn/quantize.md old mode 100644 new mode 100755 index 57f5837d8..26a75ec4e --- a/docs/cn/quantize.md +++ b/docs/cn/quantize.md @@ -36,7 +36,7 @@ FastDeploy基于PaddleSlim的Auto Compression Toolkit(ACT), 给用户提供了 目前, FastDeploy支持自动化压缩,并完成部署测试的模型的Runtime Benchmark和端到端Benchmark如下所示. Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -63,7 +63,7 @@ Benchmark表格说明: | [YOLOv7](../../examples/vision/detection/yolov7/quantize/) | Paddle Inference | CPU | 995.85 | 477.93|None|None | 2.08 |51.1 | 46.2|量化蒸馏训练 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [YOLOv5s](../../examples/vision/detection/yolov5/quantize/) | TensorRT | GPU | 24.61 | 21.20 | 20.78 | 20.94 | 1.18 | 37.6 | 36.7 | 量化蒸馏训练 | | [YOLOv5s](../../examples/vision/detection/yolov5/quantize/) | Paddle-TensorRT | GPU | 23.53 | None | 21.98 | 19.84 | 1.28 | 37.6 | 36.8 | 量化蒸馏训练 | @@ -94,7 +94,7 @@ Benchmark表格说明: | [MobileNetV1_ssld](../../examples/vision/classification/paddleclas/quantize/) | Paddle Inference | CPU | 12.29 | 4.68 | None|None|2.62 |77.89 | 71.36 |离线量化 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 Top1 | INT8 Top1 | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 Top1 | INT8 Top1 | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [ResNet50_vd](../../examples/vision/classification/paddleclas/quantize/) | TensorRT | GPU | 4.92| 2.28|2.24|2.23 | 2.21 | 79.12 | 79.06 | 离线量化 | | [ResNet50_vd](../../examples/vision/classification/paddleclas/quantize/) | Paddle-TensorRT | GPU | 4.48|None |2.09|2.10 | 2.14 | 79.12 | 79.06 | 离线量化 | @@ -119,7 +119,7 @@ NOTE: - TensorRT比Paddle-TensorRT快的原因是在runtime移除了multiclass_nms3算子 #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [ppyoloe_crn_l_300e_coco](../../examples/vision/detection/paddledetection/quantize ) | TensorRT | GPU | 35.75 | 15.42 |20.70|20.85 | 2.32 | 51.4 | 50.7 | 量化蒸馏训练 | | [ppyoloe_crn_l_300e_coco](../../examples/vision/detection/paddledetection/quantize ) | Paddle-TensorRT | GPU | 33.48 |None | 18.47 |18.03 | 1.81 | 51.4 | 50.5| 量化蒸馏训练 | @@ -134,6 +134,6 @@ NOTE: | [PP-LiteSeg-T(STDC1)-cityscapes](../../examples/vision/segmentation/paddleseg/quantize) | Paddle Inference | CPU | 1138.04| 602.62 |None|None | 1.89 |77.37 | 71.62 |量化蒸馏训练 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mIoU | INT8 mIoU | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mIoU | INT8 mIoU | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [PP-LiteSeg-T(STDC1)-cityscapes](../../examples/vision/segmentation/paddleseg/quantize) | Paddle Inference | CPU | 4726.65| 4134.91|None|None | 1.14 |77.37 | 71.62 |量化蒸馏训练 | diff --git a/docs/cn/quick_start/models/cpp.md b/docs/cn/quick_start/models/cpp.md index b99f12299..8b1d3ee28 100644 --- a/docs/cn/quick_start/models/cpp.md +++ b/docs/cn/quick_start/models/cpp.md @@ -68,7 +68,7 @@ target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) ## 4. 编译可执行程序 -假设当前目录已经准备好`infer_demo.cc`和`CMakeLists.txt`两个文件,目录结构如下所示,即可进行编译 +假设当前目录已经准备好`infer_demo.cc`和`CMakeLists.txt`两个文件,即可进行编译 ### Linux & Mac diff --git a/docs/en/build_and_install/cpu.md b/docs/en/build_and_install/cpu.md index f280cce69..bc01fb1f2 100644 --- a/docs/en/build_and_install/cpu.md +++ b/docs/en/build_and_install/cpu.md @@ -30,6 +30,11 @@ Prerequisite for Compiling on Linux & Mac: - gcc/g++ >= 5.4 (8.2 is recommended) - cmake >= 3.18.0 +It it recommend install OpenCV library manually, and define `-DOPENCV_DIRECTORY` to set path of OpenCV library(If the flag is not defined, a prebuilt OpenCV library will be downloaded automaticly while building FastDeploy, but the prebuilt OpenCV cannot support reading video file or other function e.g `imshow`) +``` +sudo apt-get install libopencv-dev +``` + ``` git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy @@ -38,7 +43,8 @@ cmake .. -DENABLE_ORT_BACKEND=ON \ -DENABLE_PADDLE_BACKEND=ON \ -DENABLE_OPENVINO_BACKEND=ON \ -DCMAKE_INSTALL_PREFIX=${PWD}/compiled_fastdeploy_sdk \ - -DENABLE_VISION=ON + -DENABLE_VISION=ON \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 make -j12 make install ``` @@ -84,6 +90,11 @@ All compilation options are introduced via environment variables ### Linux & Mac +It it recommend install OpenCV library manually, and define `-DOPENCV_DIRECTORY` to set path of OpenCV library(If the flag is not defined, a prebuilt OpenCV library will be downloaded automaticly while building FastDeploy, but the prebuilt OpenCV cannot support reading video file or other function e.g `imshow`) +``` +sudo apt-get install libopencv-dev +``` + ``` git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy/python @@ -91,6 +102,8 @@ export ENABLE_ORT_BACKEND=ON export ENABLE_PADDLE_BACKEND=ON export ENABLE_OPENVINO_BACKEND=ON export ENABLE_VISION=ON +# The OPENCV_DIRECTORY is optional, if not exported, a prebuilt OpenCV library will be downloaded +export OPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 python setup.py build python setup.py bdist_wheel diff --git a/docs/en/build_and_install/download_prebuilt_libraries.md b/docs/en/build_and_install/download_prebuilt_libraries.md index 779afe081..37b199ba0 100644 --- a/docs/en/build_and_install/download_prebuilt_libraries.md +++ b/docs/en/build_and_install/download_prebuilt_libraries.md @@ -1,3 +1,4 @@ +English | [中文](../../cn/build_and_install/download_prebuilt_libraries.md) # How to Install Prebuilt Library FastDeploy provides pre-built libraries for developers to download and install directly. Meanwhile, FastDeploy also offers easy access to compile so that developers can compile FastDeploy according to their own needs. @@ -21,7 +22,7 @@ FastDeploy supports Computer Vision, Text and NLP model deployment on CPU and Nv ### Python SDK -Install the released version(the newest 0.8.0 for now) +Install the released version(the newest 1.0.1 for now) ``` pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html @@ -41,12 +42,12 @@ conda config --add channels conda-forge && conda install cudatoolkit=11.2 cudnn= ### C++ SDK -Install the released version(Latest 0.8.0) +Install the released version(Latest 1.0.1) | Platform | File | Description | |:----------- |:--------------------------------------------------------------------------------------------------------------------- |:--------------------------------------------------------- | -| Linux x64 | [fastdeploy-linux-x64-gpu-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-gpu-0.8.0.tgz) | g++ 8.2, CUDA 11.2, cuDNN 8.2 | -| Windows x64 | [fastdeploy-win-x64-gpu-0.8.0.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-gpu-0.8.0.zip) | Visual Studio 16 2019, CUDA 11.2, cuDNN 8.2 | +| Linux x64 | [fastdeploy-linux-x64-gpu-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-gpu-1.0.1.tgz) | g++ 8.2, CUDA 11.2, cuDNN 8.2 | +| Windows x64 | [fastdeploy-win-x64-gpu-1.0.1.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-gpu-1.0.1.zip) | Visual Studio 16 2019, CUDA 11.2, cuDNN 8.2 | Install the Develop version(Nightly build) @@ -68,7 +69,7 @@ FastDeploy supports computer vision, text and NLP model deployment on CPU with P ### Python SDK -Install the released version(Latest 0.8.0 for now) +Install the released version(Latest 1.0.1 for now) ``` pip install fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html @@ -82,15 +83,15 @@ pip install fastdeploy-python==0.0.0 -f https://www.paddlepaddle.org.cn/whl/fast ### C++ SDK -Install the released version(Latest 0.8.0 for now, Android is 1.0.0 pre-release) +Install the released version(Latest 1.0.1 for now, Android is 1.0.1) | Platform | File | Description | |:------------- |:--------------------------------------------------------------------------------------------------------------------- |:------------------------------ | -| Linux x64 | [fastdeploy-linux-x64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-0.8.0.tgz) | g++ 8.2 | -| Windows x64 | [fastdeploy-win-x64-0.8.0.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-0.8.0.zip) | Visual Studio 16 2019 | -| Mac OSX x64 | [fastdeploy-osx-x86_64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-x86_64-0.8.0.tgz) | clang++ 10.0.0| -| Mac OSX arm64 | [fastdeploy-osx-arm64-0.8.0.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-arm64-0.8.0.tgz) | clang++ 13.0.0 | -| Linux aarch64 | - | - | +| Linux x64 | [fastdeploy-linux-x64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-1.0.1.tgz) | g++ 8.2 | +| Windows x64 | [fastdeploy-win-x64-1.0.1.zip](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-win-x64-1.0.1.zip) | Visual Studio 16 2019 | +| Mac OSX x64 | [fastdeploy-osx-x86_64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-x86_64-1.0.1.tgz) | clang++ 10.0.0| +| Mac OSX arm64 | [fastdeploy-osx-arm64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-osx-arm64-1.0.1.tgz) | clang++ 13.0.0 | +| Linux aarch64 | [fastdeploy-osx-arm64-1.0.1.tgz](https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-aarch64-1.0.1.tgz) | gcc 6.3 | | Android armv7&v8 | [fastdeploy-android-1.0.0-shared.tgz](https://bj.bcebos.com/fastdeploy/release/android/fastdeploy-android-1.0.0-shared.tgz)| NDK 25, clang++, support arm64-v8a及armeabi-v7a | ## Java SDK diff --git a/docs/en/build_and_install/gpu.md b/docs/en/build_and_install/gpu.md index 40357f118..df0645262 100644 --- a/docs/en/build_and_install/gpu.md +++ b/docs/en/build_and_install/gpu.md @@ -34,6 +34,11 @@ Prerequisite for Compiling on Linux: - cuda >= 11.2 - cudnn >= 8.2 +It it recommend install OpenCV library manually, and define `-DOPENCV_DIRECTORY` to set path of OpenCV library(If the flag is not defined, a prebuilt OpenCV library will be downloaded automaticly while building FastDeploy, but the prebuilt OpenCV cannot support reading video file or other function e.g `imshow`) +``` +sudo apt-get install libopencv-dev +``` + ``` git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy @@ -46,7 +51,8 @@ cmake .. -DENABLE_ORT_BACKEND=ON \ -DTRT_DIRECTORY=/Paddle/TensorRT-8.4.1.5 \ -DCUDA_DIRECTORY=/usr/local/cuda \ -DCMAKE_INSTALL_PREFIX=${PWD}/compiled_fastdeploy_sdk \ - -DENABLE_VISION=ON + -DENABLE_VISION=ON \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 make -j12 make install ``` @@ -106,6 +112,11 @@ Prerequisite for Compiling on Linux: All compilation options are imported via environment variables +It it recommend install OpenCV library manually, and define `-DOPENCV_DIRECTORY` to set path of OpenCV library(If the flag is not defined, a prebuilt OpenCV library will be downloaded automaticly while building FastDeploy, but the prebuilt OpenCV cannot support reading video file or other function e.g `imshow`) +``` +sudo apt-get install libopencv-dev +``` + ``` git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy/python @@ -117,6 +128,8 @@ export ENABLE_TRT_BACKEND=ON export WITH_GPU=ON export TRT_DIRECTORY=/Paddle/TensorRT-8.4.1.5 export CUDA_DIRECTORY=/usr/local/cuda +# The OPENCV_DIRECTORY is optional, if not exported, a prebuilt OpenCV library will be downloaded +export OPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 python setup.py build python setup.py bdist_wheel diff --git a/docs/en/build_and_install/jetson.md b/docs/en/build_and_install/jetson.md index e606b6d29..8d16f3149 100644 --- a/docs/en/build_and_install/jetson.md +++ b/docs/en/build_and_install/jetson.md @@ -1,7 +1,7 @@ # How to Build FastDeploy Library on Nvidia Jetson Platform -FastDeploy supports CPU inference with ONNX Runtime and GPU inference with Nvidia TensorRT on Nvidia Jetson platform +FastDeploy supports CPU inference with ONNX Runtime and GPU inference with Nvidia TensorRT/Paddle Inference on Nvidia Jetson platform ## How to Build and Install FastDeploy C++ Library @@ -11,12 +11,16 @@ Prerequisite for Compiling on NVIDIA Jetson: - cmake >= 3.10.0 - jetpack >= 4.6.1 +If you need to integrate Paddle Inference backend(Support CPU/GPU),please download and decompress the prebuilt library in [Paddle Inference prebuild libraries](https://www.paddlepaddle.org.cn/inference/v2.4/guides/install/download_lib.html#c) according to your develop envriment. + ``` git clone https://github.com/PaddlePaddle/FastDeploy.git cd FastDeploy mkdir build && cd build cmake .. -DBUILD_ON_JETSON=ON \ -DENABLE_VISION=ON \ + -DENABLE_PADDLE_BACKEND=ON \ # This is optional, can be OFF if you don't need + -DPADDLEINFERENCE_DIRECTORY=/Download/paddle_inference_jetson \ -DCMAKE_INSTALL_PREFIX=${PWD}/installed_fastdeploy make -j8 make install @@ -35,6 +39,8 @@ Prerequisite for Compiling on NVIDIA Jetson: Notice the `wheel` is required if you need to pack a wheel, execute `pip install wheel` first. +If you need to integrate Paddle Inference backend(Support CPU/GPU),please download and decompress the prebuilt library in [Paddle Inference prebuild libraries](https://www.paddlepaddle.org.cn/inference/v2.4/guides/install/download_lib.html#c) according to your develop envriment. + All compilation options are imported via environment variables ``` @@ -43,6 +49,10 @@ cd FastDeploy/python export BUILD_ON_JETSON=ON export ENABLE_VISION=ON +# ENABLE_PADDLE_BACKEND & PADDLEINFERENCE_DIRECTORY are optional +export ENABLE_PADDLE_BACKEND=ON +export PADDLEINFERENCE_DIRECTORY=/Download/paddle_inference_jetson + python setup.py build python setup.py bdist_wheel ``` diff --git a/docs/en/faq/custom_opencv.md b/docs/en/faq/custom_opencv.md new file mode 100644 index 000000000..41ccc72c6 --- /dev/null +++ b/docs/en/faq/custom_opencv.md @@ -0,0 +1,37 @@ +English | [中文](../../cn/faq/custom_opencv.md) + +# Use Own OpenCV Library + +The prebuilt FastDeploy library has a built-in OpenCV library, which is not able to read video file or call `imshow` because the prebuilt FastDeploy has to build in manylinux version. If you need to read video or other functions provided by opencv, this document shows how to build FastDeploy with your own OpenCV in your environment. + +FastDeploy provides flag `-DOPENCV_DIRECTORY` to set path of OpenCV library, the following steps show how to build CPU C++ SDK on Ubuntu. + +## CPU C++ SDK + +### 1. Install OpenCV + +``` +sudo apt-get install libopencv-dev +``` + +### 2. Build FastDeploy + +``` +git clone https://github.com/PaddlePaddle/FastDeploy +cd FastDeploy +mkdir build && cd build +cmake .. -DENABLE_ORT_BACKEND=ON \ + -DENABLE_PADDLE_BACKEND=ON \ + -DENABLE_OPENVINO_BACKEND=ON \ + -DENABLE_VISION=ON \ + -DCMAKE_INSTALL_PREFIX=${PWD}/installed_fastdeploy \ + -DOPENCV_DIRECTORY=/usr/lib/x86_64-linux-gnu/cmake/opencv4 +make -j8 +make install +``` + +Now we get the C++ SDK in current directory `installed_fastdeploy`, this library can use all the functions from your own OpenCV library. + +This document also works for other hardware deployment(GPU/IPU/XPU...) on Linux platform. + +- [More Options to build FastDeploy](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/README_EN.md) diff --git a/examples/multimodal/stable_diffusion/cpp/CMakeLists.txt b/examples/multimodal/stable_diffusion/cpp/CMakeLists.txt new file mode 100644 index 000000000..33b4afb93 --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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. + +PROJECT(main C CXX) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) + +option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.") +set(THIRD_LIBS "") +include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) + +include_directories(${FASTDEPLOY_INCS}) + +file(GLOB_RECURSE ALL_SRCS ${PROJECT_SOURCE_DIR}/*.cc) + +add_executable(main ${ALL_SRCS}) +target_link_libraries(main ${FASTDEPLOY_LIBS} ${THIRD_LIBS}) diff --git a/examples/multimodal/stable_diffusion/cpp/README.md b/examples/multimodal/stable_diffusion/cpp/README.md new file mode 100644 index 000000000..06d085feb --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/README.md @@ -0,0 +1,12 @@ +# StableDiffusion C++部署示例 + +在部署前,需确认以下两个步骤 + +- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) +- 2. 根据开发环境,下载预编译部署库和samples代码,参考[FastDeploy预编译库](../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) + +本目录下提供`*_infer.cc`快速完成StableDiffusion各任务的C++部署示例。 + +## Inpaint任务 + +StableDiffusion Inpaint任务是一个根据提示文本补全图片的任务,具体而言就是用户给定提示文本,原始图片以及原始图片的mask图片,该任务输出补全后的图片。 diff --git a/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.cc b/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.cc new file mode 100644 index 000000000..b61c5b5db --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.cc @@ -0,0 +1,398 @@ +// 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 "dpm_solver_multistep_scheduler.h" +#include "fastdeploy/core/fd_scalar.h" +#include "fastdeploy/function/functions.h" +#include +#include + +namespace fastdeploy { + +void DPMSolverMultistepScheduler::BetaForAlphaBar(FDTensor* out, + int num_diffusion_timesteps, + float max_beta) { + auto alpha_bar = [](float time_step) -> float { + constexpr float pi = 3.14159265358979323846; + return std::pow(std::cos((time_step + 0.008) / 1.008 * pi / 2), 2); + }; + std::vector betas; + for (int i = 0; i < num_diffusion_timesteps; ++i) { + float t1 = i / num_diffusion_timesteps; + float t2 = (i + 1) / num_diffusion_timesteps; + float beta_val = (std::min)(1 - alpha_bar(t1) / alpha_bar(t2), max_beta); + betas.emplace_back(Scalar(beta_val)); + } + function::Concat(betas, out); +} + +DPMSolverMultistepScheduler::DPMSolverMultistepScheduler( + int num_train_timesteps, float beta_start, float beta_end, + const std::string& beta_schedule, const std::vector& trained_betas, + int solver_order, bool predict_epsilon, bool thresholding, + float dynamic_thresholding_ratio, float sample_max_value, + const std::string& algorithm_type, const std::string& solver_type, + bool lower_order_final) + : config({num_train_timesteps, beta_start, beta_end, beta_schedule, + solver_order, predict_epsilon, thresholding, + dynamic_thresholding_ratio, sample_max_value, algorithm_type, + solver_type, lower_order_final}) { + int beta_size = trained_betas.size(); + if (beta_size > 0) { + betas_.Allocate({beta_size}, FDDataType::FP32); + std::copy(trained_betas.data(), trained_betas.data() + beta_size, + reinterpret_cast(betas_.Data())); + } else if (beta_schedule == "linear") { + function::Linspace(beta_start, beta_end, num_train_timesteps, &betas_, + FDDataType::FP32); + } else if (beta_schedule == "scaled_linear") { + function::Linspace(std::sqrt(beta_start), std::sqrt(beta_end), + num_train_timesteps, &betas_, FDDataType::FP32); + betas_ = betas_ * betas_; + } else if (beta_schedule == "squaredcos_cap_v2") { + BetaForAlphaBar(&betas_, num_train_timesteps); + } else { + FDASSERT(false, "%s is not implemented for DPMSolverMultistepScheduler", + beta_schedule.c_str()); + } + + alphas_ = 1.0f - betas_; + function::Cumprod(alphas_, &alphas_cumprod_); + function::Sqrt(alphas_cumprod_, &alpha_t_); + function::Sqrt(1.0f - alphas_cumprod_, &sigma_t_); + FDTensor alpha_t_log, sigma_t_log; + function::Log(alpha_t_, &alpha_t_log); + function::Log(sigma_t_, &sigma_t_log); + lambda_t_ = alpha_t_log - sigma_t_log; + + FDASSERT(config.algorithm_type_ == "dpmsolver" || + config.algorithm_type_ == "dpmsolver++", + "%s does is not implemented for DPMSolverMultistepScheduler", + config.algorithm_type_.c_str()); + FDASSERT(config.solver_type_ == "midpoint" || config.solver_type_ == "heun", + "%s does is not implemented for DPMSolverMultistepScheduler", + config.solver_type_.c_str()); + num_inference_steps_ = -1; + + function::Linspace(0, config.num_train_timesteps_ - 1, + config.num_train_timesteps_, ×teps_); + function::Cast(timesteps_, ×teps_, FDDataType::INT64); + // Reverse timesteps + int64_t* timesteps_data = reinterpret_cast(timesteps_.Data()); + std::reverse(timesteps_data, timesteps_data + timesteps_.Numel()); + + model_outputs_.resize(config.solver_order_); + lower_order_nums_ = 0; +} + +float DPMSolverMultistepScheduler::InitNoiseSigma() { return 1.0; } + +void DPMSolverMultistepScheduler::ConvertModelOutput( + const FDTensor& model_output, int timestep, const FDTensor& sample, + FDTensor* out) { + if (config.algorithm_type_ == "dpmsolver++") { + FDTensor x0_pred; + if (config.predict_epsilon_) { + FDTensor alpha_t, sigma_t; + function::Slice(alpha_t_, {0}, {timestep}, &alpha_t); + function::Slice(sigma_t_, {0}, {timestep}, &sigma_t); + x0_pred = (sample - sigma_t * model_output) / alpha_t; + } else { + x0_pred = model_output; + } + if (config.thresholding_) { + FDTensor dynamic_max_val, x0_pred_abs; + function::Abs(x0_pred, &x0_pred_abs); + x0_pred_abs.Reshape({x0_pred_abs.Shape()[0], -1}); + function::Quantile(x0_pred_abs, {config.dynamic_thresholding_ratio_}, {1}, + &dynamic_max_val); + + FDTensor max_value, dy_max_val; + function::FullLike(dynamic_max_val, config.sample_max_value_, &max_value, + dynamic_max_val.Dtype()); + function::Maximum(dynamic_max_val, max_value, &dy_max_val); + int expand_dims = x0_pred.Shape().size() - 1; + for (int i = 0; i < expand_dims; ++i) { + dy_max_val.ExpandDim(dy_max_val.Shape().size()); + } + float clip_max = reinterpret_cast(dy_max_val.Data())[0]; + function::Clip(x0_pred, -clip_max, clip_max, &x0_pred); + x0_pred = x0_pred / dy_max_val; + } + *out = std::move(x0_pred); + } else if (config.algorithm_type_ == "dpmsolver") { + if (config.predict_epsilon_) { + *out = model_output; + } else { + FDTensor alpha_t, sigma_t; + function::Slice(alpha_t_, {0}, {timestep}, &alpha_t); + function::Slice(sigma_t_, {0}, {timestep}, &sigma_t); + *out = (sample - (alpha_t * model_output)) / sigma_t; + } + } +} + +void DPMSolverMultistepScheduler::DPMSolverFirstOrderUpdate( + const FDTensor& model_output, int timestep, int prev_timestep, + const FDTensor& sample, FDTensor* out) { + FDTensor lambda_t, lambda_s; + function::Slice(lambda_t_, {0}, {prev_timestep}, &lambda_t); + function::Slice(lambda_t_, {0}, {timestep}, &lambda_s); + + FDTensor alpha_t, alpha_s; + function::Slice(alpha_t_, {0}, {prev_timestep}, &alpha_t); + function::Slice(alpha_t_, {0}, {timestep}, &alpha_s); + + FDTensor sigma_t, sigma_s; + function::Slice(sigma_t_, {0}, {prev_timestep}, &sigma_t); + function::Slice(sigma_t_, {0}, {timestep}, &sigma_s); + + FDTensor h = lambda_t - lambda_s; + if (config.algorithm_type_ == "dpmsolver++") { + function::Exp(0.0f - h, &h); + *out = (sigma_t / sigma_s) * sample - (alpha_t * (h - 1.0f)) * model_output; + } else if (config.algorithm_type_ == "dpmsolver") { + function::Exp(h, &h); + *out = (alpha_t / alpha_s) * sample - (sigma_t * (h - 1.0f)) * model_output; + } +} + +void DPMSolverMultistepScheduler::MultiStepDPMSolverSecondOrderUpdate( + const std::vector& model_output_list, + const std::vector& timestep_list, int prev_timestep, + const FDTensor& sample, FDTensor* out) { + int timestep_size = timestep_list.size(); + int model_output_size = model_output_list.size(); + int t = prev_timestep; + int s0 = timestep_list[timestep_size - 1]; + int s1 = timestep_list[timestep_size - 2]; + const FDTensor& m0 = model_output_list[model_output_size - 1]; + const FDTensor& m1 = model_output_list[model_output_size - 2]; + FDTensor lambda_t, lambda_s0, lambda_s1; + function::Slice(lambda_t_, {0}, {t}, &lambda_t); + function::Slice(lambda_t_, {0}, {s0}, &lambda_s0); + function::Slice(lambda_t_, {0}, {s1}, &lambda_s1); + + FDTensor alpha_t, alpha_s0, sigma_t, sigma_s0; + function::Slice(alpha_t_, {0}, {t}, &alpha_t); + function::Slice(alpha_t_, {0}, {s0}, &alpha_s0); + function::Slice(sigma_t_, {0}, {t}, &sigma_t); + function::Slice(sigma_t_, {0}, {s0}, &sigma_s0); + + FDTensor h = lambda_t - lambda_s0; + FDTensor h0 = lambda_s0 - lambda_s1; + FDTensor r0 = h0 / h; + FDTensor D0 = m0; + FDTensor D1 = (1.0f / r0) * (m0 - m1); + if (config.algorithm_type_ == "dpmsolver++") { + if (config.solver_type_ == "midpoint") { + function::Exp(0.0f - h, &h); + *out = (sigma_t / sigma_s0 * sample) - (alpha_t * (h - 1.0f) * D0) - + (0.5f * alpha_t * (h - 1.0f) * D1); + } else if (config.solver_type_ == "heun") { + FDTensor h_exp; + function::Exp(0.0f - h, &h_exp); + *out = (sigma_t / sigma_s0 * sample) - (alpha_t * (h_exp - 1.0f) * D0) + + (alpha_t * ((h_exp - 1.0f) / h + 1.0f) * D1); + } + } else if (config.algorithm_type_ == "dpmsolver") { + FDTensor h_exp; + function::Exp(h, &h_exp); + if (config.solver_type_ == "midpoint") { + *out = alpha_t / alpha_s0 * sample - sigma_t * (h_exp - 1.0f) * D0 - + 0.5 * (sigma_t * (h_exp - 1.0f) * D1); + } else if (config.solver_type_ == "heun") { + *out = alpha_t / alpha_s0 * sample - sigma_t * (h_exp - 1.0f) * D0 - + (sigma_t * ((h_exp - 1.0f) / h - 1.0f) * D1); + } + } +} + +void DPMSolverMultistepScheduler::MultiStepDPMSolverThirdOrderUpdate( + const std::vector& model_output_list, + const std::vector& timestep_list, int prev_timestep, + const FDTensor& sample, FDTensor* out) { + int timestep_size = timestep_list.size(); + int model_output_size = model_output_list.size(); + int t = prev_timestep; + + int s0 = timestep_list[timestep_size - 1]; + int s1 = timestep_list[timestep_size - 2]; + int s2 = timestep_list[timestep_size - 3]; + const FDTensor& m0 = model_output_list[model_output_size - 1]; + const FDTensor& m1 = model_output_list[model_output_size - 2]; + const FDTensor& m2 = model_output_list[model_output_size - 3]; + + FDTensor lambda_t, lambda_s0, lambda_s1, lambda_s2; + function::Slice(lambda_t_, {0}, {t}, &lambda_t); + function::Slice(lambda_t_, {0}, {s0}, &lambda_s0); + function::Slice(lambda_t_, {0}, {s1}, &lambda_s1); + function::Slice(lambda_t_, {0}, {s2}, &lambda_s2); + + FDTensor alpha_t, alpha_s0, sigma_t, sigma_s0; + function::Slice(alpha_t_, {0}, {t}, &alpha_t); + function::Slice(alpha_t_, {0}, {s0}, &alpha_s0); + function::Slice(sigma_t_, {0}, {t}, &sigma_t); + function::Slice(sigma_t_, {0}, {s0}, &sigma_s0); + + FDTensor h = lambda_t - lambda_s0; + FDTensor h0 = lambda_s0 - lambda_s1; + FDTensor h1 = lambda_s1 - lambda_s2; + + FDTensor r0 = h0 / h; + FDTensor r1 = h1 / h; + FDTensor D0 = m0; + FDTensor D1_0 = (1.0f / r0) * (m0 - m1); + FDTensor D1_1 = (1.0f / r1) * (m1 - m2); + FDTensor D1 = D1_0 + (r0 / (r0 + r1)) * (D1_0 - D1_1); + FDTensor D2 = (1.0f / (r0 + r1)) * (D1_0 - D1_1); + + if (config.algorithm_type_ == "dpmsolver++") { + FDTensor h_exp; + function::Exp(0.0f - h, &h_exp); + *out = (sigma_t / sigma_s0) * sample - (alpha_t * (h_exp - 1.0f)) * D0 + + (alpha_t * ((h_exp - 1.0) / h + 1.0)) * D1 - + (alpha_t * ((h_exp - 1.0 + h) / (h * h) - 0.5)) * D2; + + } else if (config.algorithm_type_ == "dpmsolver") { + FDTensor h_exp; + function::Exp(h, &h_exp); + *out = (alpha_t / alpha_s0) * sample - (sigma_t * (h_exp - 1.0f)) * D0 + + (sigma_t * ((h_exp - 1.0) / h - 1.0)) * D1 - + (sigma_t * ((h_exp - 1.0 - h) / (h * h) - 0.5)) * D2; + } +} + +void DPMSolverMultistepScheduler::ScaleModelInput( + const FDTensor& sample, FDTensor* out, + const std::vector& timesteps) { + *out = sample; +} + +void DPMSolverMultistepScheduler::SetTimesteps(int num_inference_steps) { + num_inference_steps_ = num_inference_steps; + function::Linspace(0, config.num_train_timesteps_ - 1, + num_inference_steps + 1, ×teps_); + function::Round(timesteps_, ×teps_); + // Reverse timesteps + float* timesteps_data = reinterpret_cast(timesteps_.Data()); + std::reverse(timesteps_data, timesteps_data + timesteps_.Numel()); + FDTensor timestep_tmp; + timestep_tmp.Allocate({num_inference_steps}, timesteps_.Dtype()); + float* timestep_tmp_data = reinterpret_cast(timestep_tmp.Data()); + std::copy(timesteps_data, timesteps_data + num_inference_steps, + timestep_tmp_data); + timesteps_ = std::move(timestep_tmp); + + function::Cast(timesteps_, ×teps_, FDDataType::INT64); + + model_outputs_.clear(); + model_outputs_.resize(config.solver_order_); + + lower_order_nums_ = 0; +} + +void DPMSolverMultistepScheduler::Step(const FDTensor& model_output, + int timestep, const FDTensor& sample, + FDTensor* prev_sample) { + FDASSERT(num_inference_steps_ > -1, + "Number of inference steps is -1, you need to run SetTimesteps " + "after creating the scheduler"); + int64_t step_index = timesteps_.Numel() - 1; + int64_t* timesteps_data = reinterpret_cast(timesteps_.Data()); + int64_t* timesteps_iter = + std::find(timesteps_data, timesteps_data + timesteps_.Numel(), timestep); + if (timesteps_iter - timesteps_data < timesteps_.Numel()) { + step_index = timesteps_iter - timesteps_data; + } + int64_t prev_timestep = 0; + if (step_index != timesteps_.Numel() - 1) { + prev_timestep = timesteps_data[step_index + 1]; + } + bool lower_order_final = (step_index == timesteps_.Numel() - 1) && + config.lower_order_final_ && + (timesteps_.Numel() < 15); + bool lower_order_second = (step_index == timesteps_.Numel() - 2) && + config.lower_order_final_ && + (timesteps_.Numel() < 15); + FDTensor model_out; + ConvertModelOutput(model_output, timestep, sample, &model_out); + for (int i = 0; i < config.solver_order_ - 1; ++i) { + model_outputs_[i] = std::move(model_outputs_[i + 1]); + } + model_outputs_[config.solver_order_ - 1] = std::move(model_out); + + if (config.solver_order_ == 1 || lower_order_nums_ < 1 || lower_order_final) { + DPMSolverFirstOrderUpdate(model_outputs_[config.solver_order_ - 1], + timestep, prev_timestep, sample, prev_sample); + } else if (config.solver_order_ == 2 || lower_order_nums_ < 2 || + lower_order_second) { + int t0 = reinterpret_cast(timesteps_.Data())[step_index - 1]; + std::vector timestep_list = {t0, timestep}; + MultiStepDPMSolverSecondOrderUpdate(model_outputs_, timestep_list, + prev_timestep, sample, prev_sample); + } else { + int t0 = reinterpret_cast(timesteps_.Data())[step_index - 1]; + int t1 = reinterpret_cast(timesteps_.Data())[step_index - 2]; + std::vector timestep_list = {t1, t0, timestep}; + MultiStepDPMSolverThirdOrderUpdate(model_outputs_, timestep_list, + prev_timestep, sample, prev_sample); + } + + if (lower_order_nums_ < config.solver_order_) { + lower_order_nums_ += 1; + } +} + +void DPMSolverMultistepScheduler::AddNoise(const FDTensor& original_samples, + const FDTensor& noise, + const FDTensor& timesteps, + FDTensor* out) { + function::Cast(alphas_cumprod_, &alphas_cumprod_, original_samples.Dtype()); + + const int64_t* timesteps_data = + reinterpret_cast(timesteps.Data()); + std::vector timesteps_vec; + for (int i = 0; i < timesteps.Numel(); ++i) { + timesteps_vec.push_back(timesteps_data[i]); + } + FDTensor sqrt_alpha_prod; + function::Slice(alphas_cumprod_, {0}, timesteps_vec, &sqrt_alpha_prod); + function::Sqrt(sqrt_alpha_prod, &sqrt_alpha_prod); + sqrt_alpha_prod.Reshape({-1}); + int rank_diff = + original_samples.Shape().size() - sqrt_alpha_prod.Shape().size(); + for (int i = 0; i < rank_diff; ++i) { + int curr_rank = sqrt_alpha_prod.Shape().size(); + sqrt_alpha_prod.ExpandDim(curr_rank - 1); + } + + FDTensor sqrt_one_minus_alpha_prod; + function::Slice(alphas_cumprod_, {0}, timesteps_vec, + &sqrt_one_minus_alpha_prod); + sqrt_one_minus_alpha_prod = 1.0f - sqrt_one_minus_alpha_prod; + function::Sqrt(sqrt_one_minus_alpha_prod, &sqrt_one_minus_alpha_prod); + sqrt_one_minus_alpha_prod.Reshape({-1}); + rank_diff = original_samples.Shape().size() - + sqrt_one_minus_alpha_prod.Shape().size(); + for (int i = 0; i < rank_diff; ++i) { + int curr_rank = sqrt_one_minus_alpha_prod.Shape().size(); + sqrt_one_minus_alpha_prod.ExpandDim(curr_rank - 1); + } + *out = sqrt_alpha_prod * original_samples + sqrt_one_minus_alpha_prod * noise; +} + +FDTensor DPMSolverMultistepScheduler::GetTimesteps() { return timesteps_; } + +} // namespace fastdeploy diff --git a/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.h b/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.h new file mode 100644 index 000000000..0775ba1ee --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/dpm_solver_multistep_scheduler.h @@ -0,0 +1,87 @@ +// 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 "./scheduler.h" +#include "fastdeploy/core/fd_tensor.h" + +namespace fastdeploy { + +class DPMSolverMultistepScheduler : public Scheduler { + public: + DPMSolverMultistepScheduler(int num_train_timesteps = 1000, + float beta_start = 0.0001, float beta_end = 0.02, + const std::string& beta_schedule = "linear", + const std::vector& trained_betas = {}, + int solver_order = 2, bool predict_epsilon = true, + bool thresholding = false, + float dynamic_thresholding_ratio = 0.995, + float sample_max_value = 1.0, + const std::string& algorithm_type = "dpmsolver++", + const std::string& solver_type = "midpoint", + bool lower_order_final = true); + void BetaForAlphaBar(FDTensor* out, int num_diffusion_timesteps, + float max_beta = 0.999); + void ConvertModelOutput(const FDTensor& model_output, int timestep, + const FDTensor& sample, FDTensor* out); + void DPMSolverFirstOrderUpdate(const FDTensor& model_output, int timestep, + int prev_timestep, const FDTensor& sample, + FDTensor* out); + void MultiStepDPMSolverSecondOrderUpdate( + const std::vector& model_output_list, + const std::vector& timestep_list, int prev_timestep, + const FDTensor& sample, FDTensor* out); + void MultiStepDPMSolverThirdOrderUpdate( + const std::vector& model_output_list, + const std::vector& timestep_list, int prev_timestep, + const FDTensor& sample, FDTensor* out); + void SetTimesteps(int num_inference_steps) override; + void Step(const FDTensor& model_output, int timestep, const FDTensor& sample, + FDTensor* prev_sample) override; + void ScaleModelInput(const FDTensor& sample, FDTensor* out, + const std::vector& timesteps = {}) override; + void AddNoise(const FDTensor& original_samples, const FDTensor& noise, + const FDTensor& timesteps, FDTensor* out) override; + float InitNoiseSigma() override; + FDTensor GetTimesteps() override; + struct Config { + int num_train_timesteps_; + float beta_start_; + float beta_end_; + std::string beta_schedule_; + int solver_order_; + bool predict_epsilon_; + bool thresholding_; + float dynamic_thresholding_ratio_; + float sample_max_value_; + std::string algorithm_type_; + std::string solver_type_; + bool lower_order_final_; + } config; + + private: + FDTensor betas_; + FDTensor alphas_; + FDTensor alphas_cumprod_; + FDTensor alpha_t_; + FDTensor sigma_t_; + FDTensor lambda_t_; + int num_inference_steps_; + FDTensor timesteps_; + int lower_order_nums_; + std::vector model_outputs_; +}; + +} // namespace fastdeploy diff --git a/examples/multimodal/stable_diffusion/cpp/main.cc b/examples/multimodal/stable_diffusion/cpp/main.cc new file mode 100644 index 000000000..79051279f --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/main.cc @@ -0,0 +1,239 @@ +// 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 "./dpm_solver_multistep_scheduler.h" +#include "./pipeline_stable_diffusion_inpaint.h" +#include "fastdeploy/utils/perf.h" +#include "fastdeploy/vision/common/processors/mat.h" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include +#include +#include +#include +#include + +#ifdef WIN32 +const char sep = '\\'; +#else +const char sep = '/'; +#endif + +template std::string Str(const T* value, int size) { + std::ostringstream oss; + oss << "[ " << value[0]; + for (int i = 1; i < size; ++i) { + oss << " ," << value[i]; + } + oss << " ]"; + return oss.str(); +} + +std::unique_ptr CreateRuntime( + const std::string& model_file, const std::string& params_file, + bool use_trt_backend = false, bool use_fp16 = false, + const std::unordered_map>>& + dynamic_shapes = {}, + const std::vector& disable_paddle_trt_ops = {}) { + fastdeploy::RuntimeOption runtime_option; + runtime_option.SetModelPath(model_file, params_file, + fastdeploy::ModelFormat::PADDLE); + runtime_option.UseGpu(); + if (!use_trt_backend) { + runtime_option.UsePaddleBackend(); + } else { + runtime_option.UseTrtBackend(); + runtime_option.EnablePaddleToTrt(); + for (auto it = dynamic_shapes.begin(); it != dynamic_shapes.end(); ++it) { + if (it->second.size() != 3) { + std::cerr << "The size of dynamic_shapes of input `" << it->first + << "` should be 3, but receive " << it->second.size() + << std::endl; + continue; + } + std::vector min_shape = (it->second)[0]; + std::vector opt_shape = (it->second)[1]; + std::vector max_shape = (it->second)[2]; + runtime_option.SetTrtInputShape(it->first, min_shape, opt_shape, + max_shape); + } + runtime_option.SetTrtCacheFile("paddle.trt"); + runtime_option.EnablePaddleTrtCollectShape(); + runtime_option.DisablePaddleTrtOPs(disable_paddle_trt_ops); + if (use_fp16) { + runtime_option.EnableTrtFP16(); + } + } + std::unique_ptr runtime = + std::unique_ptr(new fastdeploy::Runtime()); + if (!runtime->Init(runtime_option)) { + std::cerr << "--- Init FastDeploy Runitme Failed! " + << "\n--- Model: " << model_file << std::endl; + return nullptr; + } else { + std::cout << "--- Init FastDeploy Runitme Done! " + << "\n--- Model: " << model_file << std::endl; + } + return runtime; +} + +int main() { + // 0. Init all configs + std::string model_dir = "sd15_inpaint"; + int max_length = 77; + bool use_trt_backend = true; + bool use_fp16 = true; + int batch_size = 1; + int num_images_per_prompt = 1; + int num_inference_steps = 50; + + int height = 512; + int width = 512; + constexpr int unet_inpaint_channels = 9; + constexpr int latents_channels = 4; + + // 1. Init scheduler + std::unique_ptr dpm( + new fastdeploy::DPMSolverMultistepScheduler( + /* num_train_timesteps */ 1000, + /* beta_start = */ 0.00085, + /* beta_end = */ 0.012, + /* beta_schedule = */ "scaled_linear", + /* trained_betas = */ {}, + /* solver_order = */ 2, + /* predict_epsilon = */ true, + /* thresholding = */ false, + /* dynamic_thresholding_ratio = */ 0.995, + /* sample_max_value = */ 1.0, + /* algorithm_type = */ "dpmsolver++", + /* solver_type = */ "midpoint", + /* lower_order_final = */ true)); + + // 2. Init text encoder runtime + std::unordered_map>> + text_dynamic_shape = {{"input_ids", + {/* min_shape */ {1, max_length}, + /* opt_shape */ {batch_size, max_length}, + /* max_shape */ {2 * batch_size, max_length}}}}; + std::string text_model_dir = model_dir + sep + "text_encoder"; + std::string text_model_file = text_model_dir + sep + "inference.pdmodel"; + std::string text_params_file = text_model_dir + sep + "inference.pdiparams"; + std::unique_ptr text_encoder_runtime = + CreateRuntime(text_model_file, text_params_file, use_trt_backend, + use_fp16, text_dynamic_shape); + + // 3. Init vae encoder runtime + std::unordered_map>> + vae_encoder_dynamic_shape = { + {"sample", + {/* min_shape */ {1, 3, height, width}, + /* opt_shape */ {2 * batch_size, 3, height, width}, + /* max_shape */ {2 * batch_size, 3, height, width}}}}; + std::string vae_encoder_model_dir = model_dir + sep + "vae_encoder"; + std::string vae_encoder_model_file = + vae_encoder_model_dir + sep + "inference.pdmodel"; + std::string vae_encoder_params_file = + vae_encoder_model_dir + sep + "inference.pdiparams"; + std::unique_ptr vae_encoder_runtime = + CreateRuntime(vae_encoder_model_file, vae_encoder_params_file, + use_trt_backend, use_fp16, vae_encoder_dynamic_shape); + + // 4. Init vae decoder runtime + std::unordered_map>> + vae_decoder_dynamic_shape = { + {"latent_sample", + {/* min_shape */ {1, latents_channels, height / 8, width / 8}, + /* opt_shape */ + {2 * batch_size, latents_channels, height / 8, width / 8}, + /* max_shape */ + {2 * batch_size, latents_channels, height / 8, width / 8}}}}; + std::string vae_decoder_model_dir = model_dir + sep + "vae_decoder"; + std::string vae_decoder_model_file = + vae_decoder_model_dir + sep + "inference.pdmodel"; + std::string vae_decoder_params_file = + vae_decoder_model_dir + sep + "inference.pdiparams"; + std::unique_ptr vae_decoder_runtime = + CreateRuntime(vae_decoder_model_file, vae_decoder_params_file, + use_trt_backend, use_fp16, vae_decoder_dynamic_shape); + + // 5. Init unet runtime + std::unordered_map>> + unet_dynamic_shape = { + {"sample", + {/* min_shape */ {1, unet_inpaint_channels, height / 8, width / 8}, + /* opt_shape */ + {2 * batch_size, unet_inpaint_channels, height / 8, width / 8}, + /* max_shape */ + {2 * batch_size, unet_inpaint_channels, height / 8, width / 8}}}, + {"timesteps", {{1}, {1}, {1}}}, + {"encoder_hidden_states", + {{1, max_length, 768}, + {2 * batch_size, max_length, 768}, + {2 * batch_size, max_length, 768}}}}; + std::vector unet_disable_paddle_trt_ops = {"sin", "cos"}; + std::string unet_model_dir = model_dir + sep + "unet"; + std::string unet_model_file = unet_model_dir + sep + "inference.pdmodel"; + std::string unet_params_file = unet_model_dir + sep + "inference.pdiparams"; + std::unique_ptr unet_runtime = + CreateRuntime(unet_model_file, unet_params_file, use_trt_backend, + use_fp16, unet_dynamic_shape, unet_disable_paddle_trt_ops); + + // 6. Init fast tokenizer + paddlenlp::fast_tokenizer::tokenizers_impl::ClipFastTokenizer tokenizer( + "clip/vocab.json", "clip/merges.txt", /* max_length = */ max_length); + fastdeploy::StableDiffusionInpaintPipeline pipe( + /* vae_encoder = */ std::move(vae_encoder_runtime), + /* vae_decoder = */ std::move(vae_decoder_runtime), + /* text_encoder = */ std::move(text_encoder_runtime), + /* unet = */ std::move(unet_runtime), + /* scheduler = */ std::move(dpm), + /* tokenizer = */ tokenizer); + + // 7. Read images + auto image = cv::imread("overture-creations.png"); + auto mask_image = cv::imread("overture-creations-mask.png"); + + // 8. Predict + /* + * One may need to pass the initial noise to predict api. + * There's an example: + * std::vector latents_data = {xxxx}; + * fastdeploy::FDTensor latents; + * latents.SetExternalData({batch_size * num_images_per_prompt, latents_channels, height / 8, width / 8},fastdeploy::FDDataType::FP32, latents_data.data()); + * pipe.Predict(..., /* latents = *\/ &latents, ....); + */ + std::vector prompts = { + "Face of a yellow cat, high resolution, sitting on a park bench"}; + std::vector outputs; + fastdeploy::TimeCounter tc; + tc.Start(); + pipe.Predict(prompts, image, mask_image, &outputs, + /* height = */ height, + /* width = */ width, + /* num_inference_steps = */ num_inference_steps, + /* guidance_scale = */ 7.5, + /* negative_prompt = */ {}, + /* num_images_per_prompt = */ num_images_per_prompt, + /* eta = */ 1.0, + /* max_length = */ max_length, + /* latents = */ nullptr, + /* output_cv_mat = */ true, + /* callback = */ nullptr, + /* callback_steps = */ 1); + tc.End(); + tc.PrintInfo(); + fastdeploy::vision::FDMat mat = fastdeploy::vision::FDMat::Create(outputs[0]); + cv::imwrite("cat_on_bench_new.png", *mat.GetOpenCVMat()); + return 0; +} \ No newline at end of file diff --git a/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.cc b/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.cc new file mode 100644 index 000000000..4e0f1ed5f --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.cc @@ -0,0 +1,320 @@ +// 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 "pipeline_stable_diffusion_inpaint.h" +#include "fastdeploy/function/functions.h" +#include "fastdeploy/vision/common/processors/color_space_convert.h" +#include "fastdeploy/vision/common/processors/mat.h" +#include "fastdeploy/vision/common/processors/resize.h" +#include + +using namespace paddlenlp; + +namespace fastdeploy { + +static constexpr int NUM_LATENT_CHANNELS = 4; +static constexpr int NUM_UNET_INPUT_CHANNELS = 9; + +void StableDiffusionInpaintPipeline::PrepareMaskAndMaskedImage( + const cv::Mat& image, const cv::Mat& mask_mat, + const std::vector& shape, FDTensor* mask, FDTensor* mask_image) { + vision::FDMat image_fdmat(image); + vision::BGR2RGB::Run(&image_fdmat, vision::ProcLib::OPENCV); + vision::Resize::Run(&image_fdmat, shape[1] * 8, shape[0] * 8, -1.0f, -1.0f, + cv::INTER_NEAREST, false, vision::ProcLib::OPENCV); + image_fdmat.ShareWithTensor(mask_image); + + vision::FDMat mask_fdmat(mask_mat); + vision::BGR2GRAY::Run(&mask_fdmat, vision::ProcLib::OPENCV); + vision::Resize::Run(&mask_fdmat, shape[1] * 8, shape[0] * 8, -1.0f, -1.0f, + cv::INTER_NEAREST, false, vision::ProcLib::OPENCV); + FDTensor image_mask; + mask_fdmat.ShareWithTensor(&image_mask); + function::Cast(image_mask, &image_mask, FDDataType::FP32); + std::vector float_mask(image_mask.Numel(), 0); + float* image_mask_ptr = reinterpret_cast(image_mask.Data()); + for (int i = 0; i < image_mask.Numel(); ++i) { + if (image_mask_ptr[i] < 127.5) { + float_mask[i] = 1; + } + } + // NCHW format + image_mask.SetExternalData({1, 1, shape[0] * 8, shape[1] * 8}, + FDDataType::FP32, float_mask.data()); + + // Set mask_image + mask_image->ExpandDim(); + function::Transpose(*mask_image, mask_image, {0, 3, 1, 2}); + function::Cast(*mask_image, mask_image, FDDataType::FP32); + *mask_image = *mask_image / 127.5f - 1.0f; + *mask_image = *mask_image * image_mask; + + // Set mask + vision::FDMat mask_fdmat_t(mask_mat); + vision::BGR2GRAY::Run(&mask_fdmat_t, vision::ProcLib::OPENCV); + vision::Resize::Run(&mask_fdmat_t, shape[1], shape[0], -1.0f, -1.0f, + cv::INTER_NEAREST, false, vision::ProcLib::OPENCV); + mask_fdmat_t.ShareWithTensor(mask); + function::Cast(*mask, mask, FDDataType::FP32); + *mask = *mask / 255.0f; + mask->ExpandDim(); + function::Transpose(*mask, mask, {0, 3, 1, 2}); + float* mask_data = reinterpret_cast(mask->Data()); + for (int i = 0; i < mask->Numel(); ++i) { + if (mask_data[i] < 0.5) { + mask_data[i] = 0; + } else { + mask_data[i] = 1; + } + } +} + +StableDiffusionInpaintPipeline::StableDiffusionInpaintPipeline( + std::unique_ptr vae_encoder, std::unique_ptr vae_decoder, + std::unique_ptr text_encoder, std::unique_ptr unet, + std::unique_ptr scheduler, + const paddlenlp::fast_tokenizer::tokenizers_impl::ClipFastTokenizer& + tokenizer) + : vae_encoder_(std::move(vae_encoder)), + vae_decoder_(std::move(vae_decoder)), + text_encoder_(std::move(text_encoder)), unet_(std::move(unet)), + scheduler_(std::move(scheduler)), tokenizer_(tokenizer) {} + +void StableDiffusionInpaintPipeline::Predict( + const std::vector& prompts, const cv::Mat& image, + const cv::Mat& mask_image, std::vector* output_images, int height, + int width, int num_inference_steps, float guidance_scale, + const std::vector& negative_prompt, int num_images_per_prompt, + float eta, uint32_t max_length, const FDTensor* latents, bool output_cv_mat, + callback_ptr callback, int callback_steps) { + int batch_size = prompts.size(); + FDASSERT(batch_size >= 1, "prompts should not be empty"); + FDASSERT( + height % 8 == 0 && width % 8 == 0, + "`height` and `width` have to be divisible by 8 but are {%d} and {%d}.", + height, width); + FDASSERT(callback_steps > 0, + "`callback_steps` has to be a positive integer but is {%d}", + callback_steps); + + // Setting tokenizer attr + if (max_length == 0) { + tokenizer_.EnablePadMethod(fast_tokenizer::core::RIGHT, + tokenizer_.GetPadTokenId(), 0, + tokenizer_.GetPadToken(), nullptr, nullptr); + tokenizer_.DisableTruncMethod(); + } else { + tokenizer_.EnablePadMethod(fast_tokenizer::core::RIGHT, + tokenizer_.GetPadTokenId(), 0, + tokenizer_.GetPadToken(), &max_length, nullptr); + tokenizer_.EnableTruncMethod(max_length, 0, fast_tokenizer::core::RIGHT, + fast_tokenizer::core::LONGEST_FIRST); + } + std::vector encodings; + tokenizer_.EncodeBatchStrings(prompts, &encodings); + + std::vector input_ids; + for (auto& encoding : encodings) { + auto curr_ids = encoding.GetIds(); + input_ids.insert(input_ids.end(), curr_ids.begin(), curr_ids.end()); + } + encodings.clear(); + // Get text encoder output + FDTensor text_intput_ids; + std::vector inputs(1); + inputs[0].SetExternalData({batch_size, max_length}, FDDataType::INT64, + input_ids.data()); + + TensorInfo text_info = text_encoder_->GetInputInfo(0); + inputs[0].name = text_info.name; + int output_size = text_encoder_->GetOutputInfos().size(); + std::vector outputs(output_size); + text_encoder_->Infer(inputs, &outputs); + + FDTensor text_embeddings; + function::Tile(outputs[0], {num_images_per_prompt, 1, 1}, &text_embeddings); + + // here `guidance_scale` is defined analog to the guidance weight `w` of equation (2) + // of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1` + // corresponds to doing no classifier free guidance. + bool do_classifier_free_guidance = guidance_scale > 1.0; + if (do_classifier_free_guidance) { + std::vector uncond_tokens; + if (negative_prompt.size() == 0) { + uncond_tokens = {""}; + } else if (negative_prompt.size() != batch_size) { + FDASSERT(false, + "negative_prompt has batch size %d, but prompt has batch size " + "%d. Please make sure that passed `negative_prompt` matches the " + "batch size of `prompt`.", + prompts.size(), negative_prompt.size()); + } else { + uncond_tokens = negative_prompt; + } + tokenizer_.EncodeBatchStrings(uncond_tokens, &encodings); + input_ids.clear(); + for (auto& encoding : encodings) { + auto curr_ids = encoding.GetIds(); + input_ids.insert(input_ids.end(), curr_ids.begin(), curr_ids.end()); + } + inputs[0].SetExternalData({batch_size, max_length}, FDDataType::INT64, + input_ids.data()); + text_encoder_->Infer(inputs, &outputs); + FDTensor uncond_embeddings; + function::Tile(outputs[0], {num_images_per_prompt, 1, 1}, + &uncond_embeddings); + function::Concat({uncond_embeddings, text_embeddings}, &text_embeddings); + } + std::vector latents_shape = {batch_size * num_images_per_prompt, + NUM_LATENT_CHANNELS, height / 8, + width / 8}; + auto latents_dtype = text_embeddings.Dtype(); + FDTensor actual_latents; + if (latents == nullptr) { + function::GaussianRandom(latents_shape, &actual_latents, latents_dtype); + } else { + bool result = std::equal(latents_shape.begin(), latents_shape.end(), + latents->Shape().begin()); + FDASSERT(result, "Unexpected latents shape, got %s, expected %s", + Str(latents_shape).c_str(), Str(latents->Shape()).c_str()); + actual_latents = *latents; + } + FDTensor mask_t, mask_image_t; + PrepareMaskAndMaskedImage(image, mask_image, {height / 8, width / 8}, &mask_t, + &mask_image_t); + function::Cast(mask_t, &mask_t, actual_latents.Dtype()); + function::Cast(mask_image_t, &mask_image_t, actual_latents.Dtype()); + + // Get vae encoder output + TensorInfo vae_encoder_info = vae_encoder_->GetInputInfo(0); + mask_image_t.name = vae_encoder_info.name; + outputs.resize(vae_encoder_->GetOutputInfos().size()); + inputs = {mask_image_t}; + vae_encoder_->Infer(inputs, &outputs); + FDTensor masked_image_latents = 0.18215f * outputs[0]; + + std::vector mask_shape(mask_t.Shape().size(), 1); + mask_shape[0] = batch_size * num_images_per_prompt; + function::Tile(mask_t, mask_shape, &mask_t); + + std::vector mask_image_shape(masked_image_latents.Shape().size(), 1); + mask_image_shape[0] = batch_size * num_images_per_prompt; + function::Tile(masked_image_latents, mask_image_shape, &masked_image_latents); + + if (do_classifier_free_guidance) { + function::Concat({mask_t, mask_t}, &mask_t); + function::Concat({masked_image_latents, masked_image_latents}, + &masked_image_latents); + } + int num_channels_mask = mask_t.Shape()[1]; + int num_channels_masked_image = masked_image_latents.Shape()[1]; + FDASSERT( + NUM_LATENT_CHANNELS + num_channels_mask + num_channels_masked_image == + NUM_UNET_INPUT_CHANNELS, + "Incorrect configuration settings! The config of `pipeline.unet` expects" + " %d but received `num_channels_latents`: %d + `num_channels_mask`: %d " + "+ `num_channels_masked_image`: %d" + " = %d. Please verify the config of `pipeline.unet` or your `mask_image` " + "or `image` input.", + NUM_UNET_INPUT_CHANNELS, NUM_LATENT_CHANNELS, num_channels_mask, + num_channels_masked_image, + NUM_LATENT_CHANNELS + num_channels_mask + num_channels_masked_image); + + // set timesteps + scheduler_->SetTimesteps(num_inference_steps); + + // scale the initial noise by the standard deviation required by the scheduler + actual_latents = actual_latents * scheduler_->InitNoiseSigma(); + + auto timestep = scheduler_->GetTimesteps(); + int64_t* timestep_data = reinterpret_cast(timestep.Data()); + outputs.resize(unet_->GetOutputInfos().size()); + inputs.resize(unet_->GetInputInfos().size()); + inputs[2] = std::move(text_embeddings); + auto unet_infos = unet_->GetInputInfos(); + for (int i = 0; i < timestep.Numel(); ++i) { + FDTensor t; + function::Slice(timestep, {0}, {i}, &t); + inputs[1] = t; + // expand the latents if we are doing classifier free guidance + FDTensor latent_model_input; + if (do_classifier_free_guidance) { + function::Concat({actual_latents, actual_latents}, &latent_model_input); + } else { + latent_model_input = actual_latents; + } + // concat latents, mask, masked_image_latnets in the channel dimension + function::Concat({latent_model_input, mask_t, masked_image_latents}, + &latent_model_input, 1); + scheduler_->ScaleModelInput(latent_model_input, &latent_model_input, {t}); + inputs[0] = std::move(latent_model_input); + // predict the noise residual + for (int i = 0; i < unet_infos.size(); ++i) { + inputs[i].name = unet_infos[i].name; + } + unet_->Infer(inputs, &outputs); + FDTensor noise_pred = std::move(outputs[0]); + // perform guidance + if (do_classifier_free_guidance) { + std::vector noise_preds; + int dim0 = noise_pred.Shape()[0]; + function::Split(noise_pred, {dim0 - dim0 / 2, dim0 / 2}, &noise_preds); + noise_pred = + noise_preds[0] + guidance_scale * (noise_preds[1] - noise_preds[0]); + } + + // compute the previous noisy sample x_t -> x_t-1 + int64_t time = reinterpret_cast(t.Data())[0]; + scheduler_->Step(noise_pred, time, actual_latents, &actual_latents); + + // call the callback, if provided + if (callback != nullptr && i % callback_steps == 0) { + callback(i, time, &actual_latents); + } + } + actual_latents = (1.0f / 0.18215f) * actual_latents; + + // Get vae decoder output + int actual_latents_bs = actual_latents.Shape()[0]; + TensorInfo vae_decoder_info = vae_decoder_->GetInputInfo(0); + inputs.resize(1); + outputs.resize(vae_decoder_->GetOutputInfos().size()); + std::vector decoder_reuslt; + for (int i = 0; i < actual_latents_bs; ++i) { + function::Slice(actual_latents, {0}, {i}, {i + 1}, &inputs[0]); + inputs[0].name = vae_decoder_info.name; + vae_decoder_->Infer(inputs, &outputs); + decoder_reuslt.emplace_back(std::move(outputs[0])); + } + FDTensor output_image; + function::Concat(decoder_reuslt, &output_image); + + function::Clip(output_image / 2.0f + 0.5f, 0, 1, &output_image); + function::Transpose(output_image, &output_image, {0, 2, 3, 1}); + + if (output_cv_mat) { + output_image = output_image * 255.0f; + function::Round(output_image, &output_image); + function::Cast(output_image, &output_image, FDDataType::UINT8); + } + int output_batch_size = output_image.Shape()[0]; + output_images->resize(output_batch_size); + for (int i = 0; i < output_batch_size; ++i) { + function::Slice(output_image, {0}, {i}, &(*output_images)[i]); + vision::FDMat mask_fdmat_t = vision::FDMat::Create((*output_images)[i]); + vision::RGB2BGR::Run(&mask_fdmat_t, vision::ProcLib::OPENCV); + mask_fdmat_t.CopyToTensor(&(*output_images)[i]); + } +} +} // namespace fastdeploy diff --git a/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.h b/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.h new file mode 100644 index 000000000..063c370f3 --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/pipeline_stable_diffusion_inpaint.h @@ -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 "./scheduler.h" +#include "fast_tokenizer/tokenizers/clip_fast_tokenizer.h" +#include "fastdeploy/core/fd_tensor.h" +#include "fastdeploy/runtime.h" +#include "opencv2/core/core.hpp" +#include +#include +#include + +namespace fastdeploy { + +class StableDiffusionInpaintPipeline { + public: + typedef void (*callback_ptr)(int, int, FDTensor*); + + StableDiffusionInpaintPipeline( + std::unique_ptr vae_encoder, + std::unique_ptr vae_decoder, + std::unique_ptr text_encoder, std::unique_ptr unet, + std::unique_ptr scheduler, + const paddlenlp::fast_tokenizer::tokenizers_impl::ClipFastTokenizer& + tokenizer); + void Predict(const std::vector& prompts, const cv::Mat& image, + const cv::Mat& mask_image, std::vector* output_images, + int height = 512, int width = 512, int num_inference_steps = 50, + float guidance_scale = 7.5, + const std::vector& negative_prompt = {}, + int num_images_per_prompt = 1, float eta = 0.0, + uint32_t max_length = 77, const FDTensor* latents = nullptr, + bool output_cv_mat = true, callback_ptr callback = nullptr, + int callback_steps = 1); + + private: + void PrepareMaskAndMaskedImage(const cv::Mat& image, const cv::Mat& mask_mat, + const std::vector& shape, + FDTensor* mask, FDTensor* mask_image); + std::unique_ptr vae_encoder_; + std::unique_ptr vae_decoder_; + std::unique_ptr text_encoder_; + std::unique_ptr unet_; + std::unique_ptr scheduler_; + paddlenlp::fast_tokenizer::tokenizers_impl::ClipFastTokenizer tokenizer_; +}; + +} // namespace fastdeploy diff --git a/examples/multimodal/stable_diffusion/cpp/scheduler.h b/examples/multimodal/stable_diffusion/cpp/scheduler.h new file mode 100644 index 000000000..e4dc452de --- /dev/null +++ b/examples/multimodal/stable_diffusion/cpp/scheduler.h @@ -0,0 +1,34 @@ +// 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/core/fd_tensor.h" + +namespace fastdeploy { + +class Scheduler { + public: + virtual void SetTimesteps(int num_inference_steps) = 0; + virtual FDTensor GetTimesteps() = 0; + virtual void Step(const FDTensor& model_output, int timestep, + const FDTensor& sample, FDTensor* prev_sample) = 0; + virtual void ScaleModelInput(const FDTensor& sample, FDTensor* out, + const std::vector& timesteps = {}) = 0; + virtual void AddNoise(const FDTensor& original_samples, const FDTensor& noise, + const FDTensor& timesteps, FDTensor* out) = 0; + virtual float InitNoiseSigma() = 0; +}; + +} // namespace fastdeploy diff --git a/examples/text/ernie-3.0/serving/README.md b/examples/text/ernie-3.0/serving/README.md index 6edc1b790..8b7fbdd9a 100644 --- a/examples/text/ernie-3.0/serving/README.md +++ b/examples/text/ernie-3.0/serving/README.md @@ -51,10 +51,10 @@ models # GPU镜像 docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 # CPU镜像 -docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10 +docker pull paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10 # 运行 -docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v /path/serving/models:/models paddlepaddle/fastdeploy:0.6.0-cpu-only-21.10 bash +docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v /path/serving/models:/models paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10 bash ``` ## 部署模型 @@ -67,7 +67,7 @@ token_cls_rpc_client.py # 序列标注任务发送pipeline预测请求的脚 ``` *注意*:启动服务时,Server的每个python后端进程默认申请`64M`内存,默认启动的docker无法启动多个python后端节点。有两个解决方案: -- 1.启动容器时设置`shm-size`参数, 比如:`docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v /path/serving/models:/models paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash` +- 1.启动容器时设置`shm-size`参数, 比如:`docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v /path/serving/models:/models paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash` - 2.启动服务时设置python后端的`shm-default-byte-size`参数, 设置python后端的默认内存为10M: `tritonserver --model-repository=/models --backend-config=python,shm-default-byte-size=10485760` ### 分类任务 diff --git a/examples/text/uie/serving/README.md b/examples/text/uie/serving/README.md index c2ade2a54..f38ff7c5e 100644 --- a/examples/text/uie/serving/README.md +++ b/examples/text/uie/serving/README.md @@ -34,10 +34,10 @@ models # GPU镜像 docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 # CPU镜像 -docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10 +docker pull paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10 # 运行容器.容器名字为 fd_serving, 并挂载当前目录为容器的 /uie_serving 目录 -docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v `pwd`/:/uie_serving paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash +docker run -it --net=host --name fastdeploy_server --shm-size="1g" -v `pwd`/:/uie_serving paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash # 启动服务(不设置CUDA_VISIBLE_DEVICES环境变量,会拥有所有GPU卡的调度权限) CUDA_VISIBLE_DEVICES=0 fastdeployserver --model-repository=/uie_serving/models --backend-config=python,shm-default-byte-size=10485760 diff --git a/examples/vision/classification/paddleclas/android/README.md b/examples/vision/classification/paddleclas/android/README.md index eba5ceceb..a9262d946 100644 --- a/examples/vision/classification/paddleclas/android/README.md +++ b/examples/vision/classification/paddleclas/android/README.md @@ -125,7 +125,7 @@ option.enableLiteFp16(); model.init(modelFile, paramFile, configFile, option); // Bitmap读取、模型预测、资源释放 同上 ... ``` -更详细的用法请参考 [MainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/examples/MainActivity.java#L207) 中的用法 +更详细的用法请参考 [MainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationMainActivity.java) 中的用法 ## 替换 FastDeploy 预测库和模型 替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-xxx-shared`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models/MobileNetV1_x0_25_infer`。 diff --git a/examples/vision/classification/paddleclas/quantize/README.md b/examples/vision/classification/paddleclas/quantize/README.md old mode 100644 new mode 100755 index 6e3f78b4d..e55f95e26 --- a/examples/vision/classification/paddleclas/quantize/README.md +++ b/examples/vision/classification/paddleclas/quantize/README.md @@ -4,14 +4,14 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) 注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可。 ## 下载量化完成的PaddleClas模型 用户也可以直接下载下表中的量化模型进行部署. Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -33,7 +33,7 @@ Benchmark表格说明: | [MobileNetV1_ssld](https://bj.bcebos.com/paddlehub/fastdeploy/mobilenetv1_ssld_ptq.tar) | Paddle Inference | CPU | 12.29 | 4.68 | None|None|2.62 |77.89 | 71.36 |离线量化 | ### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 Top1 | INT8 Top1 | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 Top1 | INT8 Top1 | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [ResNet50_vd](https://bj.bcebos.com/paddlehub/fastdeploy/resnet50_vd_ptq.tar) | TensorRT | GPU | 4.92| 2.28|2.24|2.23 | 2.21 | 79.12 | 79.06 | 离线量化 | | [ResNet50_vd](https://bj.bcebos.com/paddlehub/fastdeploy/resnet50_vd_ptq.tar) | Paddle-TensorRT | GPU | 4.48|None |2.09|2.10 | 2.14 | 79.12 | 79.06 | 离线量化 | diff --git a/examples/vision/classification/paddleclas/quantize/cpp/README.md b/examples/vision/classification/paddleclas/quantize/cpp/README.md old mode 100644 new mode 100755 index 3dced039c..999cc7fde --- a/examples/vision/classification/paddleclas/quantize/cpp/README.md +++ b/examples/vision/classification/paddleclas/quantize/cpp/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的ResNet50_Vd模型为例, 进行部署,支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) 在本目录执行如下命令即可完成编译,以及量化模型部署. diff --git a/examples/vision/classification/paddleclas/quantize/python/README.md b/examples/vision/classification/paddleclas/quantize/python/README.md old mode 100644 new mode 100755 index 6b874e77a..a7fc4f9d3 --- a/examples/vision/classification/paddleclas/quantize/python/README.md +++ b/examples/vision/classification/paddleclas/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的ResNet50_Vd模型为例, 进行部署 diff --git a/examples/vision/classification/paddleclas/rk1126/README.md b/examples/vision/classification/paddleclas/rv1126/README.md similarity index 61% rename from examples/vision/classification/paddleclas/rk1126/README.md rename to examples/vision/classification/paddleclas/rv1126/README.md index bac6d7bf8..065939a27 100755 --- a/examples/vision/classification/paddleclas/rk1126/README.md +++ b/examples/vision/classification/paddleclas/rv1126/README.md @@ -1,11 +1,11 @@ -# PaddleClas 量化模型在 RK1126 上的部署 -目前 FastDeploy 已经支持基于 PaddleLite 部署 PaddleClas 量化模型到 RK1126 上。 +# PaddleClas 量化模型在 RV1126 上的部署 +目前 FastDeploy 已经支持基于 PaddleLite 部署 PaddleClas 量化模型到 RV1126 上。 模型的量化和量化模型的下载请参考:[模型量化](../quantize/README.md) ## 详细部署文档 -在 RK1126 上只支持 C++ 的部署。 +在 RV1126 上只支持 C++ 的部署。 - [C++部署](cpp) diff --git a/examples/vision/classification/paddleclas/rk1126/cpp/CMakeLists.txt b/examples/vision/classification/paddleclas/rv1126/cpp/CMakeLists.txt similarity index 100% rename from examples/vision/classification/paddleclas/rk1126/cpp/CMakeLists.txt rename to examples/vision/classification/paddleclas/rv1126/cpp/CMakeLists.txt diff --git a/examples/vision/classification/paddleclas/rk1126/cpp/README.md b/examples/vision/classification/paddleclas/rv1126/cpp/README.md similarity index 65% rename from examples/vision/classification/paddleclas/rk1126/cpp/README.md rename to examples/vision/classification/paddleclas/rv1126/cpp/README.md index 6d8ecd151..feaba462f 100755 --- a/examples/vision/classification/paddleclas/rk1126/cpp/README.md +++ b/examples/vision/classification/paddleclas/rv1126/cpp/README.md @@ -1,22 +1,22 @@ -# PaddleClas RK1126开发板 C++ 部署示例 -本目录下提供的 `infer.cc`,可以帮助用户快速完成 PaddleClas 量化模型在 RK1126 上的部署推理加速。 +# PaddleClas RV1126 开发板 C++ 部署示例 +本目录下提供的 `infer.cc`,可以帮助用户快速完成 PaddleClas 量化模型在 RV1126 上的部署推理加速。 ## 部署准备 ### FastDeploy 交叉编译环境准备 -- 1. 软硬件环境满足要求,以及交叉编译环境的准备,请参考:[FastDeploy 交叉编译环境准备](../../../../../../docs/cn/build_and_install/rk1126.md#交叉编译环境搭建) +- 1. 软硬件环境满足要求,以及交叉编译环境的准备,请参考:[FastDeploy 交叉编译环境准备](../../../../../../docs/cn/build_and_install/rv1126.md#交叉编译环境搭建) ### 量化模型准备 - 1. 用户可以直接使用由 FastDeploy 提供的量化模型进行部署。 -- 2. 用户可以使用 FastDeploy 提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署。(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此 yaml 文件, 用户从 FP32 模型文件夹下复制此 yaml 文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用 FastDeploy 提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署。(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的inference_cls.yaml文件, 自行量化的模型文件夹内不包含此 yaml 文件, 用户从 FP32 模型文件夹下复制此 yaml 文件到量化后的模型文件夹内即可.) - 更多量化相关相关信息可查阅[模型量化](../../quantize/README.md) -## 在 RK1126 上部署量化后的 ResNet50_Vd 分类模型 -请按照以下步骤完成在 RK1126 上部署 ResNet50_Vd 量化模型: -1. 交叉编译编译 FastDeploy 库,具体请参考:[交叉编译 FastDeploy](../../../../../../docs/cn/build_and_install/rk1126.md#基于-paddlelite-的-fastdeploy-交叉编译库编译) +## 在 RV1126 上部署量化后的 ResNet50_Vd 分类模型 +请按照以下步骤完成在 RV1126 上部署 ResNet50_Vd 量化模型: +1. 交叉编译编译 FastDeploy 库,具体请参考:[交叉编译 FastDeploy](../../../../../../docs/cn/build_and_install/rv1126.md#基于-paddlelite-的-fastdeploy-交叉编译库编译) 2. 将编译后的库拷贝到当前目录,可使用如下命令: ```bash -cp -r FastDeploy/build/fastdeploy-tmivx/ FastDeploy/examples/vision/classification/paddleclas/rk1126/cpp/ +cp -r FastDeploy/build/fastdeploy-tmivx/ FastDeploy/examples/vision/classification/paddleclas/rv1126/cpp/ ``` 3. 在当前路径下载部署所需的模型和示例图片: @@ -32,7 +32,7 @@ cp -r ILSVRC2012_val_00000010.jpeg images 4. 编译部署示例,可使入如下命令: ```bash mkdir build && cd build -cmake -DCMAKE_TOOLCHAIN_FILE=../fastdeploy-tmivx/timvx.cmake -DFASTDEPLOY_INSTALL_DIR=fastdeploy-tmivx .. +cmake -DCMAKE_TOOLCHAIN_FILE=${PWD}/../fastdeploy-tmivx/timvx.cmake -DFASTDEPLOY_INSTALL_DIR=${PWD}/../fastdeploy-tmivx .. make -j8 make install # 成功编译之后,会生成 install 文件夹,里面有一个运行 demo 和部署所需的库 @@ -41,7 +41,7 @@ make install 5. 基于 adb 工具部署 ResNet50_vd 分类模型到 Rockchip RV1126,可使用如下命令: ```bash # 进入 install 目录 -cd FastDeploy/examples/vision/classification/paddleclas/rk1126/cpp/build/install/ +cd FastDeploy/examples/vision/classification/paddleclas/rv1126/cpp/build/install/ # 如下命令表示:bash run_with_adb.sh 需要运行的demo 模型路径 图片路径 设备的DEVICE_ID bash run_with_adb.sh infer_demo ResNet50_vd_infer ILSVRC2012_val_00000010.jpeg $DEVICE_ID ``` @@ -50,4 +50,4 @@ bash run_with_adb.sh infer_demo ResNet50_vd_infer ILSVRC2012_val_00000010.jpeg $ -需要特别注意的是,在 RK1126 上部署的模型需要是量化后的模型,模型的量化请参考:[模型量化](../../../../../../docs/cn/quantize.md) +需要特别注意的是,在 RV1126 上部署的模型需要是量化后的模型,模型的量化请参考:[模型量化](../../../../../../docs/cn/quantize.md) diff --git a/examples/vision/classification/paddleclas/rk1126/cpp/infer.cc b/examples/vision/classification/paddleclas/rv1126/cpp/infer.cc similarity index 100% rename from examples/vision/classification/paddleclas/rk1126/cpp/infer.cc rename to examples/vision/classification/paddleclas/rv1126/cpp/infer.cc diff --git a/examples/vision/classification/paddleclas/rk1126/cpp/run_with_adb.sh b/examples/vision/classification/paddleclas/rv1126/cpp/run_with_adb.sh similarity index 100% rename from examples/vision/classification/paddleclas/rk1126/cpp/run_with_adb.sh rename to examples/vision/classification/paddleclas/rv1126/cpp/run_with_adb.sh diff --git a/examples/vision/classification/paddleclas/serving/README.md b/examples/vision/classification/paddleclas/serving/README.md index 971e9bbd0..0b4771717 100644 --- a/examples/vision/classification/paddleclas/serving/README.md +++ b/examples/vision/classification/paddleclas/serving/README.md @@ -28,10 +28,10 @@ mv ResNet50_vd_infer/inference.pdiparams models/runtime/1/model.pdiparams # GPU镜像 docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 # CPU镜像 -docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10 +docker pull paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10 # 运行容器.容器名字为 fd_serving, 并挂载当前目录为容器的 /serving 目录 -nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/serving paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash +nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/serving 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 --backend-config=python,shm-default-byte-size=10485760 diff --git a/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java b/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java index dbb76df83..127711767 100644 --- a/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java +++ b/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java @@ -305,6 +305,8 @@ public class DetectionMainActivity extends Activity implements View.OnClickListe // Open camera until the permissions have been granted if (!checkAllPermissions()) { svPreview.disableCamera(); + } else { + svPreview.enableCamera(); } svPreview.onResume(); } diff --git a/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java b/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java index 94a5fdbd0..14217181d 100644 --- a/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java +++ b/examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java @@ -278,6 +278,10 @@ public class CameraSurfaceView extends GLSurfaceView implements Renderer, disableCamera = true; } + public void enableCamera() { + disableCamera = false; + } + public void switchCamera() { releaseCamera(); selectedCameraId = (selectedCameraId + 1) % numberOfCameras; diff --git a/examples/vision/detection/paddledetection/coco_label_list.txt b/examples/vision/detection/paddledetection/coco_label_list.txt deleted file mode 100644 index 941cb4e13..000000000 --- a/examples/vision/detection/paddledetection/coco_label_list.txt +++ /dev/null @@ -1,80 +0,0 @@ -person -bicycle -car -motorcycle -airplane -bus -train -truck -boat -traffic light -fire hydrant -stop sign -parking meter -bench -bird -cat -dog -horse -sheep -cow -elephant -bear -zebra -giraffe -backpack -umbrella -handbag -tie -suitcase -frisbee -skis -snowboard -sports ball -kite -baseball bat -baseball glove -skateboard -surfboard -tennis racket -bottle -wine glass -cup -fork -knife -spoon -bowl -banana -apple -sandwich -orange -broccoli -carrot -hot dog -pizza -donut -cake -chair -couch -potted plant -bed -dining table -toilet -tv -laptop -mouse -remote -keyboard -cell phone -microwave -oven -toaster -sink -refrigerator -book -clock -vase -scissors -teddy bear -hair drier -toothbrush diff --git a/examples/vision/detection/paddledetection/cpp/infer_ppyoloe.cc b/examples/vision/detection/paddledetection/cpp/infer_ppyoloe.cc old mode 100644 new mode 100755 diff --git a/examples/vision/detection/paddledetection/quantize/README.md b/examples/vision/detection/paddledetection/quantize/README.md old mode 100644 new mode 100755 index 8c6f1feee..f0caf8112 --- a/examples/vision/detection/paddledetection/quantize/README.md +++ b/examples/vision/detection/paddledetection/quantize/README.md @@ -4,14 +4,14 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) ## 下载量化完成的PP-YOLOE-l模型 用户也可以直接下载下表中的量化模型进行部署.(点击模型名字即可下载) Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -32,7 +32,7 @@ NOTE: - TensorRT比Paddle-TensorRT快的原因是在runtime移除了multiclass_nms3算子 #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [ppyoloe_crn_l_300e_coco](https://bj.bcebos.com/paddlehub/fastdeploy/ppyoloe_crn_l_300e_coco_qat.tar ) | TensorRT | GPU | 35.75 | 15.42 |20.70|20.85 | 2.32 | 51.4 | 50.7 | 量化蒸馏训练 | | [ppyoloe_crn_l_300e_coco](https://bj.bcebos.com/paddlehub/fastdeploy/ppyoloe_crn_l_300e_coco_qat.tar ) | Paddle-TensorRT | GPU | 33.48 |None | 18.47 |18.03 | 1.81 | 51.4 | 50.5 | 量化蒸馏训练 | diff --git a/examples/vision/detection/paddledetection/quantize/cpp/README.md b/examples/vision/detection/paddledetection/quantize/cpp/README.md old mode 100644 new mode 100755 index 793fc3938..4511eb508 --- a/examples/vision/detection/paddledetection/quantize/cpp/README.md +++ b/examples/vision/detection/paddledetection/quantize/cpp/README.md @@ -9,7 +9,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的infer_cfg.yml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的检测模型仍然需要FP32模型文件夹下的infer_cfg.yml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的PP-YOLOE-l模型为例, 进行部署。支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) 在本目录执行如下命令即可完成编译,以及量化模型部署. diff --git a/examples/vision/detection/paddledetection/quantize/python/README.md b/examples/vision/detection/paddledetection/quantize/python/README.md old mode 100644 new mode 100755 index 3efcd232b..15e0d463e --- a/examples/vision/detection/paddledetection/quantize/python/README.md +++ b/examples/vision/detection/paddledetection/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的infer_cfg.yml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的infer_cfg.yml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的PP-YOLOE-l模型为例, 进行部署 diff --git a/examples/vision/detection/paddledetection/rk1126/download_models_and_libs.sh b/examples/vision/detection/paddledetection/rk1126/download_models_and_libs.sh deleted file mode 100755 index e7a0fca7a..000000000 --- a/examples/vision/detection/paddledetection/rk1126/download_models_and_libs.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e - -DETECTION_MODEL_DIR="$(pwd)/picodet_detection/models" -LIBS_DIR="$(pwd)" - -DETECTION_MODEL_URL="https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/models/picodetv2_relu6_coco_no_fuse.tar.gz" -LIBS_URL="https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/Paddle-Lite-libs.tar.gz" - -download_and_uncompress() { - local url="$1" - local dir="$2" - - echo "Start downloading ${url}" - curl -L ${url} > ${dir}/download.tar.gz - cd ${dir} - tar -zxvf download.tar.gz - rm -f download.tar.gz -} - -download_and_uncompress "${DETECTION_MODEL_URL}" "${DETECTION_MODEL_DIR}" -download_and_uncompress "${LIBS_URL}" "${LIBS_DIR}" - -echo "Download successful!" diff --git a/examples/vision/detection/paddledetection/rk1126/picodet_detection/CMakeLists.txt b/examples/vision/detection/paddledetection/rk1126/picodet_detection/CMakeLists.txt deleted file mode 100755 index 575db78ad..000000000 --- a/examples/vision/detection/paddledetection/rk1126/picodet_detection/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -cmake_minimum_required(VERSION 3.10) -set(CMAKE_SYSTEM_NAME Linux) -if(TARGET_ARCH_ABI STREQUAL "armv8") - set(CMAKE_SYSTEM_PROCESSOR aarch64) - set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc") - set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") -elseif(TARGET_ARCH_ABI STREQUAL "armv7hf") - set(CMAKE_SYSTEM_PROCESSOR arm) - set(CMAKE_C_COMPILER "arm-linux-gnueabihf-gcc") - set(CMAKE_CXX_COMPILER "arm-linux-gnueabihf-g++") -else() - message(FATAL_ERROR "Unknown arch abi ${TARGET_ARCH_ABI}, only support armv8 and armv7hf.") - return() -endif() - -project(object_detection_demo) - -message(STATUS "TARGET ARCH ABI: ${TARGET_ARCH_ABI}") -message(STATUS "PADDLE LITE DIR: ${PADDLE_LITE_DIR}") -include_directories(${PADDLE_LITE_DIR}/include) -link_directories(${PADDLE_LITE_DIR}/libs/${TARGET_ARCH_ABI}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -if(TARGET_ARCH_ABI STREQUAL "armv8") - set(CMAKE_CXX_FLAGS "-march=armv8-a ${CMAKE_CXX_FLAGS}") - set(CMAKE_C_FLAGS "-march=armv8-a ${CMAKE_C_FLAGS}") -elseif(TARGET_ARCH_ABI STREQUAL "armv7hf") - set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_CXX_FLAGS}") - set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_C_FLAGS}" ) -endif() - -include_directories(${PADDLE_LITE_DIR}/libs/${TARGET_ARCH_ABI}/third_party/yaml-cpp/include) -link_directories(${PADDLE_LITE_DIR}/libs/${TARGET_ARCH_ABI}/third_party/yaml-cpp) - -find_package(OpenMP REQUIRED) -if(OpenMP_FOUND OR OpenMP_CXX_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - message(STATUS "Found OpenMP ${OpenMP_VERSION} ${OpenMP_CXX_VERSION}") - message(STATUS "OpenMP C flags: ${OpenMP_C_FLAGS}") - message(STATUS "OpenMP CXX flags: ${OpenMP_CXX_FLAGS}") - message(STATUS "OpenMP OpenMP_CXX_LIB_NAMES: ${OpenMP_CXX_LIB_NAMES}") - message(STATUS "OpenMP OpenMP_CXX_LIBRARIES: ${OpenMP_CXX_LIBRARIES}") -else() - message(FATAL_ERROR "Could not found OpenMP!") - return() -endif() -find_package(OpenCV REQUIRED) -if(OpenCV_FOUND OR OpenCV_CXX_FOUND) - include_directories(${OpenCV_INCLUDE_DIRS}) - message(STATUS "OpenCV library status:") - message(STATUS " version: ${OpenCV_VERSION}") - message(STATUS " libraries: ${OpenCV_LIBS}") - message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") -else() - message(FATAL_ERROR "Could not found OpenCV!") - return() -endif() - - -add_executable(object_detection_demo object_detection_demo.cc) - -target_link_libraries(object_detection_demo paddle_full_api_shared dl ${OpenCV_LIBS} yaml-cpp) diff --git a/examples/vision/detection/paddledetection/rk1126/picodet_detection/README.md b/examples/vision/detection/paddledetection/rk1126/picodet_detection/README.md deleted file mode 100755 index ddebdeb7a..000000000 --- a/examples/vision/detection/paddledetection/rk1126/picodet_detection/README.md +++ /dev/null @@ -1,343 +0,0 @@ -# 目标检测 C++ API Demo 使用指南 - -在 ARMLinux 上实现实时的目标检测功能,此 Demo 有较好的的易用性和扩展性,如在 Demo 中跑自己训练好的模型等。 - - 如果该开发板使用搭载了芯原 NPU (瑞芯微、晶晨、JQL、恩智浦)的 Soc,将有更好的加速效果。 - -## 如何运行目标检测 Demo - -### 环境准备 - -* 准备 ARMLiunx 开发版,将系统刷为 Ubuntu,用于 Demo 编译和运行。请注意,本 Demo 是使用板上编译,而非交叉编译,因此需要图形界面的开发板操作系统。 -* 如果需要使用 芯原 NPU 的计算加速,对 NPU 驱动版本有严格要求,请务必注意事先参考 [芯原 TIM-VX 部署示例](https://paddle-lite.readthedocs.io/zh/develop/demo_guides/verisilicon_timvx.html#id6),将 NPU 驱动改为要求的版本。 -* Paddle Lite 当前已验证的开发板为 Khadas VIM3(芯片为 Amlogic A311d)、荣品 RV1126、荣品RV1109,其它平台用户可自行尝试; - - Khadas VIM3:由于 VIM3 出厂自带 Android 系统,请先刷成 Ubuntu 系统,在此提供刷机教程:[VIM3/3L Linux 文档](https://docs.khadas.com/linux/zh-cn/vim3),其中有详细描述刷机方法。以及系统镜像:VIM3 Linux:VIM3_Ubuntu-gnome-focal_Linux-4.9_arm64_EMMC_V1.0.7-210625:[官方链接](http://dl.khadas.com/firmware/VIM3/Ubuntu/EMMC/VIM3_Ubuntu-gnome-focal_Linux-4.9_arm64_EMMC_V1.0.7-210625.img.xz);[百度云备用链接](https://paddlelite-demo.bj.bcebos.com/devices/verisilicon/firmware/khadas/vim3/VIM3_Ubuntu-gnome-focal_Linux-4.9_arm64_EMMC_V1.0.7-210625.img.xz) - - 荣品 RV1126、1109:由于出场自带 buildroot 系统,如果使用 GUI 界面的 demo,请先刷成 Ubuntu 系统,在此提供刷机教程:[RV1126/1109 教程](https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/os_img/rockchip/RV1126-RV1109%E4%BD%BF%E7%94%A8%E6%8C%87%E5%AF%BC%E6%96%87%E6%A1%A3-V3.0.pdf),[刷机工具](https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/os_img/rockchip/RKDevTool_Release.zip),以及镜像:[1126镜像](https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/os_img/update-pro-rv1126-ubuntu20.04-5-720-1280-v2-20220505.img),[1109镜像](https://paddlelite-demo.bj.bcebos.com/Paddle-Lite-Demo/os_img/update-pro-rv1109-ubuntu20.04-5.5-720-1280-v2-20220429.img)。完整的文档和各种镜像请参考[百度网盘链接](https://pan.baidu.com/s/1Id0LMC0oO2PwR2YcYUAaiQ#list/path=%2F&parentPath=%2Fsharelink2521613171-184070898837664),密码:2345。 -* 准备 usb camera,注意使用 openCV capture 图像时,请注意 usb camera 的 video序列号作为入参。 -* 请注意,瑞芯微芯片不带有 HDMI 接口,图像显示是依赖 MIPI DSI,所以请准备好 MIPI 显示屏(我们提供的镜像是 720*1280 分辨率,网盘中有更多分辨率选择,注意:请选择 camera-gc2093x2 的镜像)。 -* 配置开发板的网络。如果是办公网络红区,可以将开发板和PC用以太网链接,然后PC共享网络给开发板。 -* gcc g++ opencv cmake 的安装(以下所有命令均在设备上操作) - -```bash -$ sudo apt-get update -$ sudo apt-get install gcc g++ make wget unzip libopencv-dev pkg-config -$ wget https://www.cmake.org/files/v3.10/cmake-3.10.3.tar.gz -$ tar -zxvf cmake-3.10.3.tar.gz -$ cd cmake-3.10.3 -$ ./configure -$ make -$ sudo make install -``` - -### 部署步骤 - -1. 将本 repo 上传至 VIM3 开发板,或者直接开发板上下载或者 git clone 本 repo -2. 目标检测 Demo 位于 `Paddle-Lite-Demo/object_detection/linux/picodet_detection` 目录 -3. 进入 `Paddle-Lite-Demo/object_detection/linux` 目录, 终端中执行 `download_models_and_libs.sh` 脚本自动下载模型和 Paddle Lite 预测库 - -```shell -cd Paddle-Lite-Demo/object_detection/linux # 1. 终端中进入 Paddle-Lite-Demo/object_detection/linux -sh download_models_and_libs.sh # 2. 执行脚本下载依赖项 (需要联网) -``` - -下载完成后会出现提示: `Download successful!` -4. 执行用例(保证 ARMLinux 环境准备完成) - -```shell -cd picodet_detection # 1. 终端中进入 -sh build.sh armv8 # 2. 编译 Demo 可执行程序,默认编译 armv8,如果是 32bit 环境,则改成 sh build.sh armv7hf。 -sh run.sh armv8 # 3. 执行物体检测(picodet 模型) demo,会直接开启摄像头,启动图形界面并呈现检测结果。如果是 32bit 环境,则改成 sh run.sh armv7hf -``` - -### Demo 结果如下:(注意,示例的 picodet 仅使用 coco 数据集,在实际场景中效果一般,请使用实际业务场景重新训练) - - demo_view - -## 更新预测库 - -* Paddle Lite 项目:https://github.com/PaddlePaddle/Paddle-Lite - * 参考 [芯原 TIM-VX 部署示例](https://paddle-lite.readthedocs.io/zh/develop/demo_guides/verisilicon_timvx.html#tim-vx),编译预测库 - * 编译最终产物位于 `build.lite.xxx.xxx.xxx` 下的 `inference_lite_lib.xxx.xxx` - * 替换 c++ 库 - * 头文件 - 将生成的 `build.lite.linux.armv8.gcc/inference_lite_lib.armlinux.armv8.nnadapter/cxx/include` 文件夹替换 Demo 中的 `Paddle-Lite-Demo/object_detection/linux/Paddle-Lite/include` - * armv8 - 将生成的 `build.lite.linux.armv8.gcc/inference_lite_lib.armlinux.armv8.nnadapter/cxx/libs/libpaddle_full_api_shared.so、libnnadapter.so、libtim-vx.so、libverisilicon_timvx.so` 库替换 Demo 中的 `Paddle-Lite-Demo/object_detection/linux/Paddle-Lite/libs/armv8/` 目录下同名 so - * armv7hf - 将生成的 `build.lite.linux.armv7hf.gcc/inference_lite_lib.armlinux.armv7hf.nnadapter/cxx/libs/libpaddle_full_api_shared.so、libnnadapter.so、libtim-vx.so、libverisilicon_timvx.so` 库替换 Demo 中的 `Paddle-Lite-Demo/object_detection/linux/Paddle-Lite/libs/armv7hf/` 目录下同名 so - -## Demo 内容介绍 - -先整体介绍下目标检测 Demo 的代码结构,然后再简要地介绍 Demo 每部分功能. - -1. `object_detection_demo.cc`: C++ 预测代码 - -```shell -# 位置: -Paddle-Lite-Demo/object_detection/linux/picodet_detection/object_detection_demo.cc -``` - -2. `models` : 模型文件夹 (执行 download_models_and_libs.sh 后会下载 picodet Paddle 模型), label 使用 Paddle-Lite-Demo/object_detection/assets/labels 目录下 coco_label_list.txt - -```shell -# 位置: -Paddle-Lite-Demo/object_detection/linux/picodet_detection/models/picodetv2_relu6_coco_no_fuse -Paddle-Lite-Demo/object_detection/assets/labels/coco_label_list.txt -``` - -3. `Paddle-Lite`:内含 Paddle-Lite 头文件和 动态库,默认带有 timvx 加速库,以及第三方库 yaml-cpp 用于解析 yml 配置文件(执行 download_models_and_libs.sh 后会下载) - -```shell -# 位置 -# 如果要替换动态库 so,则将新的动态库 so 更新到此目录下 -Paddle-Lite-Demo/object_detection/linux/Paddle-Lite/libs/armv8 -Paddle-Lite-Demo/object_detection/linux/Paddle-Lite/include -``` - -4. `CMakeLists.txt` : C++ 预测代码的编译脚本,用于生成可执行文件 - -```shell -# 位置 -Paddle-Lite-Demo/object_detection/linux/picodet_detection/CMakeLists.txt -# 如果有cmake 编译选项更新,可以在 CMakeLists.txt 进行修改即可,默认编译 armv8 可执行文件; -``` - -5. `build.sh` : 编译脚本 - -```shell -# 位置 -Paddle-Lite-Demo/object_detection/linux/picodet_detection/build.sh -``` - -6. `run.sh` : 运行脚本,请注意设置 arm-aarch,armv8 或者 armv7hf。默认为armv8 - -```shell -# 位置 -Paddle-Lite-Demo/object_detection/linux/picodet_detection/run.sh -``` -- 请注意,运行需要5个元素:测试程序、模型、label 文件、异构配置、yaml 文件。 - -## 代码讲解 (使用 Paddle Lite `C++ API` 执行预测) - -ARMLinux 示例基于 C++ API 开发,调用 Paddle Lite `C++s API` 包括以下五步。更详细的 `API` 描述参考:[Paddle Lite C++ API ](https://paddle-lite.readthedocs.io/zh/latest/api_reference/cxx_api_doc.html)。 - -```c++ -#include -// 引入 C++ API -#include "include/paddle_api.h" -#include "include/paddle_use_ops.h" -#include "include/paddle_use_kernels.h" - -// 使用在线编译模型的方式(等价于使用 opt 工具) - -// 1. 设置 CxxConfig -paddle::lite_api::CxxConfig cxx_config; -std::vector valid_places; -valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kInt8)}); -valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kFloat)}); -// 如果只需要 cpu 计算,那到此结束即可,下面是设置 NPU 的代码段 -valid_places.push_back( - paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kInt8)}); -cxx_config.set_valid_places(valid_places); -std::string device = "verisilicon_timvx"; -cxx_config.set_nnadapter_device_names({device}); -// 设置定制化的异构策略 (如需要) -cxx_config.set_nnadapter_subgraph_partition_config_buffer( - nnadapter_subgraph_partition_config_string); - -// 2. 生成 nb 模型 (等价于 opt 工具的产出) -std::shared_ptr predictor = nullptr; -predictor = paddle::lite_api::CreatePaddlePredictor(cxx_config); -predictor->SaveOptimizedModel( - model_path, paddle::lite_api::LiteModelType::kNaiveBuffer); - -// 3. 设置 MobileConfig -MobileConfig config; -config.set_model_from_file(modelPath); // 设置 NaiveBuffer 格式模型路径 -config.set_power_mode(LITE_POWER_NO_BIND); // 设置 CPU 运行模式 -config.set_threads(4); // 设置工作线程数 - -// 4. 创建 PaddlePredictor -predictor = CreatePaddlePredictor(config); - -// 5. 设置输入数据,注意,如果是带后处理的 picodet ,则是有两个输入 -std::unique_ptr input_tensor(std::move(predictor->GetInput(0))); -input_tensor->Resize({1, 3, 416, 416}); -auto* data = input_tensor->mutable_data(); -// scale_factor tensor -auto scale_factor_tensor = predictor->GetInput(1); -scale_factor_tensor->Resize({1, 2}); -auto scale_factor_data = scale_factor_tensor->mutable_data(); -scale_factor_data[0] = 1.0f; -scale_factor_data[1] = 1.0f; - -// 6. 执行预测 -predictor->run(); - -// 7. 获取输出数据 -std::unique_ptr output_tensor(std::move(predictor->GetOutput(0))); - -``` - -## 如何更新模型和输入/输出预处理 - -### 更新模型 -1. 请参考 PaddleDetection 中 [picodet 重训和全量化文档](https://github.com/PaddlePaddle/PaddleDetection/blob/develop/configs/picodet/FULL_QUANTIZATION.md),基于用户自己数据集重训并且重新全量化 -2. 将模型存放到目录 `object_detection_demo/models/` 下; -3. 模型名字跟工程中模型名字一模一样,即均是使用 `model`、`params`; - -```shell -# shell 脚本 `object_detection_demo/run.sh` -TARGET_ABI=armv8 # for 64bit, such as Amlogic A311D -#TARGET_ABI=armv7hf # for 32bit, such as Rockchip 1109/1126 -if [ -n "$1" ]; then - TARGET_ABI=$1 -fi -export LD_LIBRARY_PATH=../Paddle-Lite/libs/$TARGET_ABI/ -export GLOG_v=0 # Paddle-Lite 日志等级 -export VSI_NN_LOG_LEVEL=0 # TIM-VX 日志等级 -export VIV_VX_ENABLE_GRAPH_TRANSFORM=-pcq:1 # NPU 开启 perchannel 量化模型 -export VIV_VX_SET_PER_CHANNEL_ENTROPY=100 # 同上 -build/object_detection_demo models/picodetv2_relu6_coco_no_fuse ../../assets/labels/coco_label_list.txt models/picodetv2_relu6_coco_no_fuse/subgraph.txt models/picodetv2_relu6_coco_no_fuse/picodet.yml # 执行 Demo 程序,4个 arg 分别为:模型、 label 文件、 自定义异构配置、 yaml -``` - -- 如果需要更新 `label_list` 或者 `yaml` 文件,则修改 `object_detection_demo/run.sh` 中执行命令的第二个和第四个 arg 指定为新的 label 文件和 yaml 配置文件; - -```shell -# 代码文件 `object_detection_demo/rush.sh` -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PADDLE_LITE_DIR}/libs/${TARGET_ARCH_ABI} -build/object_detection_demo {模型} {label} {自定义异构配置文件} {yaml} -``` - -### 更新输入/输出预处理 - -1. 更新输入预处理 -预处理完全根据 yaml 文件来,如果完全按照 PaddleDetection 中 picodet 重训,只需要替换 yaml 文件即可 - -2. 更新输出预处理 -此处需要更新 `object_detection_demo/object_detection_demo.cc` 中的 `postprocess` 方法 - -```c++ -std::vector postprocess(const float *output_data, int64_t output_size, - const std::vector &word_labels, - const float score_threshold, - cv::Mat &output_image, double time) { - std::vector results; - std::vector colors = { - cv::Scalar(237, 189, 101), cv::Scalar(0, 0, 255), - cv::Scalar(102, 153, 153), cv::Scalar(255, 0, 0), - cv::Scalar(9, 255, 0), cv::Scalar(0, 0, 0), - cv::Scalar(51, 153, 51)}; - for (int64_t i = 0; i < output_size; i += 6) { - if (output_data[i + 1] < score_threshold) { - continue; - } - int class_id = static_cast(output_data[i]); - float score = output_data[i + 1]; - RESULT result; - std::string class_name = "Unknown"; - if (word_labels.size() > 0 && class_id >= 0 && - class_id < word_labels.size()) { - class_name = word_labels[class_id]; - } - result.class_name = class_name; - result.score = score; - result.left = output_data[i + 2] / 416; // 此处416根据输入的 HW 得来 - result.top = output_data[i + 3] / 416; - result.right = output_data[i + 4] / 416; - result.bottom = output_data[i + 5] / 416; - int lx = static_cast(result.left * output_image.cols); - int ly = static_cast(result.top * output_image.rows); - int w = static_cast(result.right * output_image.cols) - lx; - int h = static_cast(result.bottom * output_image.rows) - ly; - cv::Rect bounding_box = - cv::Rect(lx, ly, w, h) & - cv::Rect(0, 0, output_image.cols, output_image.rows); - if (w > 0 && h > 0 && score <= 1) { - cv::Scalar color = colors[results.size() % colors.size()]; - cv::rectangle(output_image, bounding_box, color); - cv::rectangle(output_image, cv::Point2d(lx, ly), - cv::Point2d(lx + w, ly - 10), color, -1); - cv::putText(output_image, std::to_string(results.size()) + "." + - class_name + ":" + std::to_string(score), - cv::Point2d(lx, ly), cv::FONT_HERSHEY_PLAIN, 1, - cv::Scalar(255, 255, 255)); - results.push_back(result); - } - } - return results; -} -``` - -## 更新模型后,自定义 NPU-CPU 异构配置(如需使用 NPU 加速) -由于使用芯原 NPU 在 8bit 量化的情况下有最优的性能,因此部署时,我们往往会考虑量化 - - 由于量化可能会引入一定程度的精度问题,所以我们可以通过自定义的异构定制,来将部分有精度问题的 layer 异构至cpu,从而达到最优的精度 - -### 第一步,确定模型量化后在 arm cpu 上的精度 -如果在 arm cpu 上,精度都无法满足,那量化本身就是失败的,此时可以考虑修改训练集或者预处理。 - - 修改 Demo 程序,仅用 arm cpu 计算 -```c++ -paddle::lite_api::CxxConfig cxx_config; -std::vector valid_places; -valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kInt8)}); -valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kFloat)}); -// 仅用 arm cpu 计算, 注释如下代码即可 -/* -valid_places.push_back( - paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kInt8)}); -valid_places.push_back( - paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kFloat)}); -*/ -``` -如果 arm cpu 计算结果精度达标,则继续 - -### 第二步,获取整网拓扑信息 - - 回退第一步的修改,不再注释,使用 NPU 加速 - - 运行 Demo,如果此时精度良好,则无需参考后面步骤,模型部署和替换非常顺利,enjoy it。 - - 如果精度不行,请参考后续步骤。 - -### 第三步,获取整网拓扑信息 - - 回退第一步的修改,使用 - - 修改 run.sh ,将其中 export GLOG_v=0 改为 export GLOG_v=5 - - 运行 Demo,等摄像头启动,即可 ctrl+c 关闭 Demo - - 收集日志,搜索关键字 "subgraph operators" 随后那一段,便是整个模型的拓扑信息,其格式如下: - - 每行记录由『算子类型:输入张量名列表:输出张量名列表』组成(即以分号分隔算子类型、输入和输出张量名列表),以逗号分隔输入、输出张量名列表中的每个张量名; - - 示例说明: - ``` - op_type0:var_name0,var_name1:var_name2 表示将算子类型为 op_type0、输入张量为var_name0 和 var_name1、输出张量为 var_name2 的节点强制运行在 ARM CPU 上 - ``` - -### 第四步,修改异构配置文件 - - 首先看到示例 Demo 中 Paddle-Lite-Demo/object_detection/linux/picodet_detection/models/picodetv2_relu6_coco_no_fuse 目录下的 subgraph.txt 文件。(feed 和 fetch 分别代表整个模型的输入和输入) - ``` - feed:feed:scale_factor - feed:feed:image - - sqrt:tmp_3:sqrt_0.tmp_0 - reshape2:sqrt_0.tmp_0:reshape2_0.tmp_0,reshape2_0.tmp_1 - - matmul_v2:softmax_0.tmp_0,auto_113_:linear_0.tmp_0 - reshape2:linear_0.tmp_0:reshape2_2.tmp_0,reshape2_2.tmp_1 - - sqrt:tmp_6:sqrt_1.tmp_0 - reshape2:sqrt_1.tmp_0:reshape2_3.tmp_0,reshape2_3.tmp_1 - - matmul_v2:softmax_1.tmp_0,auto_113_:linear_1.tmp_0 - reshape2:linear_1.tmp_0:reshape2_5.tmp_0,reshape2_5.tmp_1 - - sqrt:tmp_9:sqrt_2.tmp_0 - reshape2:sqrt_2.tmp_0:reshape2_6.tmp_0,reshape2_6.tmp_1 - - matmul_v2:softmax_2.tmp_0,auto_113_:linear_2.tmp_0 - ... - ``` - - 在 txt 中的都是需要异构至 cpu 计算的 layer,在示例 Demo 中,我们把 picodet 后处理的部分异构至 arm cpu 做计算,不必担心,Paddle-Lite 的 arm kernel 性能也是非常卓越。 - - 如果新训练的模型没有额外修改 layer,则直接复制使用示例 Demo 中的 subgraph.txt 即可 - - 此时 ./run.sh 看看精度是否符合预期,如果精度符合预期,恭喜,可以跳过本章节,enjoy it。 - - 如果精度不符合预期,则将上文『第二步,获取整网拓扑信息』中获取的拓扑信息,从 "feed" 之后第一行,直到 "sqrt" 之前,都复制进 sugraph.txt。这一步代表了将大量的 backbone 部分算子放到 arm cpu 计算。 - - 此时 ./run.sh 看看精度是否符合预期,如果精度达标,那说明在 backbone 中确实存在引入 NPU 精度异常的层(再次重申,在 subgraph.txt 的代表强制在 arm cpu 计算)。 - - 逐行删除、成片删除、二分法,发挥开发人员的耐心,找到引入 NPU 精度异常的 layer,将其留在 subgraph.txt 中,按照经验,如果有 NPU 精度问题,可能会有 1~5 层conv layer 需要异构。 - - 剩余没有精度问题的 layer 在 subgraph.txt 中删除即可 diff --git a/examples/vision/detection/paddledetection/rk1126/picodet_detection/build.sh b/examples/vision/detection/paddledetection/rk1126/picodet_detection/build.sh deleted file mode 100755 index 1219c481b..000000000 --- a/examples/vision/detection/paddledetection/rk1126/picodet_detection/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -USE_FULL_API=TRUE -# configure -TARGET_ARCH_ABI=armv8 # for RK3399, set to default arch abi -#TARGET_ARCH_ABI=armv7hf # for Raspberry Pi 3B -PADDLE_LITE_DIR=../Paddle-Lite -THIRD_PARTY_DIR=./third_party -if [ "x$1" != "x" ]; then - TARGET_ARCH_ABI=$1 -fi - -# build -rm -rf build -mkdir build -cd build -cmake -DPADDLE_LITE_DIR=${PADDLE_LITE_DIR} -DTARGET_ARCH_ABI=${TARGET_ARCH_ABI} -DTHIRD_PARTY_DIR=${THIRD_PARTY_DIR} .. -make diff --git a/examples/vision/detection/paddledetection/rk1126/picodet_detection/object_detection_demo.cc b/examples/vision/detection/paddledetection/rk1126/picodet_detection/object_detection_demo.cc deleted file mode 100644 index 8c132dea2..000000000 --- a/examples/vision/detection/paddledetection/rk1126/picodet_detection/object_detection_demo.cc +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright (c) 2019 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 "paddle_api.h" -#include "yaml-cpp/yaml.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int WARMUP_COUNT = 0; -int REPEAT_COUNT = 1; -const int CPU_THREAD_NUM = 2; -const paddle::lite_api::PowerMode CPU_POWER_MODE = - paddle::lite_api::PowerMode::LITE_POWER_HIGH; -const std::vector INPUT_SHAPE = {1, 3, 416, 416}; -std::vector INPUT_MEAN = {0.f, 0.f, 0.f}; -std::vector INPUT_STD = {1.f, 1.f, 1.f}; -float INPUT_SCALE = 1 / 255.f; -const float SCORE_THRESHOLD = 0.35f; - -struct RESULT { - std::string class_name; - float score; - float left; - float top; - float right; - float bottom; -}; - -inline int64_t get_current_us() { - struct timeval time; - gettimeofday(&time, NULL); - return 1000000LL * (int64_t)time.tv_sec + (int64_t)time.tv_usec; -} - -bool read_file(const std::string &filename, std::vector *contents, - bool binary = true) { - FILE *fp = fopen(filename.c_str(), binary ? "rb" : "r"); - if (!fp) - return false; - fseek(fp, 0, SEEK_END); - size_t size = ftell(fp); - fseek(fp, 0, SEEK_SET); - contents->clear(); - contents->resize(size); - size_t offset = 0; - char *ptr = reinterpret_cast(&(contents->at(0))); - while (offset < size) { - size_t already_read = fread(ptr, 1, size - offset, fp); - offset += already_read; - ptr += already_read; - } - fclose(fp); - return true; -} - -std::vector load_labels(const std::string &path) { - std::ifstream file; - std::vector labels; - file.open(path); - while (file) { - std::string line; - std::getline(file, line); - labels.push_back(line); - } - file.clear(); - file.close(); - return labels; -} - -bool load_yaml_config(std::string yaml_path) { - YAML::Node cfg; - try { - std::cout << "before loadFile" << std::endl; - cfg = YAML::LoadFile(yaml_path); - } catch (YAML::BadFile &e) { - std::cout << "Failed to load yaml file " << yaml_path - << ", maybe you should check this file." << std::endl; - return false; - } - auto preprocess_cfg = cfg["TestReader"]["sample_transforms"]; - for (const auto &op : preprocess_cfg) { - if (!op.IsMap()) { - std::cout << "Require the transform information in yaml be Map type." - << std::endl; - std::abort(); - } - auto op_name = op.begin()->first.as(); - if (op_name == "NormalizeImage") { - INPUT_MEAN = op.begin()->second["mean"].as>(); - INPUT_STD = op.begin()->second["std"].as>(); - INPUT_SCALE = op.begin()->second["scale"].as(); - } - } - return true; -} - -void preprocess(cv::Mat &input_image, std::vector &input_mean, - std::vector &input_std, float input_scale, - int input_width, int input_height, float *input_data) { - cv::Mat resize_image; - cv::resize(input_image, resize_image, cv::Size(input_width, input_height), 0, - 0); - if (resize_image.channels() == 4) { - cv::cvtColor(resize_image, resize_image, cv::COLOR_BGRA2RGB); - } - cv::Mat norm_image; - resize_image.convertTo(norm_image, CV_32FC3, input_scale); - // NHWC->NCHW - int image_size = input_height * input_width; - const float *image_data = reinterpret_cast(norm_image.data); - float32x4_t vmean0 = vdupq_n_f32(input_mean[0]); - float32x4_t vmean1 = vdupq_n_f32(input_mean[1]); - float32x4_t vmean2 = vdupq_n_f32(input_mean[2]); - float32x4_t vscale0 = vdupq_n_f32(1.0f / input_std[0]); - float32x4_t vscale1 = vdupq_n_f32(1.0f / input_std[1]); - float32x4_t vscale2 = vdupq_n_f32(1.0f / input_std[2]); - float *input_data_c0 = input_data; - float *input_data_c1 = input_data + image_size; - float *input_data_c2 = input_data + image_size * 2; - int i = 0; - for (; i < image_size - 3; i += 4) { - float32x4x3_t vin3 = vld3q_f32(image_data); - float32x4_t vsub0 = vsubq_f32(vin3.val[0], vmean0); - float32x4_t vsub1 = vsubq_f32(vin3.val[1], vmean1); - float32x4_t vsub2 = vsubq_f32(vin3.val[2], vmean2); - float32x4_t vs0 = vmulq_f32(vsub0, vscale0); - float32x4_t vs1 = vmulq_f32(vsub1, vscale1); - float32x4_t vs2 = vmulq_f32(vsub2, vscale2); - vst1q_f32(input_data_c0, vs0); - vst1q_f32(input_data_c1, vs1); - vst1q_f32(input_data_c2, vs2); - image_data += 12; - input_data_c0 += 4; - input_data_c1 += 4; - input_data_c2 += 4; - } - for (; i < image_size; i++) { - *(input_data_c0++) = (*(image_data++) - input_mean[0]) / input_std[0]; - *(input_data_c1++) = (*(image_data++) - input_mean[1]) / input_std[1]; - *(input_data_c2++) = (*(image_data++) - input_mean[2]) / input_std[2]; - } -} - -std::vector postprocess(const float *output_data, int64_t output_size, - const std::vector &word_labels, - const float score_threshold, - cv::Mat &output_image, double time) { - std::vector results; - std::vector colors = { - cv::Scalar(237, 189, 101), cv::Scalar(0, 0, 255), - cv::Scalar(102, 153, 153), cv::Scalar(255, 0, 0), - cv::Scalar(9, 255, 0), cv::Scalar(0, 0, 0), - cv::Scalar(51, 153, 51)}; - for (int64_t i = 0; i < output_size; i += 6) { - if (output_data[i + 1] < score_threshold) { - continue; - } - int class_id = static_cast(output_data[i]); - float score = output_data[i + 1]; - RESULT result; - std::string class_name = "Unknown"; - if (word_labels.size() > 0 && class_id >= 0 && - class_id < word_labels.size()) { - class_name = word_labels[class_id]; - } - result.class_name = class_name; - result.score = score; - result.left = output_data[i + 2] / 416; - result.top = output_data[i + 3] / 416; - result.right = output_data[i + 4] / 416; - result.bottom = output_data[i + 5] / 416; - int lx = static_cast(result.left * output_image.cols); - int ly = static_cast(result.top * output_image.rows); - int w = static_cast(result.right * output_image.cols) - lx; - int h = static_cast(result.bottom * output_image.rows) - ly; - cv::Rect bounding_box = - cv::Rect(lx, ly, w, h) & - cv::Rect(0, 0, output_image.cols, output_image.rows); - if (w > 0 && h > 0 && score <= 1) { - cv::Scalar color = colors[results.size() % colors.size()]; - cv::rectangle(output_image, bounding_box, color); - cv::rectangle(output_image, cv::Point2d(lx, ly), - cv::Point2d(lx + w, ly - 10), color, -1); - cv::putText(output_image, std::to_string(results.size()) + "." + - class_name + ":" + std::to_string(score), - cv::Point2d(lx, ly), cv::FONT_HERSHEY_PLAIN, 1, - cv::Scalar(255, 255, 255)); - results.push_back(result); - } - } - return results; -} - -cv::Mat process(cv::Mat &input_image, std::vector &word_labels, - std::shared_ptr &predictor) { - // Preprocess image and fill the data of input tensor - std::unique_ptr input_tensor( - std::move(predictor->GetInput(0))); - input_tensor->Resize(INPUT_SHAPE); - int input_width = INPUT_SHAPE[3]; - int input_height = INPUT_SHAPE[2]; - auto *input_data = input_tensor->mutable_data(); -#if 1 - // scale_factor tensor - auto scale_factor_tensor = predictor->GetInput(1); - scale_factor_tensor->Resize({1, 2}); - auto scale_factor_data = scale_factor_tensor->mutable_data(); - scale_factor_data[0] = 1.0f; - scale_factor_data[1] = 1.0f; -#endif - - double preprocess_start_time = get_current_us(); - preprocess(input_image, INPUT_MEAN, INPUT_STD, INPUT_SCALE, input_width, - input_height, input_data); - double preprocess_end_time = get_current_us(); - double preprocess_time = - (preprocess_end_time - preprocess_start_time) / 1000.0f; - - double prediction_time; - // Run predictor - // warm up to skip the first inference and get more stable time, remove it in - // actual products - for (int i = 0; i < WARMUP_COUNT; i++) { - predictor->Run(); - } - // repeat to obtain the average time, set REPEAT_COUNT=1 in actual products - double max_time_cost = 0.0f; - double min_time_cost = std::numeric_limits::max(); - double total_time_cost = 0.0f; - for (int i = 0; i < REPEAT_COUNT; i++) { - auto start = get_current_us(); - predictor->Run(); - auto end = get_current_us(); - double cur_time_cost = (end - start) / 1000.0f; - if (cur_time_cost > max_time_cost) { - max_time_cost = cur_time_cost; - } - if (cur_time_cost < min_time_cost) { - min_time_cost = cur_time_cost; - } - total_time_cost += cur_time_cost; - prediction_time = total_time_cost / REPEAT_COUNT; - printf("iter %d cost: %f ms\n", i, cur_time_cost); - } - printf("warmup: %d repeat: %d, average: %f ms, max: %f ms, min: %f ms\n", - WARMUP_COUNT, REPEAT_COUNT, prediction_time, max_time_cost, - min_time_cost); - - // Get the data of output tensor and postprocess to output detected objects - std::unique_ptr output_tensor( - std::move(predictor->GetOutput(0))); - const float *output_data = output_tensor->mutable_data(); - int64_t output_size = 1; - for (auto dim : output_tensor->shape()) { - output_size *= dim; - } - cv::Mat output_image = input_image.clone(); - double postprocess_start_time = get_current_us(); - std::vector results = - postprocess(output_data, output_size, word_labels, SCORE_THRESHOLD, - output_image, prediction_time); - double postprocess_end_time = get_current_us(); - double postprocess_time = - (postprocess_end_time - postprocess_start_time) / 1000.0f; - - printf("results: %d\n", results.size()); - for (int i = 0; i < results.size(); i++) { - printf("[%d] %s - %f %f,%f,%f,%f\n", i, results[i].class_name.c_str(), - results[i].score, results[i].left, results[i].top, results[i].right, - results[i].bottom); - } - printf("Preprocess time: %f ms\n", preprocess_time); - printf("Prediction time: %f ms\n", prediction_time); - printf("Postprocess time: %f ms\n\n", postprocess_time); - - return output_image; -} - -int main(int argc, char **argv) { - if (argc < 5 || argc == 6) { - printf("Usage: \n" - "./object_detection_demo model_dir label_path [input_image_path] " - "[output_image_path]" - "use images from camera if input_image_path and input_image_path " - "isn't provided."); - return -1; - } - - std::string model_path = argv[1]; - std::string label_path = argv[2]; - std::vector word_labels = load_labels(label_path); - std::string nnadapter_subgraph_partition_config_path = argv[3]; - - std::string yaml_path = argv[4]; - if (yaml_path != "null") { - load_yaml_config(yaml_path); - } - - // Run inference by using full api with CxxConfig - paddle::lite_api::CxxConfig cxx_config; - if (1) { // combined model - cxx_config.set_model_file(model_path + "/model"); - cxx_config.set_param_file(model_path + "/params"); - } else { - cxx_config.set_model_dir(model_path); - } - cxx_config.set_threads(CPU_THREAD_NUM); - cxx_config.set_power_mode(CPU_POWER_MODE); - - std::shared_ptr predictor = nullptr; - std::vector valid_places; - valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kInt8)}); - valid_places.push_back( - paddle::lite_api::Place{TARGET(kARM), PRECISION(kFloat)}); - valid_places.push_back( - paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kInt8)}); - valid_places.push_back( - paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kFloat)}); - cxx_config.set_valid_places(valid_places); - std::string device = "verisilicon_timvx"; - cxx_config.set_nnadapter_device_names({device}); - // cxx_config.set_nnadapter_context_properties(nnadapter_context_properties); - - // cxx_config.set_nnadapter_model_cache_dir(nnadapter_model_cache_dir); - // Set the subgraph custom partition configuration file - - if (!nnadapter_subgraph_partition_config_path.empty()) { - std::vector nnadapter_subgraph_partition_config_buffer; - if (read_file(nnadapter_subgraph_partition_config_path, - &nnadapter_subgraph_partition_config_buffer, false)) { - if (!nnadapter_subgraph_partition_config_buffer.empty()) { - std::string nnadapter_subgraph_partition_config_string( - nnadapter_subgraph_partition_config_buffer.data(), - nnadapter_subgraph_partition_config_buffer.size()); - cxx_config.set_nnadapter_subgraph_partition_config_buffer( - nnadapter_subgraph_partition_config_string); - } - } else { - printf("Failed to load the subgraph custom partition configuration file " - "%s\n", - nnadapter_subgraph_partition_config_path.c_str()); - } - } - - try { - predictor = paddle::lite_api::CreatePaddlePredictor(cxx_config); - predictor->SaveOptimizedModel( - model_path, paddle::lite_api::LiteModelType::kNaiveBuffer); - } catch (std::exception e) { - printf("An internal error occurred in PaddleLite(cxx config).\n"); - } - - paddle::lite_api::MobileConfig config; - config.set_model_from_file(model_path + ".nb"); - config.set_threads(CPU_THREAD_NUM); - config.set_power_mode(CPU_POWER_MODE); - config.set_nnadapter_device_names({device}); - predictor = - paddle::lite_api::CreatePaddlePredictor( - config); - if (argc > 5) { - WARMUP_COUNT = 1; - REPEAT_COUNT = 5; - std::string input_image_path = argv[5]; - std::string output_image_path = argv[6]; - cv::Mat input_image = cv::imread(input_image_path); - cv::Mat output_image = process(input_image, word_labels, predictor); - cv::imwrite(output_image_path, output_image); - cv::imshow("Object Detection Demo", output_image); - cv::waitKey(0); - } else { - cv::VideoCapture cap(1); - cap.set(cv::CAP_PROP_FRAME_WIDTH, 640); - cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480); - if (!cap.isOpened()) { - return -1; - } - while (1) { - cv::Mat input_image; - cap >> input_image; - cv::Mat output_image = process(input_image, word_labels, predictor); - cv::imshow("Object Detection Demo", output_image); - if (cv::waitKey(1) == char('q')) { - break; - } - } - cap.release(); - cv::destroyAllWindows(); - } - return 0; -} diff --git a/examples/vision/detection/paddledetection/rk1126/picodet_detection/run.sh b/examples/vision/detection/paddledetection/rk1126/picodet_detection/run.sh deleted file mode 100755 index a6025104a..000000000 --- a/examples/vision/detection/paddledetection/rk1126/picodet_detection/run.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -#run - -TARGET_ABI=armv8 # for 64bit -#TARGET_ABI=armv7hf # for 32bit -if [ -n "$1" ]; then - TARGET_ABI=$1 -fi -export LD_LIBRARY_PATH=../Paddle-Lite/libs/$TARGET_ABI/ -export GLOG_v=0 -export VSI_NN_LOG_LEVEL=0 -export VIV_VX_ENABLE_GRAPH_TRANSFORM=-pcq:1 -export VIV_VX_SET_PER_CHANNEL_ENTROPY=100 -export TIMVX_BATCHNORM_FUSION_MAX_ALLOWED_QUANT_SCALE_DEVIATION=30000 -build/object_detection_demo models/picodetv2_relu6_coco_no_fuse ../../assets/labels/coco_label_list.txt models/picodetv2_relu6_coco_no_fuse/subgraph.txt models/picodetv2_relu6_coco_no_fuse/picodet.yml diff --git a/examples/vision/detection/paddledetection/rknpu2/README.md b/examples/vision/detection/paddledetection/rknpu2/README.md index d5f339db5..98f1ada10 100644 --- a/examples/vision/detection/paddledetection/rknpu2/README.md +++ b/examples/vision/detection/paddledetection/rknpu2/README.md @@ -113,5 +113,7 @@ Preprocess: type: Resize ``` +## 其他链接 +- [Cpp部署](./cpp) - [Python部署](./python) - [视觉模型预测结果](../../../../../docs/api/vision_results/) diff --git a/examples/vision/detection/paddledetection/rv1126/README.md b/examples/vision/detection/paddledetection/rv1126/README.md new file mode 100755 index 000000000..ff1d58bab --- /dev/null +++ b/examples/vision/detection/paddledetection/rv1126/README.md @@ -0,0 +1,11 @@ +# PP-YOLOE 量化模型在 RV1126 上的部署 +目前 FastDeploy 已经支持基于 PaddleLite 部署 PP-YOLOE 量化模型到 RV1126 上。 + +模型的量化和量化模型的下载请参考:[模型量化](../quantize/README.md) + + +## 详细部署文档 + +在 RV1126 上只支持 C++ 的部署。 + +- [C++部署](cpp) diff --git a/examples/vision/detection/paddledetection/rv1126/cpp/CMakeLists.txt b/examples/vision/detection/paddledetection/rv1126/cpp/CMakeLists.txt new file mode 100755 index 000000000..7a145177e --- /dev/null +++ b/examples/vision/detection/paddledetection/rv1126/cpp/CMakeLists.txt @@ -0,0 +1,38 @@ +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}) +include_directories(${FastDeploy_INCLUDE_DIRS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer_ppyoloe.cc) +# 添加FastDeploy库依赖 +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) + +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build/install) + +install(TARGETS infer_demo DESTINATION ./) + +install(DIRECTORY models DESTINATION ./) +install(DIRECTORY images DESTINATION ./) +# install(DIRECTORY run_with_adb.sh DESTINATION ./) + +file(GLOB FASTDEPLOY_LIBS ${FASTDEPLOY_INSTALL_DIR}/lib/*) +install(PROGRAMS ${FASTDEPLOY_LIBS} DESTINATION lib) + +file(GLOB OPENCV_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/opencv/lib/lib*) +install(PROGRAMS ${OPENCV_LIBS} DESTINATION lib) + +file(GLOB PADDLELITE_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/lib*) +install(PROGRAMS ${PADDLELITE_LIBS} DESTINATION lib) + +file(GLOB TIMVX_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/verisilicon_timvx/*) +install(PROGRAMS ${TIMVX_LIBS} DESTINATION lib) + +file(GLOB ADB_TOOLS run_with_adb.sh) +install(PROGRAMS ${ADB_TOOLS} DESTINATION ./) diff --git a/examples/vision/detection/paddledetection/rv1126/cpp/README.md b/examples/vision/detection/paddledetection/rv1126/cpp/README.md new file mode 100755 index 000000000..5b366bd83 --- /dev/null +++ b/examples/vision/detection/paddledetection/rv1126/cpp/README.md @@ -0,0 +1,55 @@ +# PP-YOLOE 量化模型 C++ 部署示例 + +本目录下提供的 `infer.cc`,可以帮助用户快速完成 PP-YOLOE 量化模型在 RV1126 上的部署推理加速。 + +## 部署准备 +### FastDeploy 交叉编译环境准备 +- 1. 软硬件环境满足要求,以及交叉编译环境的准备,请参考:[FastDeploy 交叉编译环境准备](../../../../../../docs/cn/build_and_install/rv1126.md#交叉编译环境搭建) + +### 模型准备 +- 1. 用户可以直接使用由 FastDeploy 提供的量化模型进行部署。 +- 2. 用户可以先使用 PaddleDetection 自行导出 Float32 模型,注意导出模型模型时设置参数:use_shared_conv=False,更多细节请参考:[PP-YOLOE](https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.4/configs/ppyoloe) +- 3. 用户可以使用 FastDeploy 提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署。(注意: 推理量化后的检测模型仍然需要FP32模型文件夹下的 infer_cfg.yml 文件,自行量化的模型文件夹内不包含此 yaml 文件,用户从 FP32 模型文件夹下复制此yaml文件到量化后的模型文件夹内即可。) +- 更多量化相关相关信息可查阅[模型量化](../../quantize/README.md) + +## 在 RV1126 上部署量化后的 PP-YOLOE 检测模型 +请按照以下步骤完成在 RV1126 上部署 PP-YOLOE 量化模型: +1. 交叉编译编译 FastDeploy 库,具体请参考:[交叉编译 FastDeploy](../../../../../../docs/cn/build_and_install/rv1126.md#基于-paddlelite-的-fastdeploy-交叉编译库编译) + +2. 将编译后的库拷贝到当前目录,可使用如下命令: +```bash +cp -r FastDeploy/build/fastdeploy-tmivx/ FastDeploy/examples/vision/detection/yolov5/rv1126/cpp +``` + +3. 在当前路径下载部署所需的模型和示例图片: +```bash +mkdir models && mkdir images +wget https://bj.bcebos.com/fastdeploy/models/ppyoloe_noshare_qat.tar.gz +tar -xvf ppyoloe_noshare_qat.tar.gz +cp -r ppyoloe_noshare_qat models +wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg +cp -r 000000014439.jpg images +``` + +4. 编译部署示例,可使入如下命令: +```bash +mkdir build && cd build +cmake -DCMAKE_TOOLCHAIN_FILE=${PWD}/../fastdeploy-tmivx/timvx.cmake -DFASTDEPLOY_INSTALL_DIR=${PWD}/../fastdeploy-tmivx .. +make -j8 +make install +# 成功编译之后,会生成 install 文件夹,里面有一个运行 demo 和部署所需的库 +``` + +5. 基于 adb 工具部署 PP-YOLOE 检测模型到 Rockchip RV1126,可使用如下命令: +```bash +# 进入 install 目录 +cd FastDeploy/examples/vision/detection/paddledetection/rv1126/cpp/build/install/ +# 如下命令表示:bash run_with_adb.sh 需要运行的demo 模型路径 图片路径 设备的DEVICE_ID +bash run_with_adb.sh infer_demo ppyoloe_noshare_qat 000000014439.jpg $DEVICE_ID +``` + +部署成功后运行结果如下: + + + +需要特别注意的是,在 RV1126 上部署的模型需要是量化后的模型,模型的量化请参考:[模型量化](../../../../../../docs/cn/quantize.md) diff --git a/examples/vision/detection/paddledetection/rv1126/cpp/infer_ppyoloe.cc b/examples/vision/detection/paddledetection/rv1126/cpp/infer_ppyoloe.cc new file mode 100755 index 000000000..77368584f --- /dev/null +++ b/examples/vision/detection/paddledetection/rv1126/cpp/infer_ppyoloe.cc @@ -0,0 +1,66 @@ +// 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) { + auto model_file = model_dir + sep + "model.pdmodel"; + auto params_file = model_dir + sep + "model.pdiparams"; + auto config_file = model_dir + sep + "infer_cfg.yml"; + auto subgraph_file = model_dir + sep + "subgraph.txt"; + + fastdeploy::RuntimeOption option; + option.UseTimVX(); + option.SetLiteSubgraphPartitionPath(subgraph_file); + + auto model = fastdeploy::vision::detection::PPYOLOE(model_file, params_file, + config_file, option); + assert(model.Initialized()); + + auto im = cv::imread(image_file); + + fastdeploy::vision::DetectionResult 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::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 < 3) { + std::cout << "Usage: infer_demo path/to/quant_model " + "path/to/image " + "run_option, " + "e.g ./infer_demo ./PPYOLOE_L_quant ./test.jpeg" + << std::endl; + return -1; + } + + std::string model_dir = argv[1]; + std::string test_image = argv[2]; + InitAndInfer(model_dir, test_image); + return 0; +} diff --git a/examples/vision/detection/paddledetection/rv1126/cpp/run_with_adb.sh b/examples/vision/detection/paddledetection/rv1126/cpp/run_with_adb.sh new file mode 100755 index 000000000..dd7d7b47d --- /dev/null +++ b/examples/vision/detection/paddledetection/rv1126/cpp/run_with_adb.sh @@ -0,0 +1,47 @@ +#!/bin/bash +HOST_SPACE=${PWD} +echo ${HOST_SPACE} +WORK_SPACE=/data/local/tmp/test + +# The first parameter represents the demo name +DEMO_NAME=image_classification_demo +if [ -n "$1" ]; then + DEMO_NAME=$1 +fi + +# The second parameter represents the model name +MODEL_NAME=mobilenet_v1_fp32_224 +if [ -n "$2" ]; then + MODEL_NAME=$2 +fi + +# The third parameter indicates the name of the image to be tested +IMAGE_NAME=0001.jpg +if [ -n "$3" ]; then + IMAGE_NAME=$3 +fi + +# The fourth parameter represents the ID of the device +ADB_DEVICE_NAME= +if [ -n "$4" ]; then + ADB_DEVICE_NAME="-s $4" +fi + +# Set the environment variables required during the running process +EXPORT_ENVIRONMENT_VARIABLES="export GLOG_v=5; export SUBGRAPH_ONLINE_MODE=true; export RKNPU_LOGLEVEL=5; export RKNN_LOG_LEVEL=5; ulimit -c unlimited; export VIV_VX_ENABLE_GRAPH_TRANSFORM=-pcq:1; export VIV_VX_SET_PER_CHANNEL_ENTROPY=100; export TIMVX_BATCHNORM_FUSION_MAX_ALLOWED_QUANT_SCALE_DEVIATION=300000; export VSI_NN_LOG_LEVEL=5;" + +EXPORT_ENVIRONMENT_VARIABLES="${EXPORT_ENVIRONMENT_VARIABLES}export LD_LIBRARY_PATH=${WORK_SPACE}/lib:\$LD_LIBRARY_PATH;" + +# Please install adb, and DON'T run this in the docker. +set -e +adb $ADB_DEVICE_NAME shell "rm -rf $WORK_SPACE" +adb $ADB_DEVICE_NAME shell "mkdir -p $WORK_SPACE" + +# Upload the demo, librarys, model and test images to the device +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/lib $WORK_SPACE +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/${DEMO_NAME} $WORK_SPACE +adb $ADB_DEVICE_NAME push models $WORK_SPACE +adb $ADB_DEVICE_NAME push images $WORK_SPACE + +# Execute the deployment demo +adb $ADB_DEVICE_NAME shell "cd $WORK_SPACE; ${EXPORT_ENVIRONMENT_VARIABLES} chmod +x ./${DEMO_NAME}; ./${DEMO_NAME} ./models/${MODEL_NAME} ./images/$IMAGE_NAME" diff --git a/examples/vision/detection/rkyolo/README.md b/examples/vision/detection/rkyolo/README.md new file mode 100644 index 000000000..015e22506 --- /dev/null +++ b/examples/vision/detection/rkyolo/README.md @@ -0,0 +1,18 @@ +# RKYOLO准备部署模型 + +RKYOLO参考[rknn_model_zoo](https://github.com/airockchip/rknn_model_zoo/tree/main/models/CV/object_detection/yolo)的代码 +对RKYOLO系列模型进行了封装,目前支持RKYOLOV5系列模型的部署。 + +## 支持模型列表 + +* RKYOLOV5 + +## 模型转换example + +请参考[RKNN_model_convert](https://github.com/airockchip/rknn_model_zoo/tree/main/models/CV/object_detection/yolo/RKNN_model_convert) + + +## 其他链接 +- [Cpp部署](./cpp) +- [Python部署](./python) +- [视觉模型预测结果](../../../../docs/api/vision_results/) diff --git a/examples/vision/detection/rkyolo/cpp/CMakeLists.txt b/examples/vision/detection/rkyolo/cpp/CMakeLists.txt new file mode 100644 index 000000000..524b94fea --- /dev/null +++ b/examples/vision/detection/rkyolo/cpp/CMakeLists.txt @@ -0,0 +1,37 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.10) +project(rknpu2_test) + +set(CMAKE_CXX_STANDARD 14) + +# 指定下载解压后的fastdeploy库路径 +set(FASTDEPLOY_INSTALL_DIR "thirdpartys/fastdeploy-0.0.3") + +include(${FASTDEPLOY_INSTALL_DIR}/FastDeployConfig.cmake) +include_directories(${FastDeploy_INCLUDE_DIRS}) + +add_executable(infer_rkyolo infer_rkyolo.cc) +target_link_libraries(infer_rkyolo ${FastDeploy_LIBS}) + + + +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build/install) + +install(TARGETS infer_rkyolo DESTINATION ./) + +install(DIRECTORY model DESTINATION ./) +install(DIRECTORY images DESTINATION ./) + +file(GLOB FASTDEPLOY_LIBS ${FASTDEPLOY_INSTALL_DIR}/lib/*) +message("${FASTDEPLOY_LIBS}") +install(PROGRAMS ${FASTDEPLOY_LIBS} DESTINATION lib) + +file(GLOB ONNXRUNTIME_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/onnxruntime/lib/*) +install(PROGRAMS ${ONNXRUNTIME_LIBS} DESTINATION lib) + +install(DIRECTORY ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/opencv/lib DESTINATION ./) + +file(GLOB PADDLETOONNX_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddle2onnx/lib/*) +install(PROGRAMS ${PADDLETOONNX_LIBS} DESTINATION lib) + +file(GLOB RKNPU2_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/rknpu2_runtime/${RKNN2_TARGET_SOC}/lib/*) +install(PROGRAMS ${RKNPU2_LIBS} DESTINATION lib) diff --git a/examples/vision/detection/rkyolo/cpp/README.md b/examples/vision/detection/rkyolo/cpp/README.md new file mode 100644 index 000000000..16f8df72d --- /dev/null +++ b/examples/vision/detection/rkyolo/cpp/README.md @@ -0,0 +1,69 @@ +# RKYOLO C++部署示例 + +本目录下提供`infer_xxxxx.cc`快速完成RKYOLO模型在Rockchip板子上上通过二代NPU加速部署的示例。 + +在部署前,需确认以下两个步骤: + +1. 软硬件环境满足要求 +2. 根据开发环境,下载预编译部署库或者从头编译FastDeploy仓库 + +以上步骤请参考[RK2代NPU部署库编译](../../../../../docs/cn/build_and_install/rknpu2.md)实现 + +## 生成基本目录文件 + +该例程由以下几个部分组成 +```text +. +├── CMakeLists.txt +├── build # 编译文件夹 +├── image # 存放图片的文件夹 +├── infer_rkyolo.cc +├── model # 存放模型文件的文件夹 +└── thirdpartys # 存放sdk的文件夹 +``` + +首先需要先生成目录结构 +```bash +mkdir build +mkdir images +mkdir model +mkdir thirdpartys +``` + +## 编译 + +### 编译并拷贝SDK到thirdpartys文件夹 + +请参考[RK2代NPU部署库编译](../../../../../../docs/cn/build_and_install/rknpu2.md)仓库编译SDK,编译完成后,将在build目录下生成 +fastdeploy-0.0.3目录,请移动它至thirdpartys目录下. + +### 拷贝模型文件,以及配置文件至model文件夹 +在Paddle动态图模型 -> Paddle静态图模型 -> ONNX模型的过程中,将生成ONNX文件以及对应的yaml配置文件,请将配置文件存放到model文件夹内。 +转换为RKNN后的模型文件也需要拷贝至model。 + +### 准备测试图片至image文件夹 +```bash +wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg +cp 000000014439.jpg ./images +``` + +### 编译example + +```bash +cd build +cmake .. +make -j8 +make install +``` + +## 运行例程 + +```bash +cd ./build/install +./infer_picodet model/ images/000000014439.jpg +``` + + +- [模型介绍](../../) +- [Python部署](../python) +- [视觉模型预测结果](../../../../../../docs/api/vision_results/) diff --git a/examples/vision/detection/rkyolo/cpp/infer_rkyolo.cc b/examples/vision/detection/rkyolo/cpp/infer_rkyolo.cc new file mode 100644 index 000000000..c7c1be43b --- /dev/null +++ b/examples/vision/detection/rkyolo/cpp/infer_rkyolo.cc @@ -0,0 +1,53 @@ +// 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" + +void RKNPU2Infer(const std::string& model_file, const std::string& image_file) { + struct timeval start_time, stop_time; + + auto option = fastdeploy::RuntimeOption(); + option.UseRKNPU2(); + + auto format = fastdeploy::ModelFormat::RKNN; + + auto model = fastdeploy::vision::detection::RKYOLOV5( + model_file, option,format); + + auto im = cv::imread(image_file); + + fastdeploy::vision::DetectionResult 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::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 < 3) { + std::cout + << "Usage: infer_demo path/to/model_dir path/to/image run_option, " + "e.g ./infer_model ./picodet_model_dir ./test.jpeg" + << std::endl; + return -1; + } + + RKNPU2Infer(argv[1], argv[2]); + + return 0; +} + diff --git a/examples/vision/detection/rkyolo/python/README.md b/examples/vision/detection/rkyolo/python/README.md new file mode 100644 index 000000000..4549ec0f9 --- /dev/null +++ b/examples/vision/detection/rkyolo/python/README.md @@ -0,0 +1,34 @@ +# RKYOLO Python部署示例 + +在部署前,需确认以下两个步骤 + +- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../../docs/cn/build_and_install/rknpu2.md) + +本目录下提供`infer.py`快速完成Picodet在RKNPU上部署的示例。执行如下脚本即可完成 + +```bash +# 下载部署示例代码 +git clone https://github.com/PaddlePaddle/FastDeploy.git +cd FastDeploy/examples/vision/detection/rkyolo/python + +# 下载图片 +wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg + +# copy model +cp -r ./model /path/to/FastDeploy/examples/vision/detection/rkyolo/python + +# 推理 +python3 infer.py --model_file ./model/ \ + --image 000000014439.jpg +``` + + +## 注意事项 +RKNPU上对模型的输入要求是使用NHWC格式,且图片归一化操作会在转RKNN模型时,内嵌到模型中,因此我们在使用FastDeploy部署时, + +## 其它文档 + +- [PaddleDetection 模型介绍](..) +- [PaddleDetection C++部署](../cpp) +- [模型预测结果说明](../../../../../../docs/api/vision_results/) +- [转换PaddleDetection RKNN模型文档](../README.md) diff --git a/examples/vision/detection/rkyolo/python/infer.py b/examples/vision/detection/rkyolo/python/infer.py new file mode 100644 index 000000000..38eea0e8c --- /dev/null +++ b/examples/vision/detection/rkyolo/python/infer.py @@ -0,0 +1,53 @@ +# 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 fastdeploy as fd +import cv2 +import os + + +def parse_arguments(): + import argparse + import ast + parser = argparse.ArgumentParser() + parser.add_argument( + "--model_file", required=True, help="Path of rknn model.") + parser.add_argument( + "--image", type=str, required=True, help="Path of test image file.") + return parser.parse_args() + + +if __name__ == "__main__": + args = parse_arguments() + + model_file = args.model_file + params_file = "" + + # 配置runtime,加载模型 + runtime_option = fd.RuntimeOption() + runtime_option.use_rknpu2() + + model = fd.vision.detection.RKYOLOV5( + model_file, + runtime_option=runtime_option, + model_format=fd.ModelFormat.RKNN) + + # 预测图片分割结果 + im = cv2.imread(args.image) + result = model.predict(im) + print(result) + + # 可视化结果 + 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") diff --git a/examples/vision/detection/yolov5/quantize/README.md b/examples/vision/detection/yolov5/quantize/README.md old mode 100644 new mode 100755 index 853718381..aa0a8d543 --- a/examples/vision/detection/yolov5/quantize/README.md +++ b/examples/vision/detection/yolov5/quantize/README.md @@ -4,13 +4,13 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) ## 下载量化完成的YOLOv5s模型 用户也可以直接下载下表中的量化模型进行部署.(点击模型名字即可下载) Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -29,7 +29,7 @@ Benchmark表格说明: | [YOLOv5s](https://bj.bcebos.com/paddlehub/fastdeploy/yolov5s_quant.tar) | Paddle Inference| CPU | 213.73 | 130.19 | None | None | 1.64 |37.6 | 35.2 | 量化蒸馏训练 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [YOLOv5s](https://bj.bcebos.com/paddlehub/fastdeploy/yolov5s_quant.tar) | TensorRT | GPU | 24.61 | 21.20 | 20.78 | 20.94 | 1.18 | 37.6 | 36.7 | 量化蒸馏训练 | | [YOLOv5s](https://bj.bcebos.com/paddlehub/fastdeploy/yolov5s_quant.tar) | Paddle-TensorRT | GPU | 23.53 | None | 21.98 | 19.84 | 1.28 | 37.6 | 36.8 | 量化蒸馏训练 | diff --git a/examples/vision/detection/yolov5/quantize/README_EN.md b/examples/vision/detection/yolov5/quantize/README_EN.md old mode 100644 new mode 100755 index c704ccce2..d897710f9 --- a/examples/vision/detection/yolov5/quantize/README_EN.md +++ b/examples/vision/detection/yolov5/quantize/README_EN.md @@ -6,7 +6,7 @@ Users can use the one-click model quantization tool to quantize and deploy the m ## FastDeploy One-Click Model Quantization Tool FastDeploy provides a one-click quantization tool that allows users to quantize a model simply with a configuration file. -For a detailed tutorial, please refer to: [One-Click Model Quantization Tool](../../../../../tools/auto_compression/) +For a detailed tutorial, please refer to: [One-Click Model Quantization Tool](../../../../../tools/common_tools/auto_compression/) ## Download Quantized YOLOv5s Model diff --git a/examples/vision/detection/yolov5/quantize/cpp/README.md b/examples/vision/detection/yolov5/quantize/cpp/README.md old mode 100644 new mode 100755 index 90334c7ba..baee6d351 --- a/examples/vision/detection/yolov5/quantize/cpp/README.md +++ b/examples/vision/detection/yolov5/quantize/cpp/README.md @@ -9,7 +9,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv5s模型为例, 进行部署 在本目录执行如下命令即可完成编译,以及量化模型部署.支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) diff --git a/examples/vision/detection/yolov5/quantize/python/README.md b/examples/vision/detection/yolov5/quantize/python/README.md old mode 100644 new mode 100755 index c63ef712c..9108e256e --- a/examples/vision/detection/yolov5/quantize/python/README.md +++ b/examples/vision/detection/yolov5/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv5s模型为例, 进行部署 diff --git a/examples/vision/detection/yolov5/rv1126/README.md b/examples/vision/detection/yolov5/rv1126/README.md new file mode 100755 index 000000000..968cc4306 --- /dev/null +++ b/examples/vision/detection/yolov5/rv1126/README.md @@ -0,0 +1,11 @@ +# YOLOv5 量化模型在 RV1126 上的部署 +目前 FastDeploy 已经支持基于 PaddleLite 部署 YOLOv5 量化模型到 RV1126 上。 + +模型的量化和量化模型的下载请参考:[模型量化](../quantize/README.md) + + +## 详细部署文档 + +在 RV1126 上只支持 C++ 的部署。 + +- [C++部署](cpp) diff --git a/examples/vision/detection/yolov5/rv1126/cpp/CMakeLists.txt b/examples/vision/detection/yolov5/rv1126/cpp/CMakeLists.txt new file mode 100755 index 000000000..3c9eee38a --- /dev/null +++ b/examples/vision/detection/yolov5/rv1126/cpp/CMakeLists.txt @@ -0,0 +1,37 @@ +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}) +include_directories(${FastDeploy_INCLUDE_DIRS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc) +# 添加FastDeploy库依赖 +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) + +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build/install) + +install(TARGETS infer_demo DESTINATION ./) + +install(DIRECTORY models DESTINATION ./) +install(DIRECTORY images DESTINATION ./) + +file(GLOB FASTDEPLOY_LIBS ${FASTDEPLOY_INSTALL_DIR}/lib/*) +install(PROGRAMS ${FASTDEPLOY_LIBS} DESTINATION lib) + +file(GLOB OPENCV_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/opencv/lib/lib*) +install(PROGRAMS ${OPENCV_LIBS} DESTINATION lib) + +file(GLOB PADDLELITE_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/lib*) +install(PROGRAMS ${PADDLELITE_LIBS} DESTINATION lib) + +file(GLOB TIMVX_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/verisilicon_timvx/*) +install(PROGRAMS ${TIMVX_LIBS} DESTINATION lib) + +file(GLOB ADB_TOOLS run_with_adb.sh) +install(PROGRAMS ${ADB_TOOLS} DESTINATION ./) diff --git a/examples/vision/detection/yolov5/rv1126/cpp/README.md b/examples/vision/detection/yolov5/rv1126/cpp/README.md new file mode 100755 index 000000000..9711577f2 --- /dev/null +++ b/examples/vision/detection/yolov5/rv1126/cpp/README.md @@ -0,0 +1,54 @@ +# YOLOv5 量化模型 C++ 部署示例 + +本目录下提供的 `infer.cc`,可以帮助用户快速完成 YOLOv5 量化模型在 RV1126 上的部署推理加速。 + +## 部署准备 +### FastDeploy 交叉编译环境准备 +- 1. 软硬件环境满足要求,以及交叉编译环境的准备,请参考:[FastDeploy 交叉编译环境准备](../../../../../../docs/cn/build_and_install/rv1126.md#交叉编译环境搭建) + +### 量化模型准备 +- 1. 用户可以直接使用由 FastDeploy 提供的量化模型进行部署。 +- 2. 用户可以使用 FastDeploy 提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署。 +- 更多量化相关相关信息可查阅[模型量化](../../quantize/README.md) + +## 在 RV1126 上部署量化后的 YOLOv5 检测模型 +请按照以下步骤完成在 RV1126 上部署 YOLOv5 量化模型: +1. 交叉编译编译 FastDeploy 库,具体请参考:[交叉编译 FastDeploy](../../../../../../docs/cn/build_and_install/rv1126.md#基于-paddlelite-的-fastdeploy-交叉编译库编译) + +2. 将编译后的库拷贝到当前目录,可使用如下命令: +```bash +cp -r FastDeploy/build/fastdeploy-tmivx/ FastDeploy/examples/vision/detection/yolov5/rv1126/cpp +``` + +3. 在当前路径下载部署所需的模型和示例图片: +```bash +mkdir models && mkdir images +wget https://bj.bcebos.com/fastdeploy/models/yolov5s_ptq_model.tar.gz +tar -xvf yolov5s_ptq_model.tar.gz +cp -r yolov5s_ptq_model models +wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg +cp -r 000000014439.jpg images +``` + +4. 编译部署示例,可使入如下命令: +```bash +mkdir build && cd build +cmake -DCMAKE_TOOLCHAIN_FILE=${PWD}/../fastdeploy-tmivx/timvx.cmake -DFASTDEPLOY_INSTALL_DIR=${PWD}/../fastdeploy-tmivx .. +make -j8 +make install +# 成功编译之后,会生成 install 文件夹,里面有一个运行 demo 和部署所需的库 +``` + +5. 基于 adb 工具部署 YOLOv5 检测模型到 Rockchip RV1126,可使用如下命令: +```bash +# 进入 install 目录 +cd FastDeploy/examples/vision/detection/yolov5/rv1126/cpp/build/install/ +# 如下命令表示:bash run_with_adb.sh 需要运行的demo 模型路径 图片路径 设备的DEVICE_ID +bash run_with_adb.sh infer_demo yolov5s_ptq_model 000000014439.jpg $DEVICE_ID +``` + +部署成功后,vis_result.jpg 保存的结果如下: + + + +需要特别注意的是,在 RV1126 上部署的模型需要是量化后的模型,模型的量化请参考:[模型量化](../../../../../../docs/cn/quantize.md) diff --git a/examples/vision/detection/yolov5/rv1126/cpp/infer.cc b/examples/vision/detection/yolov5/rv1126/cpp/infer.cc new file mode 100755 index 000000000..f1cf9e8dc --- /dev/null +++ b/examples/vision/detection/yolov5/rv1126/cpp/infer.cc @@ -0,0 +1,64 @@ +// 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) { + auto model_file = model_dir + sep + "model.pdmodel"; + auto params_file = model_dir + sep + "model.pdiparams"; + auto subgraph_file = model_dir + sep + "subgraph.txt"; + + fastdeploy::RuntimeOption option; + option.UseTimVX(); + option.SetLiteSubgraphPartitionPath(subgraph_file); + + auto model = fastdeploy::vision::detection::YOLOv5( + model_file, params_file, option, fastdeploy::ModelFormat::PADDLE); + assert(model.Initialized()); + + auto im = cv::imread(image_file); + + fastdeploy::vision::DetectionResult 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::VisDetection(im, res); + 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 < 3) { + std::cout << "Usage: infer_demo path/to/quant_model " + "path/to/image " + "run_option, " + "e.g ./infer_demo ./yolov5s_quant ./000000014439.jpg" + << std::endl; + return -1; + } + + std::string model_dir = argv[1]; + std::string test_image = argv[2]; + InitAndInfer(model_dir, test_image); + return 0; +} diff --git a/examples/vision/detection/yolov5/rv1126/cpp/run_with_adb.sh b/examples/vision/detection/yolov5/rv1126/cpp/run_with_adb.sh new file mode 100755 index 000000000..aacaed4c5 --- /dev/null +++ b/examples/vision/detection/yolov5/rv1126/cpp/run_with_adb.sh @@ -0,0 +1,47 @@ +#!/bin/bash +HOST_SPACE=${PWD} +echo ${HOST_SPACE} +WORK_SPACE=/data/local/tmp/test + +# The first parameter represents the demo name +DEMO_NAME=image_classification_demo +if [ -n "$1" ]; then + DEMO_NAME=$1 +fi + +# The second parameter represents the model name +MODEL_NAME=mobilenet_v1_fp32_224 +if [ -n "$2" ]; then + MODEL_NAME=$2 +fi + +# The third parameter indicates the name of the image to be tested +IMAGE_NAME=0001.jpg +if [ -n "$3" ]; then + IMAGE_NAME=$3 +fi + +# The fourth parameter represents the ID of the device +ADB_DEVICE_NAME= +if [ -n "$4" ]; then + ADB_DEVICE_NAME="-s $4" +fi + +# Set the environment variables required during the running process +EXPORT_ENVIRONMENT_VARIABLES="export GLOG_v=5; export VIV_VX_ENABLE_GRAPH_TRANSFORM=-pcq:1; export VIV_VX_SET_PER_CHANNEL_ENTROPY=100; export TIMVX_BATCHNORM_FUSION_MAX_ALLOWED_QUANT_SCALE_DEVIATION=300000; export VSI_NN_LOG_LEVEL=5;" + +EXPORT_ENVIRONMENT_VARIABLES="${EXPORT_ENVIRONMENT_VARIABLES}export LD_LIBRARY_PATH=${WORK_SPACE}/lib:\$LD_LIBRARY_PATH;" + +# Please install adb, and DON'T run this in the docker. +set -e +adb $ADB_DEVICE_NAME shell "rm -rf $WORK_SPACE" +adb $ADB_DEVICE_NAME shell "mkdir -p $WORK_SPACE" + +# Upload the demo, librarys, model and test images to the device +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/lib $WORK_SPACE +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/${DEMO_NAME} $WORK_SPACE +adb $ADB_DEVICE_NAME push models $WORK_SPACE +adb $ADB_DEVICE_NAME push images $WORK_SPACE + +# Execute the deployment demo +adb $ADB_DEVICE_NAME shell "cd $WORK_SPACE; ${EXPORT_ENVIRONMENT_VARIABLES} chmod +x ./${DEMO_NAME}; ./${DEMO_NAME} ./models/${MODEL_NAME} ./images/$IMAGE_NAME" diff --git a/examples/vision/detection/yolov5/serving/README.md b/examples/vision/detection/yolov5/serving/README.md index 3e341ff6d..d1f922433 100644 --- a/examples/vision/detection/yolov5/serving/README.md +++ b/examples/vision/detection/yolov5/serving/README.md @@ -22,10 +22,10 @@ mv yolov5s.onnx models/runtime/1/model.onnx # GPU镜像 docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 # CPU镜像 -docker pull paddlepaddle/fastdeploy:z.y.z-cpu-only-21.10 +docker pull paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10 # 运行容器.容器名字为 fd_serving, 并挂载当前目录为容器的 /yolov5_serving 目录 -nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/yolov5_serving paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash +nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/yolov5_serving paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash # 启动服务(不设置CUDA_VISIBLE_DEVICES环境变量,会拥有所有GPU卡的调度权限) CUDA_VISIBLE_DEVICES=0 fastdeployserver --model-repository=/yolov5_serving/models --backend-config=python,shm-default-byte-size=10485760 @@ -49,7 +49,7 @@ I0928 04:51:15.826578 206 http_server.cc:167] Started Metrics Service at 0.0.0.0 wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg #安装客户端依赖 -python3 -m pip install tritonclient\[all\] +python3 -m pip install tritonclient[all] # 发送请求 python3 yolov5_grpc_client.py diff --git a/examples/vision/detection/yolov5/serving/README_EN.md b/examples/vision/detection/yolov5/serving/README_EN.md index cc85355d8..cb4630463 100644 --- a/examples/vision/detection/yolov5/serving/README_EN.md +++ b/examples/vision/detection/yolov5/serving/README_EN.md @@ -9,11 +9,11 @@ wget https://bj.bcebos.com/paddlehub/fastdeploy/yolov5s.onnx # Save the model under models/infer/1 and rename it as model.onnx mv yolov5s.onnx models/infer/1/ -# Pull fastdeploy image -docker pull paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 +# Pull fastdeploy image, x.y.z is FastDeploy version, example 1.0.0. +docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 # Run the docker. The docker name is fd_serving, and the current directory is mounted as the docker's /yolov5_serving directory -nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/yolov5_serving paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash +nvidia-docker run -it --net=host --name fd_serving -v `pwd`/:/yolov5_serving paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash # Start the service (Without setting the CUDA_VISIBLE_DEVICES environment variable, it will have scheduling privileges for all GPU cards) CUDA_VISIBLE_DEVICES=0 fastdeployserver --model-repository=models --backend-config=python,shm-default-byte-size=10485760 diff --git a/examples/vision/detection/yolov6/quantize/README.md b/examples/vision/detection/yolov6/quantize/README.md old mode 100644 new mode 100755 index 04af3f689..57c71cedb --- a/examples/vision/detection/yolov6/quantize/README.md +++ b/examples/vision/detection/yolov6/quantize/README.md @@ -4,12 +4,12 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) ## 下载量化完成的YOLOv6s模型 用户也可以直接下载下表中的量化模型进行部署.(点击模型名字即可下载) Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -28,7 +28,7 @@ Benchmark表格说明: #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [YOLOv6s](https://bj.bcebos.com/paddlehub/fastdeploy/yolov6s_ptq_model.tar) | TensorRT | GPU | 15.66 | 11.30 | 10.25 |9.59 | 1.63 | 42.5 | 40.7|量化蒸馏训练 | | [YOLOv6s](https://bj.bcebos.com/paddlehub/fastdeploy/yolov6s_ptq_model.tar) | Paddle-TensorRT | GPU | 15.03 | None| 11.36 | 9.32 | 1.61 | 42.5 | 40.7|量化蒸馏训练 | diff --git a/examples/vision/detection/yolov6/quantize/README_EN.md b/examples/vision/detection/yolov6/quantize/README_EN.md old mode 100644 new mode 100755 index b7ae61d11..7a13ef7d0 --- a/examples/vision/detection/yolov6/quantize/README_EN.md +++ b/examples/vision/detection/yolov6/quantize/README_EN.md @@ -6,7 +6,7 @@ Users can use the one-click model quantization tool to quantize and deploy the m ## FastDeploy One-Click Model Quantization Tool FastDeploy provides a one-click quantization tool that allows users to quantize a model simply with a configuration file. -For detailed tutorial, please refer to : [One-Click Model Quantization Tool](../../../../../tools/auto_compression/) +For detailed tutorial, please refer to : [One-Click Model Quantization Tool](../../../../../tools/common_tools/auto_compression/) ## Download Quantized YOLOv6s Model diff --git a/examples/vision/detection/yolov6/quantize/cpp/README.md b/examples/vision/detection/yolov6/quantize/cpp/README.md old mode 100644 new mode 100755 index ee11f315d..7ad762100 --- a/examples/vision/detection/yolov6/quantize/cpp/README.md +++ b/examples/vision/detection/yolov6/quantize/cpp/README.md @@ -9,7 +9,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv6s模型为例, 进行部署 在本目录执行如下命令即可完成编译,以及量化模型部署.支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) diff --git a/examples/vision/detection/yolov6/quantize/python/README.md b/examples/vision/detection/yolov6/quantize/python/README.md old mode 100644 new mode 100755 index 169a0a946..057e13f9a --- a/examples/vision/detection/yolov6/quantize/python/README.md +++ b/examples/vision/detection/yolov6/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv6s模型为例, 进行部署 ```bash diff --git a/examples/vision/detection/yolov7/quantize/README.md b/examples/vision/detection/yolov7/quantize/README.md old mode 100644 new mode 100755 index 579532568..e1bbc2f69 --- a/examples/vision/detection/yolov7/quantize/README.md +++ b/examples/vision/detection/yolov7/quantize/README.md @@ -4,14 +4,14 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) ## 下载量化完成的YOLOv7模型 用户也可以直接下载下表中的量化模型进行部署.(点击模型名字即可下载) Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -29,7 +29,7 @@ Benchmark表格说明: | [YOLOv7](https://bj.bcebos.com/paddlehub/fastdeploy/yolov7_quant.tar) | Paddle Inference | CPU | 995.85 | 477.93|None|None | 2.08 |51.1 | 46.2|量化蒸馏训练 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mAP | INT8 mAP | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [YOLOv7](https://bj.bcebos.com/paddlehub/fastdeploy/yolov7_quant.tar) | TensorRT | GPU | 36.47 | 18.81 | 20.33| 17.58| 2.07 | 51.1| 50.4|量化蒸馏训练 | | [YOLOv7](https://bj.bcebos.com/paddlehub/fastdeploy/yolov7_quant.tar) | Paddle-TensorRT | GPU | 37.06|None|20.26|17.53 | 2.11 | 51.1| 50.4|量化蒸馏训练 | diff --git a/examples/vision/detection/yolov7/quantize/README_EN.md b/examples/vision/detection/yolov7/quantize/README_EN.md old mode 100644 new mode 100755 index 4e6b2e353..5a1add2e6 --- a/examples/vision/detection/yolov7/quantize/README_EN.md +++ b/examples/vision/detection/yolov7/quantize/README_EN.md @@ -6,7 +6,7 @@ Users can use the one-click model quantization tool to quantize and deploy the m ## FastDeploy One-Click Model Quantization Tool FastDeploy provides a one-click quantization tool that allows users to quantize a model simply with a configuration file. -For detailed tutorial, please refer to : [One-Click Model Quantization Tool](../../../../../tools/auto_compression/) +For detailed tutorial, please refer to : [One-Click Model Quantization Tool](../../../../../tools/common_tools/auto_compression/) ## Download Quantized YOLOv7 Model diff --git a/examples/vision/detection/yolov7/quantize/cpp/README.md b/examples/vision/detection/yolov7/quantize/cpp/README.md old mode 100644 new mode 100755 index 17eb9eb0f..d59964bcc --- a/examples/vision/detection/yolov7/quantize/cpp/README.md +++ b/examples/vision/detection/yolov7/quantize/cpp/README.md @@ -9,7 +9,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv7模型为例, 进行部署 在本目录执行如下命令即可完成编译,以及量化模型部署.支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) diff --git a/examples/vision/detection/yolov7/quantize/python/README.md b/examples/vision/detection/yolov7/quantize/python/README.md old mode 100644 new mode 100755 index 4389d44c1..08ee726e2 --- a/examples/vision/detection/yolov7/quantize/python/README.md +++ b/examples/vision/detection/yolov7/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署. ## 以量化后的YOLOv7模型为例, 进行部署 ```bash diff --git a/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java b/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java index 169c09cd0..8397531c8 100644 --- a/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java +++ b/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java @@ -300,6 +300,8 @@ public class FaceDetMainActivity extends Activity implements View.OnClickListene // Open camera until the permissions have been granted if (!checkAllPermissions()) { svPreview.disableCamera(); + } else { + svPreview.enableCamera(); } svPreview.onResume(); } diff --git a/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java b/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java index 94a5fdbd0..14217181d 100644 --- a/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java +++ b/examples/vision/facedet/scrfd/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java @@ -278,6 +278,10 @@ public class CameraSurfaceView extends GLSurfaceView implements Renderer, disableCamera = true; } + public void enableCamera() { + disableCamera = false; + } + public void switchCamera() { releaseCamera(); selectedCameraId = (selectedCameraId + 1) % numberOfCameras; diff --git a/examples/vision/ocr/PP-OCRv2/android/README.md b/examples/vision/ocr/PP-OCRv2/android/README.md index 51163d8a6..4181a93e1 100644 --- a/examples/vision/ocr/PP-OCRv2/android/README.md +++ b/examples/vision/ocr/PP-OCRv2/android/README.md @@ -27,14 +27,14 @@ | --- | --- | --- | | ![app_pic](https://user-images.githubusercontent.com/14995488/203484427-83de2316-fd60-4baf-93b6-3755f9b5559d.jpg) | ![app_res](https://user-images.githubusercontent.com/14995488/203495616-af42a5b7-d3bc-4fce-8d5e-2ed88454f618.jpg) | ![app_setup](https://user-images.githubusercontent.com/14995488/203484436-57fdd041-7dcc-4e0e-b6cb-43e5ac1e729b.jpg) | -### PP-OCRv2 & PP-OCRv3 Java API 说明 +### PP-OCRv2 Java API 说明 - 模型初始化 API: 模型初始化API包含两种方式,方式一是通过构造函数直接初始化;方式二是,通过调用init函数,在合适的程序节点进行初始化。 PP-OCR初始化参数说明如下: - modelFile: String, paddle格式的模型文件路径,如 model.pdmodel - paramFile: String, paddle格式的参数文件路径,如 model.pdiparams - labelFile: String, 可选参数,表示label标签文件所在路径,用于可视化,如 ppocr_keys_v1.txt,每一行包含一个label - option: RuntimeOption,可选参数,模型初始化option。如果不传入该参数则会使用默认的运行时选项。 - 与其他模型不同的是,PP-OCRv2 和 PP-OCRv3 包含 DBDetector、Classifier和Recognizer等基础模型,以及PPOCRv2和PPOCRv3等pipeline类型。 + 与其他模型不同的是,PP-OCRv2 包含 DBDetector、Classifier和Recognizer等基础模型,以及pipeline类型。 ```java // 构造函数: constructor w/o label file public DBDetector(String modelFile, String paramsFile); @@ -47,10 +47,6 @@ public PPOCRv2(); // 空构造函数,之后可以调用init初始化 // Constructor w/o classifier public PPOCRv2(DBDetector detModel, Recognizer recModel); public PPOCRv2(DBDetector detModel, Classifier clsModel, Recognizer recModel); -public PPOCRv3(); // 空构造函数,之后可以调用init初始化 -// Constructor w/o classifier -public PPOCRv3(DBDetector detModel, Recognizer recModel); -public PPOCRv3(DBDetector detModel, Classifier clsModel, Recognizer recModel); ``` - 模型预测 API:模型预测API包含直接预测的API以及带可视化功能的API。直接预测是指,不保存图片以及不渲染结果到Bitmap上,仅预测推理结果。预测并且可视化是指,预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap(目前支持ARGB8888格式的Bitmap), 后续可将该Bitmap在camera中进行显示。 ```java @@ -66,6 +62,126 @@ public boolean release(); // 释放native资源 public boolean initialized(); // 检查是否初始化成功 ``` +- RuntimeOption设置说明 + +```java +public void enableLiteFp16(); // 开启fp16精度推理 +public void disableLiteFP16(); // 关闭fp16精度推理 +public void enableLiteInt8(); // 开启int8精度推理,针对量化模型 +public void disableLiteInt8(); // 关闭int8精度推理 +public void setCpuThreadNum(int threadNum); // 设置线程数 +public void setLitePowerMode(LitePowerMode mode); // 设置能耗模式 +public void setLitePowerMode(String modeStr); // 通过字符串形式设置能耗模式 +``` + +- 模型结果OCRResult说明 +```java +public class OCRResult { + public int[][] mBoxes; // 表示单张图片检测出来的所有目标框坐标,每个框以8个int数值依次表示框的4个坐标点,顺序为左下,右下,右上,左上 + public String[] mText; // 表示多个文本框内被识别出来的文本内容 + public float[] mRecScores; // 表示文本框内识别出来的文本的置信度 + public float[] mClsScores; // 表示文本框的分类结果的置信度 + public int[] mClsLabels; // 表示文本框的方向分类类别 + public boolean mInitialized = false; // 检测结果是否有效 +} +``` +其他参考:C++/Python对应的OCRResult说明: [api/vision_results/ocr_result.md](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/api/vision_results/ocr_result.md) + + +- 模型调用示例1:使用构造函数 +```java +import java.nio.ByteBuffer; +import android.graphics.Bitmap; +import android.opengl.GLES20; + +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.LitePowerMode; +import com.baidu.paddle.fastdeploy.vision.OCRResult; +import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; +import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector; +import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer; + +// 模型路径 +String detModelFile = "ch_PP-OCRv2_det_infer/inference.pdmodel"; +String detParamsFile = "ch_PP-OCRv2_det_infer/inference.pdiparams"; +String clsModelFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdmodel"; +String clsParamsFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdiparams"; +String recModelFile = "ch_PP-OCRv2_rec_infer/inference.pdmodel"; +String recParamsFile = "ch_PP-OCRv2_rec_infer/inference.pdiparams"; +String recLabelFilePath = "labels/ppocr_keys_v1.txt"; +// 设置RuntimeOption +RuntimeOption detOption = new RuntimeOption(); +RuntimeOption clsOption = new RuntimeOption(); +RuntimeOption recOption = new RuntimeOption(); +detOption.setCpuThreadNum(2); +clsOption.setCpuThreadNum(2); +recOption.setCpuThreadNum(2); +detOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +clsOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +recOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +detOption.enableLiteFp16(); +clsOption.enableLiteFp16(); +recOption.enableLiteFp16(); +// 初始化模型 +DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); +Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); +Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); +PPOCRv2 model = new PPOCRv2(detModel, clsModel, recModel); + +// 读取图片: 以下仅为读取Bitmap的伪代码 +ByteBuffer pixelBuffer = ByteBuffer.allocate(width * height * 4); +GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer); +Bitmap ARGB8888ImageBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); +ARGB8888ImageBitmap.copyPixelsFromBuffer(pixelBuffer); + +// 模型推理 +OCRResult result = model.predict(ARGB8888ImageBitmap); + +// 释放模型资源 +model.release(); +``` + +- 模型调用示例2: 在合适的程序节点,手动调用init +```java +// import 同上 ... +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.LitePowerMode; +import com.baidu.paddle.fastdeploy.vision.OCRResult; +import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; +import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector; +import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer; +// 新建空模型 +PPOCRv2 model = new PPOCRv2(); +// 模型路径 +String detModelFile = "ch_PP-OCRv2_det_infer/inference.pdmodel"; +String detParamsFile = "ch_PP-OCRv2_det_infer/inference.pdiparams"; +String clsModelFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdmodel"; +String clsParamsFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdiparams"; +String recModelFile = "ch_PP-OCRv2_rec_infer/inference.pdmodel"; +String recParamsFile = "ch_PP-OCRv2_rec_infer/inference.pdiparams"; +String recLabelFilePath = "labels/ppocr_keys_v1.txt"; +// 设置RuntimeOption +RuntimeOption detOption = new RuntimeOption(); +RuntimeOption clsOption = new RuntimeOption(); +RuntimeOption recOption = new RuntimeOption(); +detOption.setCpuThreadNum(2); +clsOption.setCpuThreadNum(2); +recOption.setCpuThreadNum(2); +detOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +clsOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +recOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +detOption.enableLiteFp16(); +clsOption.enableLiteFp16(); +recOption.enableLiteFp16(); +// 使用init函数初始化 +DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); +Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); +Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); +model.init(detModel, clsModel, recModel); +// Bitmap读取、模型预测、资源释放 同上 ... +``` +更详细的用法请参考 [OcrMainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java)中的用法 + ## 替换 FastDeploy SDK和模型 替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-sdk-xxx.aar`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models`。 - 替换FastDeploy Android SDK: 下载或编译最新的FastDeploy Android SDK,解压缩后放在 `app/libs` 目录下;详细配置文档可参考: diff --git a/examples/vision/ocr/PP-OCRv2/cpp/README.md b/examples/vision/ocr/PP-OCRv2/cpp/README.md index afc35d50b..1bb794f5e 100644 --- a/examples/vision/ocr/PP-OCRv2/cpp/README.md +++ b/examples/vision/ocr/PP-OCRv2/cpp/README.md @@ -26,7 +26,7 @@ tar -xvf ch_PP-OCRv2_det_infer.tar wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar tar -xvf ch_ppocr_mobile_v2.0_cls_infer.tar -wgethttps://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar +wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar tar -xvf ch_PP-OCRv2_rec_infer.tar wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/doc/imgs/12.jpg @@ -82,6 +82,7 @@ PPOCRv2 的初始化,由检测,识别模型串联构成(无分类器) > ``` > bool Predict(cv::Mat* img, fastdeploy::vision::OCRResult* result); +> bool Predict(const cv::Mat& img, fastdeploy::vision::OCRResult* result); > ``` > > 模型预测接口,输入一张图片,返回OCR预测结果 diff --git a/examples/vision/ocr/PP-OCRv2/cpp/infer.cc b/examples/vision/ocr/PP-OCRv2/cpp/infer.cc index f05015d86..6cde6390f 100644 --- a/examples/vision/ocr/PP-OCRv2/cpp/infer.cc +++ b/examples/vision/ocr/PP-OCRv2/cpp/infer.cc @@ -33,13 +33,18 @@ void InitAndInfer(const std::string& det_model_dir, const std::string& cls_model auto cls_option = option; auto rec_option = option; + // The cls and rec model can inference a batch of images now. + // User could initialize the inference batch size and set them after create PPOCR model. + int cls_batch_size = 1; + int rec_batch_size = 6; + // If use TRT backend, the dynamic shape will be set as follow. // We recommend that users set the length and height of the detection model to a multiple of 32. det_option.SetTrtInputShape("x", {1, 3, 64,64}, {1, 3, 640, 640}, {1, 3, 960, 960}); - cls_option.SetTrtInputShape("x", {1, 3, 48, 10}, {10, 3, 48, 320}, {64, 3, 48, 1024}); - rec_option.SetTrtInputShape("x", {1, 3, 32, 10}, {10, 3, 32, 320}, - {64, 3, 32, 2304}); + cls_option.SetTrtInputShape("x", {1, 3, 48, 10}, {cls_batch_size, 3, 48, 320}, {cls_batch_size, 3, 48, 1024}); + rec_option.SetTrtInputShape("x", {1, 3, 32, 10}, {rec_batch_size, 3, 32, 320}, + {rec_batch_size, 3, 32, 2304}); // Users could save TRT cache file to disk as follow. // det_option.SetTrtCacheFile(det_model_dir + sep + "det_trt_cache.trt"); @@ -58,6 +63,12 @@ void InitAndInfer(const std::string& det_model_dir, const std::string& cls_model // auto ppocr_v2 = fastdeploy::pipeline::PPOCRv2(&det_model, &rec_model); auto ppocr_v2 = fastdeploy::pipeline::PPOCRv2(&det_model, &cls_model, &rec_model); + // Set inference batch size for cls model and rec model, the value could be -1 and 1 to positive infinity. + // When inference batch size is set to -1, it means that the inference batch size + // of the cls and rec models will be the same as the number of boxes detected by the det model. + ppocr_v2.SetClsBatchSize(cls_batch_size); + ppocr_v2.SetRecBatchSize(rec_batch_size); + if(!ppocr_v2.Initialized()){ std::cerr << "Failed to initialize PP-OCR." << std::endl; return; diff --git a/examples/vision/ocr/PP-OCRv2/python/README.md b/examples/vision/ocr/PP-OCRv2/python/README.md index a846f19c0..89e5fc073 100644 --- a/examples/vision/ocr/PP-OCRv2/python/README.md +++ b/examples/vision/ocr/PP-OCRv2/python/README.md @@ -16,7 +16,7 @@ tar -xvf ch_PP-OCRv2_det_infer.tar wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar tar -xvf ch_ppocr_mobile_v2.0_cls_infer.tar -wgethttps://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar +wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar tar -xvf ch_PP-OCRv2_rec_infer.tar wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/doc/imgs/12.jpg diff --git a/examples/vision/ocr/PP-OCRv2/python/infer.py b/examples/vision/ocr/PP-OCRv2/python/infer.py index 0dce3f95c..1487d795f 100644 --- a/examples/vision/ocr/PP-OCRv2/python/infer.py +++ b/examples/vision/ocr/PP-OCRv2/python/infer.py @@ -106,6 +106,11 @@ rec_label_file = args.rec_label_file # 用户也可根据自行需求分别配置 runtime_option = build_option(args) +# PPOCR的cls和rec模型现在已经支持推理一个Batch的数据 +# 定义下面两个变量后, 可用于设置trt输入shape, 并在PPOCR模型初始化后, 完成Batch推理设置 +cls_batch_size = 1 +rec_batch_size = 6 + # 当使用TRT时,分别给三个模型的runtime设置动态shape,并完成模型的创建. # 注意: 需要在检测模型创建完成后,再设置分类模型的动态输入并创建分类模型, 识别模型同理. # 如果用户想要自己改动检测模型的输入shape, 我们建议用户把检测模型的长和高设置为32的倍数. @@ -118,16 +123,18 @@ det_model = fd.vision.ocr.DBDetector( det_model_file, det_params_file, runtime_option=det_option) cls_option = runtime_option -cls_option.set_trt_input_shape("x", [1, 3, 48, 10], [10, 3, 48, 320], - [64, 3, 48, 1024]) +cls_option.set_trt_input_shape("x", [1, 3, 48, 10], + [cls_batch_size, 3, 48, 320], + [cls_batch_size, 3, 48, 1024]) # 用户可以把TRT引擎文件保存至本地 # cls_option.set_trt_cache_file(args.cls_model + "/cls_trt_cache.trt") cls_model = fd.vision.ocr.Classifier( cls_model_file, cls_params_file, runtime_option=cls_option) rec_option = runtime_option -rec_option.set_trt_input_shape("x", [1, 3, 32, 10], [10, 3, 32, 320], - [64, 3, 32, 2304]) +rec_option.set_trt_input_shape("x", [1, 3, 32, 10], + [rec_batch_size, 3, 32, 320], + [rec_batch_size, 3, 32, 2304]) # 用户可以把TRT引擎文件保存至本地 # rec_option.set_trt_cache_file(args.rec_model + "/rec_trt_cache.trt") rec_model = fd.vision.ocr.Recognizer( @@ -137,6 +144,12 @@ rec_model = fd.vision.ocr.Recognizer( ppocr_v2 = fd.vision.ocr.PPOCRv2( det_model=det_model, cls_model=cls_model, rec_model=rec_model) +# 给cls和rec模型设置推理时的batch size +# 此值能为-1, 和1到正无穷 +# 当此值为-1时, cls和rec模型的batch size将默认和det模型检测出的框的数量相同 +ppocr_v2.cls_batch_size = cls_batch_size +ppocr_v2.rec_batch_size = rec_batch_size + # 预测图片准备 im = cv2.imread(args.image) diff --git a/examples/vision/ocr/PP-OCRv3/android/.gitignore b/examples/vision/ocr/PP-OCRv3/android/.gitignore new file mode 100644 index 000000000..f6eba672f --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +.idea +.gradle +.cxx +cache +build +app/cache +app/libs/fastdeploy* +app/.cxx +app/build +app/src/main/assets/models/* +app/.gradle +app/.idea +fastdeploy/cache +fastdeploy/libs/fastdeploy* +fastdeploy/.cxx +fastdeploy/build +fastdeploy/src/main/assets/models/* +fastdeploy/.gradle +fastdeploy/.idea diff --git a/examples/vision/ocr/PP-OCRv3/android/README.md b/examples/vision/ocr/PP-OCRv3/android/README.md new file mode 100644 index 000000000..f4e23ab99 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/README.md @@ -0,0 +1,222 @@ +# OCR文字识别 Android Demo 使用文档 + +在 Android 上实现实时的OCR文字识别功能,此 Demo 有很好的的易用性和开放性,如在 Demo 中跑自己训练好的模型等。 + +## 环境准备 + +1. 在本地环境安装好 Android Studio 工具,详细安装方法请见[Android Stuido 官网](https://developer.android.com/studio)。 +2. 准备一部 Android 手机,并开启 USB 调试模式。开启方法: `手机设置 -> 查找开发者选项 -> 打开开发者选项和 USB 调试模式` + +## 部署步骤 + +1. OCR文字识别 Demo 位于 `fastdeploy/examples/vision/ocr/PP-OCRv3/android` 目录 +2. 用 Android Studio 打开 PP-OCRv3/android 工程 +3. 手机连接电脑,打开 USB 调试和文件传输模式,并在 Android Studio 上连接自己的手机设备(手机需要开启允许从 USB 安装软件权限) + +

+image +

+ +> **注意:** +>> 如果您在导入项目、编译或者运行过程中遇到 NDK 配置错误的提示,请打开 ` File > Project Structure > SDK Location`,修改 `Andriod SDK location` 为您本机配置的 SDK 所在路径。 + +4. 点击 Run 按钮,自动编译 APP 并安装到手机。(该过程会自动下载预编译的 FastDeploy Android 库 以及 模型文件,需要联网) + 成功后效果如下,图一:APP 安装到手机;图二: APP 打开后的效果,会自动识别图片中的物体并标记;图三:APP设置选项,点击右上角的设置图片,可以设置不同选项进行体验。 + +| APP 图标 | APP 效果 | APP设置项 + | --- | --- | --- | +| ![app_pic](https://user-images.githubusercontent.com/14995488/203484427-83de2316-fd60-4baf-93b6-3755f9b5559d.jpg) | ![app_res](https://user-images.githubusercontent.com/14995488/203495616-af42a5b7-d3bc-4fce-8d5e-2ed88454f618.jpg) | ![app_setup](https://user-images.githubusercontent.com/14995488/203484436-57fdd041-7dcc-4e0e-b6cb-43e5ac1e729b.jpg) | + +### PP-OCRv3 Java API 说明 + +- 模型初始化 API: 模型初始化API包含两种方式,方式一是通过构造函数直接初始化;方式二是,通过调用init函数,在合适的程序节点进行初始化。 PP-OCR初始化参数说明如下: + - modelFile: String, paddle格式的模型文件路径,如 model.pdmodel + - paramFile: String, paddle格式的参数文件路径,如 model.pdiparams + - labelFile: String, 可选参数,表示label标签文件所在路径,用于可视化,如 ppocr_keys_v1.txt,每一行包含一个label + - option: RuntimeOption,可选参数,模型初始化option。如果不传入该参数则会使用默认的运行时选项。 + 与其他模型不同的是,PP-OCRv3 包含 DBDetector、Classifier和Recognizer等基础模型,以及pipeline类型。 +```java +// 构造函数: constructor w/o label file +public DBDetector(String modelFile, String paramsFile); +public DBDetector(String modelFile, String paramsFile, RuntimeOption option); +public Classifier(String modelFile, String paramsFile); +public Classifier(String modelFile, String paramsFile, RuntimeOption option); +public Recognizer(String modelFile, String paramsFile, String labelPath); +public Recognizer(String modelFile, String paramsFile, String labelPath, RuntimeOption option); +public PPOCRv3(); // 空构造函数,之后可以调用init初始化 +// Constructor w/o classifier +public PPOCRv3(DBDetector detModel, Recognizer recModel); +public PPOCRv3(DBDetector detModel, Classifier clsModel, Recognizer recModel); +``` +- 模型预测 API:模型预测API包含直接预测的API以及带可视化功能的API。直接预测是指,不保存图片以及不渲染结果到Bitmap上,仅预测推理结果。预测并且可视化是指,预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap(目前支持ARGB8888格式的Bitmap), 后续可将该Bitmap在camera中进行显示。 +```java +// 直接预测:不保存图片以及不渲染结果到Bitmap上 +public OCRResult predict(Bitmap ARGB8888Bitmap); +// 预测并且可视化:预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap上 +public OCRResult predict(Bitmap ARGB8888Bitmap, String savedImagePath); +public OCRResult predict(Bitmap ARGB8888Bitmap, boolean rendering); // 只渲染 不保存图片 +``` +- 模型资源释放 API:调用 release() API 可以释放模型资源,返回true表示释放成功,false表示失败;调用 initialized() 可以判断模型是否初始化成功,true表示初始化成功,false表示失败。 +```java +public boolean release(); // 释放native资源 +public boolean initialized(); // 检查是否初始化成功 +``` + +- RuntimeOption设置说明 + +```java +public void enableLiteFp16(); // 开启fp16精度推理 +public void disableLiteFP16(); // 关闭fp16精度推理 +public void enableLiteInt8(); // 开启int8精度推理,针对量化模型 +public void disableLiteInt8(); // 关闭int8精度推理 +public void setCpuThreadNum(int threadNum); // 设置线程数 +public void setLitePowerMode(LitePowerMode mode); // 设置能耗模式 +public void setLitePowerMode(String modeStr); // 通过字符串形式设置能耗模式 +``` + +- 模型结果OCRResult说明 +```java +public class OCRResult { + public int[][] mBoxes; // 表示单张图片检测出来的所有目标框坐标,每个框以8个int数值依次表示框的4个坐标点,顺序为左下,右下,右上,左上 + public String[] mText; // 表示多个文本框内被识别出来的文本内容 + public float[] mRecScores; // 表示文本框内识别出来的文本的置信度 + public float[] mClsScores; // 表示文本框的分类结果的置信度 + public int[] mClsLabels; // 表示文本框的方向分类类别 + public boolean mInitialized = false; // 检测结果是否有效 +} +``` +其他参考:C++/Python对应的OCRResult说明: [api/vision_results/ocr_result.md](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/api/vision_results/ocr_result.md) + + +- 模型调用示例1:使用构造函数 +```java +import java.nio.ByteBuffer; +import android.graphics.Bitmap; +import android.opengl.GLES20; + +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.LitePowerMode; +import com.baidu.paddle.fastdeploy.vision.OCRResult; +import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; +import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector; +import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer; + +// 模型路径 +String detModelFile = "ch_PP-OCRv3_det_infer/inference.pdmodel"; +String detParamsFile = "ch_PP-OCRv3_det_infer/inference.pdiparams"; +String clsModelFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdmodel"; +String clsParamsFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdiparams"; +String recModelFile = "ch_PP-OCRv3_rec_infer/inference.pdmodel"; +String recParamsFile = "ch_PP-OCRv3_rec_infer/inference.pdiparams"; +String recLabelFilePath = "labels/ppocr_keys_v1.txt"; +// 设置RuntimeOption +RuntimeOption detOption = new RuntimeOption(); +RuntimeOption clsOption = new RuntimeOption(); +RuntimeOption recOption = new RuntimeOption(); +detOption.setCpuThreadNum(2); +clsOption.setCpuThreadNum(2); +recOption.setCpuThreadNum(2); +detOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +clsOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +recOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +detOption.enableLiteFp16(); +clsOption.enableLiteFp16(); +recOption.enableLiteFp16(); +// 初始化模型 +DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); +Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); +Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); +PPOCRv3 model = new PPOCRv3(detModel,clsModel,recModel); + +// 读取图片: 以下仅为读取Bitmap的伪代码 +ByteBuffer pixelBuffer = ByteBuffer.allocate(width * height * 4); +GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer); +Bitmap ARGB8888ImageBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); +ARGB8888ImageBitmap.copyPixelsFromBuffer(pixelBuffer); + +// 模型推理 +OCRResult result = model.predict(ARGB8888ImageBitmap); + +// 释放模型资源 +model.release(); +``` + +- 模型调用示例2: 在合适的程序节点,手动调用init +```java +// import 同上 ... +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.LitePowerMode; +import com.baidu.paddle.fastdeploy.vision.OCRResult; +import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; +import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector; +import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer; +// 新建空模型 +PPOCRv3 model = new PPOCRv3(); +// 模型路径 +String detModelFile = "ch_PP-OCRv3_det_infer/inference.pdmodel"; +String detParamsFile = "ch_PP-OCRv3_det_infer/inference.pdiparams"; +String clsModelFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdmodel"; +String clsParamsFile = "ch_ppocr_mobile_v2.0_cls_infer/inference.pdiparams"; +String recModelFile = "ch_PP-OCRv3_rec_infer/inference.pdmodel"; +String recParamsFile = "ch_PP-OCRv3_rec_infer/inference.pdiparams"; +String recLabelFilePath = "labels/ppocr_keys_v1.txt"; +// 设置RuntimeOption +RuntimeOption detOption = new RuntimeOption(); +RuntimeOption clsOption = new RuntimeOption(); +RuntimeOption recOption = new RuntimeOption(); +detOption.setCpuThreadNum(2); +clsOption.setCpuThreadNum(2); +recOption.setCpuThreadNum(2); +detOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +clsOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +recOption.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH); +detOption.enableLiteFp16(); +clsOption.enableLiteFp16(); +recOption.enableLiteFp16(); +// 使用init函数初始化 +DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); +Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); +Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); +model.init(detModel, clsModel, recModel); +// Bitmap读取、模型预测、资源释放 同上 ... +``` +更详细的用法请参考 [OcrMainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java)中的用法 + +## 替换 FastDeploy SDK和模型 +替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-sdk-xxx.aar`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models`。 +- 替换FastDeploy Android SDK: 下载或编译最新的FastDeploy Android SDK,解压缩后放在 `app/libs` 目录下;详细配置文档可参考: + - [在 Android 中使用 FastDeploy Java SDK](../../../../../java/android/) + +- 替换OCR模型的步骤: + - 将您的OCR模型放在 `app/src/main/assets/models` 目录下; + - 修改 `app/src/main/res/values/strings.xml` 中模型路径的默认值,如: +```xml + +models +labels/ppocr_keys_v1.txt +``` +## 使用量化模型 +如果您使用的是量化格式的模型,只需要使用RuntimeOption的enableLiteInt8()接口设置Int8精度推理即可。 +```java +String detModelFile = "ch_ppocrv3_plate_det_quant/inference.pdmodel"; +String detParamsFile = "ch_ppocrv3_plate_det_quant/inference.pdiparams"; +String recModelFile = "ch_ppocrv3_plate_rec_distillation_quant/inference.pdmodel"; +String recParamsFile = "ch_ppocrv3_plate_rec_distillation_quant/inference.pdiparams"; +String recLabelFilePath = "ppocr_keys_v1.txt"; // ppocr_keys_v1.txt +RuntimeOption detOption = new RuntimeOption(); +RuntimeOption recOption = new RuntimeOption(); +// 使用Int8精度进行推理 +detOption.enableLiteInt8(); +recOption.enableLiteInt8(); +// 初始化PP-OCRv3 Pipeline +PPOCRv3 predictor = new PPOCRv3(); +DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); +Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); +predictor.init(detModel, recModel); +``` +在App中使用,可以参考 [OcrMainActivity.java](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java) 中的用法。 + +## 更多参考文档 +如果您想知道更多的FastDeploy Java API文档以及如何通过JNI来接入FastDeploy C++ API感兴趣,可以参考以下内容: +- [在 Android 中使用 FastDeploy Java SDK](../../../../../java/android/) +- [在 Android 中使用 FastDeploy C++ SDK](../../../../../docs/cn/faq/use_cpp_sdk_on_android.md) diff --git a/examples/vision/ocr/PP-OCRv3/android/app/build.gradle b/examples/vision/ocr/PP-OCRv3/android/app/build.gradle new file mode 100644 index 000000000..de19b87c0 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/build.gradle @@ -0,0 +1,125 @@ +import java.security.MessageDigest + +apply plugin: 'com.android.application' + +android { + compileSdk 28 + + defaultConfig { + applicationId 'com.baidu.paddle.fastdeploy.app.examples' + minSdkVersion 15 + //noinspection ExpiredTargetSdkVersion + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(include: ['*.aar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:28.0.0' + //noinspection GradleDependency + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:design:28.0.0' + implementation 'org.jetbrains:annotations:15.0' + //noinspection GradleDependency + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} + +def FD_MODEL = [ + [ + 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/ch_PP-OCRv3_det_infer.tgz', + 'dest': 'src/main/assets/models' + ], + [ + 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/ch_ppocr_mobile_v2.0_cls_infer.tgz', + 'dest': 'src/main/assets/models' + ], + [ + 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/ch_PP-OCRv3_rec_infer.tgz', + 'dest': 'src/main/assets/models' + ] +] + +def FD_JAVA_SDK = [ + [ + 'src' : 'https://bj.bcebos.com/fastdeploy/test/fastdeploy-android-sdk-latest-dev.aar', + 'dest': 'libs' + ] +] + +task downloadAndExtractModels(type: DefaultTask) { + doFirst { + println "Downloading and extracting fastdeploy models ..." + } + doLast { + String cachePath = "cache" + if (!file("${cachePath}").exists()) { + mkdir "${cachePath}" + } + FD_MODEL.eachWithIndex { model, index -> + MessageDigest messageDigest = MessageDigest.getInstance('MD5') + messageDigest.update(model.src.bytes) + String[] modelPaths = model.src.split("/") + String modelName = modelPaths[modelPaths.length - 1] + // Download the target model if not exists + boolean copyFiles = !file("${model.dest}").exists() + if (!file("${cachePath}/${modelName}").exists()) { + println "Downloading ${model.src} -> ${cachePath}/${modelName}" + ant.get(src: model.src, dest: file("${cachePath}/${modelName}")) + copyFiles = true + } + if (copyFiles) { + println "Coping ${cachePath}/${modelName} -> ${model.dest}" + copy { + from tarTree("${cachePath}/${modelName}") + into "${model.dest}" + } + } + } + } +} + +task downloadAndExtractSDKs(type: DefaultTask) { + doFirst { + println "Downloading and extracting fastdeploy android java sdk ..." + } + doLast { + String cachePath = "cache" + if (!file("${cachePath}").exists()) { + mkdir "${cachePath}" + } + FD_JAVA_SDK.eachWithIndex { sdk, index -> + String[] sdkPaths = sdk.src.split("/") + String sdkName = sdkPaths[sdkPaths.length - 1] + // Download the target SDK if not exists + boolean copyFiles = !file("${sdk.dest}/${sdkName}").exists() + if (!file("${cachePath}/${sdkName}").exists()) { + println "Downloading ${sdk.src} -> ${cachePath}/${sdkName}" + ant.get(src: sdk.src, dest: file("${cachePath}/${sdkName}")) + copyFiles = true + } + if (copyFiles) { + println "Coping ${cachePath}/${sdkName} -> ${sdk.dest}/${sdkName}" + copy { + from "${cachePath}/${sdkName}" + into "${sdk.dest}" + } + } + } + } +} + +preBuild.dependsOn downloadAndExtractSDKs +preBuild.dependsOn downloadAndExtractModels \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/proguard-rules.pro b/examples/vision/ocr/PP-OCRv3/android/app/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/java/android/app/src/androidTest/java/com/baidu/paddle/fastdeploy/ExampleInstrumentedTest.java b/examples/vision/ocr/PP-OCRv3/android/app/src/androidTest/java/com/baidu/paddle/fastdeploy/ExampleInstrumentedTest.java similarity index 100% rename from java/android/app/src/androidTest/java/com/baidu/paddle/fastdeploy/ExampleInstrumentedTest.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/androidTest/java/com/baidu/paddle/fastdeploy/ExampleInstrumentedTest.java diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/AndroidManifest.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8493c0379 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/assets/labels/ppocr_keys_v1.txt b/examples/vision/ocr/PP-OCRv3/android/app/src/main/assets/labels/ppocr_keys_v1.txt new file mode 100644 index 000000000..b75af2130 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/assets/labels/ppocr_keys_v1.txt @@ -0,0 +1,6623 @@ +' +疗 +绚 +诚 +娇 +溜 +题 +贿 +者 +廖 +更 +纳 +加 +奉 +公 +一 +就 +汴 +计 +与 +路 +房 +原 +妇 +2 +0 +8 +- +7 +其 +> +: +] +, +, +骑 +刈 +全 +消 +昏 +傈 +安 +久 +钟 +嗅 +不 +影 +处 +驽 +蜿 +资 +关 +椤 +地 +瘸 +专 +问 +忖 +票 +嫉 +炎 +韵 +要 +月 +田 +节 +陂 +鄙 +捌 +备 +拳 +伺 +眼 +网 +盎 +大 +傍 +心 +东 +愉 +汇 +蹿 +科 +每 +业 +里 +航 +晏 +字 +平 +录 +先 +1 +3 +彤 +鲶 +产 +稍 +督 +腴 +有 +象 +岳 +注 +绍 +在 +泺 +文 +定 +核 +名 +水 +过 +理 +让 +偷 +率 +等 +这 +发 +” +为 +含 +肥 +酉 +相 +鄱 +七 +编 +猥 +锛 +日 +镀 +蒂 +掰 +倒 +辆 +栾 +栗 +综 +涩 +州 +雌 +滑 +馀 +了 +机 +块 +司 +宰 +甙 +兴 +矽 +抚 +保 +用 +沧 +秩 +如 +收 +息 +滥 +页 +疑 +埠 +! +! +姥 +异 +橹 +钇 +向 +下 +跄 +的 +椴 +沫 +国 +绥 +獠 +报 +开 +民 +蜇 +何 +分 +凇 +长 +讥 +藏 +掏 +施 +羽 +中 +讲 +派 +嘟 +人 +提 +浼 +间 +世 +而 +古 +多 +倪 +唇 +饯 +控 +庚 +首 +赛 +蜓 +味 +断 +制 +觉 +技 +替 +艰 +溢 +潮 +夕 +钺 +外 +摘 +枋 +动 +双 +单 +啮 +户 +枇 +确 +锦 +曜 +杜 +或 +能 +效 +霜 +盒 +然 +侗 +电 +晁 +放 +步 +鹃 +新 +杖 +蜂 +吒 +濂 +瞬 +评 +总 +隍 +对 +独 +合 +也 +是 +府 +青 +天 +诲 +墙 +组 +滴 +级 +邀 +帘 +示 +已 +时 +骸 +仄 +泅 +和 +遨 +店 +雇 +疫 +持 +巍 +踮 +境 +只 +亨 +目 +鉴 +崤 +闲 +体 +泄 +杂 +作 +般 +轰 +化 +解 +迂 +诿 +蛭 +璀 +腾 +告 +版 +服 +省 +师 +小 +规 +程 +线 +海 +办 +引 +二 +桧 +牌 +砺 +洄 +裴 +修 +图 +痫 +胡 +许 +犊 +事 +郛 +基 +柴 +呼 +食 +研 +奶 +律 +蛋 +因 +葆 +察 +戏 +褒 +戒 +再 +李 +骁 +工 +貂 +油 +鹅 +章 +啄 +休 +场 +给 +睡 +纷 +豆 +器 +捎 +说 +敏 +学 +会 +浒 +设 +诊 +格 +廓 +查 +来 +霓 +室 +溆 +¢ +诡 +寥 +焕 +舜 +柒 +狐 +回 +戟 +砾 +厄 +实 +翩 +尿 +五 +入 +径 +惭 +喹 +股 +宇 +篝 +| +; +美 +期 +云 +九 +祺 +扮 +靠 +锝 +槌 +系 +企 +酰 +阊 +暂 +蚕 +忻 +豁 +本 +羹 +执 +条 +钦 +H +獒 +限 +进 +季 +楦 +于 +芘 +玖 +铋 +茯 +未 +答 +粘 +括 +样 +精 +欠 +矢 +甥 +帷 +嵩 +扣 +令 +仔 +风 +皈 +行 +支 +部 +蓉 +刮 +站 +蜡 +救 +钊 +汗 +松 +嫌 +成 +可 +. +鹤 +院 +从 +交 +政 +怕 +活 +调 +球 +局 +验 +髌 +第 +韫 +谗 +串 +到 +圆 +年 +米 +/ +* +友 +忿 +检 +区 +看 +自 +敢 +刃 +个 +兹 +弄 +流 +留 +同 +没 +齿 +星 +聆 +轼 +湖 +什 +三 +建 +蛔 +儿 +椋 +汕 +震 +颧 +鲤 +跟 +力 +情 +璺 +铨 +陪 +务 +指 +族 +训 +滦 +鄣 +濮 +扒 +商 +箱 +十 +召 +慷 +辗 +所 +莞 +管 +护 +臭 +横 +硒 +嗓 +接 +侦 +六 +露 +党 +馋 +驾 +剖 +高 +侬 +妪 +幂 +猗 +绺 +骐 +央 +酐 +孝 +筝 +课 +徇 +缰 +门 +男 +西 +项 +句 +谙 +瞒 +秃 +篇 +教 +碲 +罚 +声 +呐 +景 +前 +富 +嘴 +鳌 +稀 +免 +朋 +啬 +睐 +去 +赈 +鱼 +住 +肩 +愕 +速 +旁 +波 +厅 +健 +茼 +厥 +鲟 +谅 +投 +攸 +炔 +数 +方 +击 +呋 +谈 +绩 +别 +愫 +僚 +躬 +鹧 +胪 +炳 +招 +喇 +膨 +泵 +蹦 +毛 +结 +5 +4 +谱 +识 +陕 +粽 +婚 +拟 +构 +且 +搜 +任 +潘 +比 +郢 +妨 +醪 +陀 +桔 +碘 +扎 +选 +哈 +骷 +楷 +亿 +明 +缆 +脯 +监 +睫 +逻 +婵 +共 +赴 +淝 +凡 +惦 +及 +达 +揖 +谩 +澹 +减 +焰 +蛹 +番 +祁 +柏 +员 +禄 +怡 +峤 +龙 +白 +叽 +生 +闯 +起 +细 +装 +谕 +竟 +聚 +钙 +上 +导 +渊 +按 +艾 +辘 +挡 +耒 +盹 +饪 +臀 +记 +邮 +蕙 +受 +各 +医 +搂 +普 +滇 +朗 +茸 +带 +翻 +酚 +( +光 +堤 +墟 +蔷 +万 +幻 +〓 +瑙 +辈 +昧 +盏 +亘 +蛀 +吉 +铰 +请 +子 +假 +闻 +税 +井 +诩 +哨 +嫂 +好 +面 +琐 +校 +馊 +鬣 +缂 +营 +访 +炖 +占 +农 +缀 +否 +经 +钚 +棵 +趟 +张 +亟 +吏 +茶 +谨 +捻 +论 +迸 +堂 +玉 +信 +吧 +瞠 +乡 +姬 +寺 +咬 +溏 +苄 +皿 +意 +赉 +宝 +尔 +钰 +艺 +特 +唳 +踉 +都 +荣 +倚 +登 +荐 +丧 +奇 +涵 +批 +炭 +近 +符 +傩 +感 +道 +着 +菊 +虹 +仲 +众 +懈 +濯 +颞 +眺 +南 +释 +北 +缝 +标 +既 +茗 +整 +撼 +迤 +贲 +挎 +耱 +拒 +某 +妍 +卫 +哇 +英 +矶 +藩 +治 +他 +元 +领 +膜 +遮 +穗 +蛾 +飞 +荒 +棺 +劫 +么 +市 +火 +温 +拈 +棚 +洼 +转 +果 +奕 +卸 +迪 +伸 +泳 +斗 +邡 +侄 +涨 +屯 +萋 +胭 +氡 +崮 +枞 +惧 +冒 +彩 +斜 +手 +豚 +随 +旭 +淑 +妞 +形 +菌 +吲 +沱 +争 +驯 +歹 +挟 +兆 +柱 +传 +至 +包 +内 +响 +临 +红 +功 +弩 +衡 +寂 +禁 +老 +棍 +耆 +渍 +织 +害 +氵 +渑 +布 +载 +靥 +嗬 +虽 +苹 +咨 +娄 +库 +雉 +榜 +帜 +嘲 +套 +瑚 +亲 +簸 +欧 +边 +6 +腿 +旮 +抛 +吹 +瞳 +得 +镓 +梗 +厨 +继 +漾 +愣 +憨 +士 +策 +窑 +抑 +躯 +襟 +脏 +参 +贸 +言 +干 +绸 +鳄 +穷 +藜 +音 +折 +详 +) +举 +悍 +甸 +癌 +黎 +谴 +死 +罩 +迁 +寒 +驷 +袖 +媒 +蒋 +掘 +模 +纠 +恣 +观 +祖 +蛆 +碍 +位 +稿 +主 +澧 +跌 +筏 +京 +锏 +帝 +贴 +证 +糠 +才 +黄 +鲸 +略 +炯 +饱 +四 +出 +园 +犀 +牧 +容 +汉 +杆 +浈 +汰 +瑷 +造 +虫 +瘩 +怪 +驴 +济 +应 +花 +沣 +谔 +夙 +旅 +价 +矿 +以 +考 +s +u +呦 +晒 +巡 +茅 +准 +肟 +瓴 +詹 +仟 +褂 +译 +桌 +混 +宁 +怦 +郑 +抿 +些 +余 +鄂 +饴 +攒 +珑 +群 +阖 +岔 +琨 +藓 +预 +环 +洮 +岌 +宀 +杲 +瀵 +最 +常 +囡 +周 +踊 +女 +鼓 +袭 +喉 +简 +范 +薯 +遐 +疏 +粱 +黜 +禧 +法 +箔 +斤 +遥 +汝 +奥 +直 +贞 +撑 +置 +绱 +集 +她 +馅 +逗 +钧 +橱 +魉 +[ +恙 +躁 +唤 +9 +旺 +膘 +待 +脾 +惫 +购 +吗 +依 +盲 +度 +瘿 +蠖 +俾 +之 +镗 +拇 +鲵 +厝 +簧 +续 +款 +展 +啃 +表 +剔 +品 +钻 +腭 +损 +清 +锶 +统 +涌 +寸 +滨 +贪 +链 +吠 +冈 +伎 +迥 +咏 +吁 +览 +防 +迅 +失 +汾 +阔 +逵 +绀 +蔑 +列 +川 +凭 +努 +熨 +揪 +利 +俱 +绉 +抢 +鸨 +我 +即 +责 +膦 +易 +毓 +鹊 +刹 +玷 +岿 +空 +嘞 +绊 +排 +术 +估 +锷 +违 +们 +苟 +铜 +播 +肘 +件 +烫 +审 +鲂 +广 +像 +铌 +惰 +铟 +巳 +胍 +鲍 +康 +憧 +色 +恢 +想 +拷 +尤 +疳 +知 +S +Y +F +D +A +峄 +裕 +帮 +握 +搔 +氐 +氘 +难 +墒 +沮 +雨 +叁 +缥 +悴 +藐 +湫 +娟 +苑 +稠 +颛 +簇 +后 +阕 +闭 +蕤 +缚 +怎 +佞 +码 +嘤 +蔡 +痊 +舱 +螯 +帕 +赫 +昵 +升 +烬 +岫 +、 +疵 +蜻 +髁 +蕨 +隶 +烛 +械 +丑 +盂 +梁 +强 +鲛 +由 +拘 +揉 +劭 +龟 +撤 +钩 +呕 +孛 +费 +妻 +漂 +求 +阑 +崖 +秤 +甘 +通 +深 +补 +赃 +坎 +床 +啪 +承 +吼 +量 +暇 +钼 +烨 +阂 +擎 +脱 +逮 +称 +P +神 +属 +矗 +华 +届 +狍 +葑 +汹 +育 +患 +窒 +蛰 +佼 +静 +槎 +运 +鳗 +庆 +逝 +曼 +疱 +克 +代 +官 +此 +麸 +耧 +蚌 +晟 +例 +础 +榛 +副 +测 +唰 +缢 +迹 +灬 +霁 +身 +岁 +赭 +扛 +又 +菡 +乜 +雾 +板 +读 +陷 +徉 +贯 +郁 +虑 +变 +钓 +菜 +圾 +现 +琢 +式 +乐 +维 +渔 +浜 +左 +吾 +脑 +钡 +警 +T +啵 +拴 +偌 +漱 +湿 +硕 +止 +骼 +魄 +积 +燥 +联 +踢 +玛 +则 +窿 +见 +振 +畿 +送 +班 +钽 +您 +赵 +刨 +印 +讨 +踝 +籍 +谡 +舌 +崧 +汽 +蔽 +沪 +酥 +绒 +怖 +财 +帖 +肱 +私 +莎 +勋 +羔 +霸 +励 +哼 +帐 +将 +帅 +渠 +纪 +婴 +娩 +岭 +厘 +滕 +吻 +伤 +坝 +冠 +戊 +隆 +瘁 +介 +涧 +物 +黍 +并 +姗 +奢 +蹑 +掣 +垸 +锴 +命 +箍 +捉 +病 +辖 +琰 +眭 +迩 +艘 +绌 +繁 +寅 +若 +毋 +思 +诉 +类 +诈 +燮 +轲 +酮 +狂 +重 +反 +职 +筱 +县 +委 +磕 +绣 +奖 +晋 +濉 +志 +徽 +肠 +呈 +獐 +坻 +口 +片 +碰 +几 +村 +柿 +劳 +料 +获 +亩 +惕 +晕 +厌 +号 +罢 +池 +正 +鏖 +煨 +家 +棕 +复 +尝 +懋 +蜥 +锅 +岛 +扰 +队 +坠 +瘾 +钬 +@ +卧 +疣 +镇 +譬 +冰 +彷 +频 +黯 +据 +垄 +采 +八 +缪 +瘫 +型 +熹 +砰 +楠 +襁 +箐 +但 +嘶 +绳 +啤 +拍 +盥 +穆 +傲 +洗 +盯 +塘 +怔 +筛 +丿 +台 +恒 +喂 +葛 +永 +¥ +烟 +酒 +桦 +书 +砂 +蚝 +缉 +态 +瀚 +袄 +圳 +轻 +蛛 +超 +榧 +遛 +姒 +奘 +铮 +右 +荽 +望 +偻 +卡 +丶 +氰 +附 +做 +革 +索 +戚 +坨 +桷 +唁 +垅 +榻 +岐 +偎 +坛 +莨 +山 +殊 +微 +骇 +陈 +爨 +推 +嗝 +驹 +澡 +藁 +呤 +卤 +嘻 +糅 +逛 +侵 +郓 +酌 +德 +摇 +※ +鬃 +被 +慨 +殡 +羸 +昌 +泡 +戛 +鞋 +河 +宪 +沿 +玲 +鲨 +翅 +哽 +源 +铅 +语 +照 +邯 +址 +荃 +佬 +顺 +鸳 +町 +霭 +睾 +瓢 +夸 +椁 +晓 +酿 +痈 +咔 +侏 +券 +噎 +湍 +签 +嚷 +离 +午 +尚 +社 +锤 +背 +孟 +使 +浪 +缦 +潍 +鞅 +军 +姹 +驶 +笑 +鳟 +鲁 +》 +孽 +钜 +绿 +洱 +礴 +焯 +椰 +颖 +囔 +乌 +孔 +巴 +互 +性 +椽 +哞 +聘 +昨 +早 +暮 +胶 +炀 +隧 +低 +彗 +昝 +铁 +呓 +氽 +藉 +喔 +癖 +瑗 +姨 +权 +胱 +韦 +堑 +蜜 +酋 +楝 +砝 +毁 +靓 +歙 +锲 +究 +屋 +喳 +骨 +辨 +碑 +武 +鸠 +宫 +辜 +烊 +适 +坡 +殃 +培 +佩 +供 +走 +蜈 +迟 +翼 +况 +姣 +凛 +浔 +吃 +飘 +债 +犟 +金 +促 +苛 +崇 +坂 +莳 +畔 +绂 +兵 +蠕 +斋 +根 +砍 +亢 +欢 +恬 +崔 +剁 +餐 +榫 +快 +扶 +‖ +濒 +缠 +鳜 +当 +彭 +驭 +浦 +篮 +昀 +锆 +秸 +钳 +弋 +娣 +瞑 +夷 +龛 +苫 +拱 +致 +% +嵊 +障 +隐 +弑 +初 +娓 +抉 +汩 +累 +蓖 +" +唬 +助 +苓 +昙 +押 +毙 +破 +城 +郧 +逢 +嚏 +獭 +瞻 +溱 +婿 +赊 +跨 +恼 +璧 +萃 +姻 +貉 +灵 +炉 +密 +氛 +陶 +砸 +谬 +衔 +点 +琛 +沛 +枳 +层 +岱 +诺 +脍 +榈 +埂 +征 +冷 +裁 +打 +蹴 +素 +瘘 +逞 +蛐 +聊 +激 +腱 +萘 +踵 +飒 +蓟 +吆 +取 +咙 +簋 +涓 +矩 +曝 +挺 +揣 +座 +你 +史 +舵 +焱 +尘 +苏 +笈 +脚 +溉 +榨 +诵 +樊 +邓 +焊 +义 +庶 +儋 +蟋 +蒲 +赦 +呷 +杞 +诠 +豪 +还 +试 +颓 +茉 +太 +除 +紫 +逃 +痴 +草 +充 +鳕 +珉 +祗 +墨 +渭 +烩 +蘸 +慕 +璇 +镶 +穴 +嵘 +恶 +骂 +险 +绋 +幕 +碉 +肺 +戳 +刘 +潞 +秣 +纾 +潜 +銮 +洛 +须 +罘 +销 +瘪 +汞 +兮 +屉 +r +林 +厕 +质 +探 +划 +狸 +殚 +善 +煊 +烹 +〒 +锈 +逯 +宸 +辍 +泱 +柚 +袍 +远 +蹋 +嶙 +绝 +峥 +娥 +缍 +雀 +徵 +认 +镱 +谷 += +贩 +勉 +撩 +鄯 +斐 +洋 +非 +祚 +泾 +诒 +饿 +撬 +威 +晷 +搭 +芍 +锥 +笺 +蓦 +候 +琊 +档 +礁 +沼 +卵 +荠 +忑 +朝 +凹 +瑞 +头 +仪 +弧 +孵 +畏 +铆 +突 +衲 +车 +浩 +气 +茂 +悖 +厢 +枕 +酝 +戴 +湾 +邹 +飚 +攘 +锂 +写 +宵 +翁 +岷 +无 +喜 +丈 +挑 +嗟 +绛 +殉 +议 +槽 +具 +醇 +淞 +笃 +郴 +阅 +饼 +底 +壕 +砚 +弈 +询 +缕 +庹 +翟 +零 +筷 +暨 +舟 +闺 +甯 +撞 +麂 +茌 +蔼 +很 +珲 +捕 +棠 +角 +阉 +媛 +娲 +诽 +剿 +尉 +爵 +睬 +韩 +诰 +匣 +危 +糍 +镯 +立 +浏 +阳 +少 +盆 +舔 +擘 +匪 +申 +尬 +铣 +旯 +抖 +赘 +瓯 +居 +ˇ +哮 +游 +锭 +茏 +歌 +坏 +甚 +秒 +舞 +沙 +仗 +劲 +潺 +阿 +燧 +郭 +嗖 +霏 +忠 +材 +奂 +耐 +跺 +砀 +输 +岖 +媳 +氟 +极 +摆 +灿 +今 +扔 +腻 +枝 +奎 +药 +熄 +吨 +话 +q +额 +慑 +嘌 +协 +喀 +壳 +埭 +视 +著 +於 +愧 +陲 +翌 +峁 +颅 +佛 +腹 +聋 +侯 +咎 +叟 +秀 +颇 +存 +较 +罪 +哄 +岗 +扫 +栏 +钾 +羌 +己 +璨 +枭 +霉 +煌 +涸 +衿 +键 +镝 +益 +岢 +奏 +连 +夯 +睿 +冥 +均 +糖 +狞 +蹊 +稻 +爸 +刿 +胥 +煜 +丽 +肿 +璃 +掸 +跚 +灾 +垂 +樾 +濑 +乎 +莲 +窄 +犹 +撮 +战 +馄 +软 +络 +显 +鸢 +胸 +宾 +妲 +恕 +埔 +蝌 +份 +遇 +巧 +瞟 +粒 +恰 +剥 +桡 +博 +讯 +凯 +堇 +阶 +滤 +卖 +斌 +骚 +彬 +兑 +磺 +樱 +舷 +两 +娱 +福 +仃 +差 +找 +桁 +÷ +净 +把 +阴 +污 +戬 +雷 +碓 +蕲 +楚 +罡 +焖 +抽 +妫 +咒 +仑 +闱 +尽 +邑 +菁 +爱 +贷 +沥 +鞑 +牡 +嗉 +崴 +骤 +塌 +嗦 +订 +拮 +滓 +捡 +锻 +次 +坪 +杩 +臃 +箬 +融 +珂 +鹗 +宗 +枚 +降 +鸬 +妯 +阄 +堰 +盐 +毅 +必 +杨 +崃 +俺 +甬 +状 +莘 +货 +耸 +菱 +腼 +铸 +唏 +痤 +孚 +澳 +懒 +溅 +翘 +疙 +杷 +淼 +缙 +骰 +喊 +悉 +砻 +坷 +艇 +赁 +界 +谤 +纣 +宴 +晃 +茹 +归 +饭 +梢 +铡 +街 +抄 +肼 +鬟 +苯 +颂 +撷 +戈 +炒 +咆 +茭 +瘙 +负 +仰 +客 +琉 +铢 +封 +卑 +珥 +椿 +镧 +窨 +鬲 +寿 +御 +袤 +铃 +萎 +砖 +餮 +脒 +裳 +肪 +孕 +嫣 +馗 +嵇 +恳 +氯 +江 +石 +褶 +冢 +祸 +阻 +狈 +羞 +银 +靳 +透 +咳 +叼 +敷 +芷 +啥 +它 +瓤 +兰 +痘 +懊 +逑 +肌 +往 +捺 +坊 +甩 +呻 +〃 +沦 +忘 +膻 +祟 +菅 +剧 +崆 +智 +坯 +臧 +霍 +墅 +攻 +眯 +倘 +拢 +骠 +铐 +庭 +岙 +瓠 +′ +缺 +泥 +迢 +捶 +? +? +郏 +喙 +掷 +沌 +纯 +秘 +种 +听 +绘 +固 +螨 +团 +香 +盗 +妒 +埚 +蓝 +拖 +旱 +荞 +铀 +血 +遏 +汲 +辰 +叩 +拽 +幅 +硬 +惶 +桀 +漠 +措 +泼 +唑 +齐 +肾 +念 +酱 +虚 +屁 +耶 +旗 +砦 +闵 +婉 +馆 +拭 +绅 +韧 +忏 +窝 +醋 +葺 +顾 +辞 +倜 +堆 +辋 +逆 +玟 +贱 +疾 +董 +惘 +倌 +锕 +淘 +嘀 +莽 +俭 +笏 +绑 +鲷 +杈 +择 +蟀 +粥 +嗯 +驰 +逾 +案 +谪 +褓 +胫 +哩 +昕 +颚 +鲢 +绠 +躺 +鹄 +崂 +儒 +俨 +丝 +尕 +泌 +啊 +萸 +彰 +幺 +吟 +骄 +苣 +弦 +脊 +瑰 +〈 +诛 +镁 +析 +闪 +剪 +侧 +哟 +框 +螃 +守 +嬗 +燕 +狭 +铈 +缮 +概 +迳 +痧 +鲲 +俯 +售 +笼 +痣 +扉 +挖 +满 +咋 +援 +邱 +扇 +歪 +便 +玑 +绦 +峡 +蛇 +叨 +〖 +泽 +胃 +斓 +喋 +怂 +坟 +猪 +该 +蚬 +炕 +弥 +赞 +棣 +晔 +娠 +挲 +狡 +创 +疖 +铕 +镭 +稷 +挫 +弭 +啾 +翔 +粉 +履 +苘 +哦 +楼 +秕 +铂 +土 +锣 +瘟 +挣 +栉 +习 +享 +桢 +袅 +磨 +桂 +谦 +延 +坚 +蔚 +噗 +署 +谟 +猬 +钎 +恐 +嬉 +雒 +倦 +衅 +亏 +璩 +睹 +刻 +殿 +王 +算 +雕 +麻 +丘 +柯 +骆 +丸 +塍 +谚 +添 +鲈 +垓 +桎 +蚯 +芥 +予 +飕 +镦 +谌 +窗 +醚 +菀 +亮 +搪 +莺 +蒿 +羁 +足 +J +真 +轶 +悬 +衷 +靛 +翊 +掩 +哒 +炅 +掐 +冼 +妮 +l +谐 +稚 +荆 +擒 +犯 +陵 +虏 +浓 +崽 +刍 +陌 +傻 +孜 +千 +靖 +演 +矜 +钕 +煽 +杰 +酗 +渗 +伞 +栋 +俗 +泫 +戍 +罕 +沾 +疽 +灏 +煦 +芬 +磴 +叱 +阱 +榉 +湃 +蜀 +叉 +醒 +彪 +租 +郡 +篷 +屎 +良 +垢 +隗 +弱 +陨 +峪 +砷 +掴 +颁 +胎 +雯 +绵 +贬 +沐 +撵 +隘 +篙 +暖 +曹 +陡 +栓 +填 +臼 +彦 +瓶 +琪 +潼 +哪 +鸡 +摩 +啦 +俟 +锋 +域 +耻 +蔫 +疯 +纹 +撇 +毒 +绶 +痛 +酯 +忍 +爪 +赳 +歆 +嘹 +辕 +烈 +册 +朴 +钱 +吮 +毯 +癜 +娃 +谀 +邵 +厮 +炽 +璞 +邃 +丐 +追 +词 +瓒 +忆 +轧 +芫 +谯 +喷 +弟 +半 +冕 +裙 +掖 +墉 +绮 +寝 +苔 +势 +顷 +褥 +切 +衮 +君 +佳 +嫒 +蚩 +霞 +佚 +洙 +逊 +镖 +暹 +唛 +& +殒 +顶 +碗 +獗 +轭 +铺 +蛊 +废 +恹 +汨 +崩 +珍 +那 +杵 +曲 +纺 +夏 +薰 +傀 +闳 +淬 +姘 +舀 +拧 +卷 +楂 +恍 +讪 +厩 +寮 +篪 +赓 +乘 +灭 +盅 +鞣 +沟 +慎 +挂 +饺 +鼾 +杳 +树 +缨 +丛 +絮 +娌 +臻 +嗳 +篡 +侩 +述 +衰 +矛 +圈 +蚜 +匕 +筹 +匿 +濞 +晨 +叶 +骋 +郝 +挚 +蚴 +滞 +增 +侍 +描 +瓣 +吖 +嫦 +蟒 +匾 +圣 +赌 +毡 +癞 +恺 +百 +曳 +需 +篓 +肮 +庖 +帏 +卿 +驿 +遗 +蹬 +鬓 +骡 +歉 +芎 +胳 +屐 +禽 +烦 +晌 +寄 +媾 +狄 +翡 +苒 +船 +廉 +终 +痞 +殇 +々 +畦 +饶 +改 +拆 +悻 +萄 +£ +瓿 +乃 +訾 +桅 +匮 +溧 +拥 +纱 +铍 +骗 +蕃 +龋 +缬 +父 +佐 +疚 +栎 +醍 +掳 +蓄 +x +惆 +颜 +鲆 +榆 +〔 +猎 +敌 +暴 +谥 +鲫 +贾 +罗 +玻 +缄 +扦 +芪 +癣 +落 +徒 +臾 +恿 +猩 +托 +邴 +肄 +牵 +春 +陛 +耀 +刊 +拓 +蓓 +邳 +堕 +寇 +枉 +淌 +啡 +湄 +兽 +酷 +萼 +碚 +濠 +萤 +夹 +旬 +戮 +梭 +琥 +椭 +昔 +勺 +蜊 +绐 +晚 +孺 +僵 +宣 +摄 +冽 +旨 +萌 +忙 +蚤 +眉 +噼 +蟑 +付 +契 +瓜 +悼 +颡 +壁 +曾 +窕 +颢 +澎 +仿 +俑 +浑 +嵌 +浣 +乍 +碌 +褪 +乱 +蔟 +隙 +玩 +剐 +葫 +箫 +纲 +围 +伐 +决 +伙 +漩 +瑟 +刑 +肓 +镳 +缓 +蹭 +氨 +皓 +典 +畲 +坍 +铑 +檐 +塑 +洞 +倬 +储 +胴 +淳 +戾 +吐 +灼 +惺 +妙 +毕 +珐 +缈 +虱 +盖 +羰 +鸿 +磅 +谓 +髅 +娴 +苴 +唷 +蚣 +霹 +抨 +贤 +唠 +犬 +誓 +逍 +庠 +逼 +麓 +籼 +釉 +呜 +碧 +秧 +氩 +摔 +霄 +穸 +纨 +辟 +妈 +映 +完 +牛 +缴 +嗷 +炊 +恩 +荔 +茆 +掉 +紊 +慌 +莓 +羟 +阙 +萁 +磐 +另 +蕹 +辱 +鳐 +湮 +吡 +吩 +唐 +睦 +垠 +舒 +圜 +冗 +瞿 +溺 +芾 +囱 +匠 +僳 +汐 +菩 +饬 +漓 +黑 +霰 +浸 +濡 +窥 +毂 +蒡 +兢 +驻 +鹉 +芮 +诙 +迫 +雳 +厂 +忐 +臆 +猴 +鸣 +蚪 +栈 +箕 +羡 +渐 +莆 +捍 +眈 +哓 +趴 +蹼 +埕 +嚣 +骛 +宏 +淄 +斑 +噜 +严 +瑛 +垃 +椎 +诱 +压 +庾 +绞 +焘 +廿 +抡 +迄 +棘 +夫 +纬 +锹 +眨 +瞌 +侠 +脐 +竞 +瀑 +孳 +骧 +遁 +姜 +颦 +荪 +滚 +萦 +伪 +逸 +粳 +爬 +锁 +矣 +役 +趣 +洒 +颔 +诏 +逐 +奸 +甭 +惠 +攀 +蹄 +泛 +尼 +拼 +阮 +鹰 +亚 +颈 +惑 +勒 +〉 +际 +肛 +爷 +刚 +钨 +丰 +养 +冶 +鲽 +辉 +蔻 +画 +覆 +皴 +妊 +麦 +返 +醉 +皂 +擀 +〗 +酶 +凑 +粹 +悟 +诀 +硖 +港 +卜 +z +杀 +涕 +± +舍 +铠 +抵 +弛 +段 +敝 +镐 +奠 +拂 +轴 +跛 +袱 +e +t +沉 +菇 +俎 +薪 +峦 +秭 +蟹 +历 +盟 +菠 +寡 +液 +肢 +喻 +染 +裱 +悱 +抱 +氙 +赤 +捅 +猛 +跑 +氮 +谣 +仁 +尺 +辊 +窍 +烙 +衍 +架 +擦 +倏 +璐 +瑁 +币 +楞 +胖 +夔 +趸 +邛 +惴 +饕 +虔 +蝎 +§ +哉 +贝 +宽 +辫 +炮 +扩 +饲 +籽 +魏 +菟 +锰 +伍 +猝 +末 +琳 +哚 +蛎 +邂 +呀 +姿 +鄞 +却 +歧 +仙 +恸 +椐 +森 +牒 +寤 +袒 +婆 +虢 +雅 +钉 +朵 +贼 +欲 +苞 +寰 +故 +龚 +坭 +嘘 +咫 +礼 +硷 +兀 +睢 +汶 +’ +铲 +烧 +绕 +诃 +浃 +钿 +哺 +柜 +讼 +颊 +璁 +腔 +洽 +咐 +脲 +簌 +筠 +镣 +玮 +鞠 +谁 +兼 +姆 +挥 +梯 +蝴 +谘 +漕 +刷 +躏 +宦 +弼 +b +垌 +劈 +麟 +莉 +揭 +笙 +渎 +仕 +嗤 +仓 +配 +怏 +抬 +错 +泯 +镊 +孰 +猿 +邪 +仍 +秋 +鼬 +壹 +歇 +吵 +炼 +< +尧 +射 +柬 +廷 +胧 +霾 +凳 +隋 +肚 +浮 +梦 +祥 +株 +堵 +退 +L +鹫 +跎 +凶 +毽 +荟 +炫 +栩 +玳 +甜 +沂 +鹿 +顽 +伯 +爹 +赔 +蛴 +徐 +匡 +欣 +狰 +缸 +雹 +蟆 +疤 +默 +沤 +啜 +痂 +衣 +禅 +w +i +h +辽 +葳 +黝 +钗 +停 +沽 +棒 +馨 +颌 +肉 +吴 +硫 +悯 +劾 +娈 +马 +啧 +吊 +悌 +镑 +峭 +帆 +瀣 +涉 +咸 +疸 +滋 +泣 +翦 +拙 +癸 +钥 +蜒 ++ +尾 +庄 +凝 +泉 +婢 +渴 +谊 +乞 +陆 +锉 +糊 +鸦 +淮 +I +B +N +晦 +弗 +乔 +庥 +葡 +尻 +席 +橡 +傣 +渣 +拿 +惩 +麋 +斛 +缃 +矮 +蛏 +岘 +鸽 +姐 +膏 +催 +奔 +镒 +喱 +蠡 +摧 +钯 +胤 +柠 +拐 +璋 +鸥 +卢 +荡 +倾 +^ +_ +珀 +逄 +萧 +塾 +掇 +贮 +笆 +聂 +圃 +冲 +嵬 +M +滔 +笕 +值 +炙 +偶 +蜱 +搐 +梆 +汪 +蔬 +腑 +鸯 +蹇 +敞 +绯 +仨 +祯 +谆 +梧 +糗 +鑫 +啸 +豺 +囹 +猾 +巢 +柄 +瀛 +筑 +踌 +沭 +暗 +苁 +鱿 +蹉 +脂 +蘖 +牢 +热 +木 +吸 +溃 +宠 +序 +泞 +偿 +拜 +檩 +厚 +朐 +毗 +螳 +吞 +媚 +朽 +担 +蝗 +橘 +畴 +祈 +糟 +盱 +隼 +郜 +惜 +珠 +裨 +铵 +焙 +琚 +唯 +咚 +噪 +骊 +丫 +滢 +勤 +棉 +呸 +咣 +淀 +隔 +蕾 +窈 +饨 +挨 +煅 +短 +匙 +粕 +镜 +赣 +撕 +墩 +酬 +馁 +豌 +颐 +抗 +酣 +氓 +佑 +搁 +哭 +递 +耷 +涡 +桃 +贻 +碣 +截 +瘦 +昭 +镌 +蔓 +氚 +甲 +猕 +蕴 +蓬 +散 +拾 +纛 +狼 +猷 +铎 +埋 +旖 +矾 +讳 +囊 +糜 +迈 +粟 +蚂 +紧 +鲳 +瘢 +栽 +稼 +羊 +锄 +斟 +睁 +桥 +瓮 +蹙 +祉 +醺 +鼻 +昱 +剃 +跳 +篱 +跷 +蒜 +翎 +宅 +晖 +嗑 +壑 +峻 +癫 +屏 +狠 +陋 +袜 +途 +憎 +祀 +莹 +滟 +佶 +溥 +臣 +约 +盛 +峰 +磁 +慵 +婪 +拦 +莅 +朕 +鹦 +粲 +裤 +哎 +疡 +嫖 +琵 +窟 +堪 +谛 +嘉 +儡 +鳝 +斩 +郾 +驸 +酊 +妄 +胜 +贺 +徙 +傅 +噌 +钢 +栅 +庇 +恋 +匝 +巯 +邈 +尸 +锚 +粗 +佟 +蛟 +薹 +纵 +蚊 +郅 +绢 +锐 +苗 +俞 +篆 +淆 +膀 +鲜 +煎 +诶 +秽 +寻 +涮 +刺 +怀 +噶 +巨 +褰 +魅 +灶 +灌 +桉 +藕 +谜 +舸 +薄 +搀 +恽 +借 +牯 +痉 +渥 +愿 +亓 +耘 +杠 +柩 +锔 +蚶 +钣 +珈 +喘 +蹒 +幽 +赐 +稗 +晤 +莱 +泔 +扯 +肯 +菪 +裆 +腩 +豉 +疆 +骜 +腐 +倭 +珏 +唔 +粮 +亡 +润 +慰 +伽 +橄 +玄 +誉 +醐 +胆 +龊 +粼 +塬 +陇 +彼 +削 +嗣 +绾 +芽 +妗 +垭 +瘴 +爽 +薏 +寨 +龈 +泠 +弹 +赢 +漪 +猫 +嘧 +涂 +恤 +圭 +茧 +烽 +屑 +痕 +巾 +赖 +荸 +凰 +腮 +畈 +亵 +蹲 +偃 +苇 +澜 +艮 +换 +骺 +烘 +苕 +梓 +颉 +肇 +哗 +悄 +氤 +涠 +葬 +屠 +鹭 +植 +竺 +佯 +诣 +鲇 +瘀 +鲅 +邦 +移 +滁 +冯 +耕 +癔 +戌 +茬 +沁 +巩 +悠 +湘 +洪 +痹 +锟 +循 +谋 +腕 +鳃 +钠 +捞 +焉 +迎 +碱 +伫 +急 +榷 +奈 +邝 +卯 +辄 +皲 +卟 +醛 +畹 +忧 +稳 +雄 +昼 +缩 +阈 +睑 +扌 +耗 +曦 +涅 +捏 +瞧 +邕 +淖 +漉 +铝 +耦 +禹 +湛 +喽 +莼 +琅 +诸 +苎 +纂 +硅 +始 +嗨 +傥 +燃 +臂 +赅 +嘈 +呆 +贵 +屹 +壮 +肋 +亍 +蚀 +卅 +豹 +腆 +邬 +迭 +浊 +} +童 +螂 +捐 +圩 +勐 +触 +寞 +汊 +壤 +荫 +膺 +渌 +芳 +懿 +遴 +螈 +泰 +蓼 +蛤 +茜 +舅 +枫 +朔 +膝 +眙 +避 +梅 +判 +鹜 +璜 +牍 +缅 +垫 +藻 +黔 +侥 +惚 +懂 +踩 +腰 +腈 +札 +丞 +唾 +慈 +顿 +摹 +荻 +琬 +~ +斧 +沈 +滂 +胁 +胀 +幄 +莜 +Z +匀 +鄄 +掌 +绰 +茎 +焚 +赋 +萱 +谑 +汁 +铒 +瞎 +夺 +蜗 +野 +娆 +冀 +弯 +篁 +懵 +灞 +隽 +芡 +脘 +俐 +辩 +芯 +掺 +喏 +膈 +蝈 +觐 +悚 +踹 +蔗 +熠 +鼠 +呵 +抓 +橼 +峨 +畜 +缔 +禾 +崭 +弃 +熊 +摒 +凸 +拗 +穹 +蒙 +抒 +祛 +劝 +闫 +扳 +阵 +醌 +踪 +喵 +侣 +搬 +仅 +荧 +赎 +蝾 +琦 +买 +婧 +瞄 +寓 +皎 +冻 +赝 +箩 +莫 +瞰 +郊 +笫 +姝 +筒 +枪 +遣 +煸 +袋 +舆 +痱 +涛 +母 +〇 +启 +践 +耙 +绲 +盘 +遂 +昊 +搞 +槿 +诬 +纰 +泓 +惨 +檬 +亻 +越 +C +o +憩 +熵 +祷 +钒 +暧 +塔 +阗 +胰 +咄 +娶 +魔 +琶 +钞 +邻 +扬 +杉 +殴 +咽 +弓 +〆 +髻 +】 +吭 +揽 +霆 +拄 +殖 +脆 +彻 +岩 +芝 +勃 +辣 +剌 +钝 +嘎 +甄 +佘 +皖 +伦 +授 +徕 +憔 +挪 +皇 +庞 +稔 +芜 +踏 +溴 +兖 +卒 +擢 +饥 +鳞 +煲 +‰ +账 +颗 +叻 +斯 +捧 +鳍 +琮 +讹 +蛙 +纽 +谭 +酸 +兔 +莒 +睇 +伟 +觑 +羲 +嗜 +宜 +褐 +旎 +辛 +卦 +诘 +筋 +鎏 +溪 +挛 +熔 +阜 +晰 +鳅 +丢 +奚 +灸 +呱 +献 +陉 +黛 +鸪 +甾 +萨 +疮 +拯 +洲 +疹 +辑 +叙 +恻 +谒 +允 +柔 +烂 +氏 +逅 +漆 +拎 +惋 +扈 +湟 +纭 +啕 +掬 +擞 +哥 +忽 +涤 +鸵 +靡 +郗 +瓷 +扁 +廊 +怨 +雏 +钮 +敦 +E +懦 +憋 +汀 +拚 +啉 +腌 +岸 +f +痼 +瞅 +尊 +咀 +眩 +飙 +忌 +仝 +迦 +熬 +毫 +胯 +篑 +茄 +腺 +凄 +舛 +碴 +锵 +诧 +羯 +後 +漏 +汤 +宓 +仞 +蚁 +壶 +谰 +皑 +铄 +棰 +罔 +辅 +晶 +苦 +牟 +闽 +\ +烃 +饮 +聿 +丙 +蛳 +朱 +煤 +涔 +鳖 +犁 +罐 +荼 +砒 +淦 +妤 +黏 +戎 +孑 +婕 +瑾 +戢 +钵 +枣 +捋 +砥 +衩 +狙 +桠 +稣 +阎 +肃 +梏 +诫 +孪 +昶 +婊 +衫 +嗔 +侃 +塞 +蜃 +樵 +峒 +貌 +屿 +欺 +缫 +阐 +栖 +诟 +珞 +荭 +吝 +萍 +嗽 +恂 +啻 +蜴 +磬 +峋 +俸 +豫 +谎 +徊 +镍 +韬 +魇 +晴 +U +囟 +猜 +蛮 +坐 +囿 +伴 +亭 +肝 +佗 +蝠 +妃 +胞 +滩 +榴 +氖 +垩 +苋 +砣 +扪 +馏 +姓 +轩 +厉 +夥 +侈 +禀 +垒 +岑 +赏 +钛 +辐 +痔 +披 +纸 +碳 +“ +坞 +蠓 +挤 +荥 +沅 +悔 +铧 +帼 +蒌 +蝇 +a +p +y +n +g +哀 +浆 +瑶 +凿 +桶 +馈 +皮 +奴 +苜 +佤 +伶 +晗 +铱 +炬 +优 +弊 +氢 +恃 +甫 +攥 +端 +锌 +灰 +稹 +炝 +曙 +邋 +亥 +眶 +碾 +拉 +萝 +绔 +捷 +浍 +腋 +姑 +菖 +凌 +涞 +麽 +锢 +桨 +潢 +绎 +镰 +殆 +锑 +渝 +铬 +困 +绽 +觎 +匈 +糙 +暑 +裹 +鸟 +盔 +肽 +迷 +綦 +『 +亳 +佝 +俘 +钴 +觇 +骥 +仆 +疝 +跪 +婶 +郯 +瀹 +唉 +脖 +踞 +针 +晾 +忒 +扼 +瞩 +叛 +椒 +疟 +嗡 +邗 +肆 +跆 +玫 +忡 +捣 +咧 +唆 +艄 +蘑 +潦 +笛 +阚 +沸 +泻 +掊 +菽 +贫 +斥 +髂 +孢 +镂 +赂 +麝 +鸾 +屡 +衬 +苷 +恪 +叠 +希 +粤 +爻 +喝 +茫 +惬 +郸 +绻 +庸 +撅 +碟 +宄 +妹 +膛 +叮 +饵 +崛 +嗲 +椅 +冤 +搅 +咕 +敛 +尹 +垦 +闷 +蝉 +霎 +勰 +败 +蓑 +泸 +肤 +鹌 +幌 +焦 +浠 +鞍 +刁 +舰 +乙 +竿 +裔 +。 +茵 +函 +伊 +兄 +丨 +娜 +匍 +謇 +莪 +宥 +似 +蝽 +翳 +酪 +翠 +粑 +薇 +祢 +骏 +赠 +叫 +Q +噤 +噻 +竖 +芗 +莠 +潭 +俊 +羿 +耜 +O +郫 +趁 +嗪 +囚 +蹶 +芒 +洁 +笋 +鹑 +敲 +硝 +啶 +堡 +渲 +揩 +』 +携 +宿 +遒 +颍 +扭 +棱 +割 +萜 +蔸 +葵 +琴 +捂 +饰 +衙 +耿 +掠 +募 +岂 +窖 +涟 +蔺 +瘤 +柞 +瞪 +怜 +匹 +距 +楔 +炜 +哆 +秦 +缎 +幼 +茁 +绪 +痨 +恨 +楸 +娅 +瓦 +桩 +雪 +嬴 +伏 +榔 +妥 +铿 +拌 +眠 +雍 +缇 +‘ +卓 +搓 +哌 +觞 +噩 +屈 +哧 +髓 +咦 +巅 +娑 +侑 +淫 +膳 +祝 +勾 +姊 +莴 +胄 +疃 +薛 +蜷 +胛 +巷 +芙 +芋 +熙 +闰 +勿 +窃 +狱 +剩 +钏 +幢 +陟 +铛 +慧 +靴 +耍 +k +浙 +浇 +飨 +惟 +绗 +祜 +澈 +啼 +咪 +磷 +摞 +诅 +郦 +抹 +跃 +壬 +吕 +肖 +琏 +颤 +尴 +剡 +抠 +凋 +赚 +泊 +津 +宕 +殷 +倔 +氲 +漫 +邺 +涎 +怠 +$ +垮 +荬 +遵 +俏 +叹 +噢 +饽 +蜘 +孙 +筵 +疼 +鞭 +羧 +牦 +箭 +潴 +c +眸 +祭 +髯 +啖 +坳 +愁 +芩 +驮 +倡 +巽 +穰 +沃 +胚 +怒 +凤 +槛 +剂 +趵 +嫁 +v +邢 +灯 +鄢 +桐 +睽 +檗 +锯 +槟 +婷 +嵋 +圻 +诗 +蕈 +颠 +遭 +痢 +芸 +怯 +馥 +竭 +锗 +徜 +恭 +遍 +籁 +剑 +嘱 +苡 +龄 +僧 +桑 +潸 +弘 +澶 +楹 +悲 +讫 +愤 +腥 +悸 +谍 +椹 +呢 +桓 +葭 +攫 +阀 +翰 +躲 +敖 +柑 +郎 +笨 +橇 +呃 +魁 +燎 +脓 +葩 +磋 +垛 +玺 +狮 +沓 +砜 +蕊 +锺 +罹 +蕉 +翱 +虐 +闾 +巫 +旦 +茱 +嬷 +枯 +鹏 +贡 +芹 +汛 +矫 +绁 +拣 +禺 +佃 +讣 +舫 +惯 +乳 +趋 +疲 +挽 +岚 +虾 +衾 +蠹 +蹂 +飓 +氦 +铖 +孩 +稞 +瑜 +壅 +掀 +勘 +妓 +畅 +髋 +W +庐 +牲 +蓿 +榕 +练 +垣 +唱 +邸 +菲 +昆 +婺 +穿 +绡 +麒 +蚱 +掂 +愚 +泷 +涪 +漳 +妩 +娉 +榄 +讷 +觅 +旧 +藤 +煮 +呛 +柳 +腓 +叭 +庵 +烷 +阡 +罂 +蜕 +擂 +猖 +咿 +媲 +脉 +【 +沏 +貅 +黠 +熏 +哲 +烁 +坦 +酵 +兜 +× +潇 +撒 +剽 +珩 +圹 +乾 +摸 +樟 +帽 +嗒 +襄 +魂 +轿 +憬 +锡 +〕 +喃 +皆 +咖 +隅 +脸 +残 +泮 +袂 +鹂 +珊 +囤 +捆 +咤 +误 +徨 +闹 +淙 +芊 +淋 +怆 +囗 +拨 +梳 +渤 +R +G +绨 +蚓 +婀 +幡 +狩 +麾 +谢 +唢 +裸 +旌 +伉 +纶 +裂 +驳 +砼 +咛 +澄 +樨 +蹈 +宙 +澍 +倍 +貔 +操 +勇 +蟠 +摈 +砧 +虬 +够 +缁 +悦 +藿 +撸 +艹 +摁 +淹 +豇 +虎 +榭 +ˉ +吱 +d +° +喧 +荀 +踱 +侮 +奋 +偕 +饷 +犍 +惮 +坑 +璎 +徘 +宛 +妆 +袈 +倩 +窦 +昂 +荏 +乖 +K +怅 +撰 +鳙 +牙 +袁 +酞 +X +痿 +琼 +闸 +雁 +趾 +荚 +虻 +涝 +《 +杏 +韭 +偈 +烤 +绫 +鞘 +卉 +症 +遢 +蓥 +诋 +杭 +荨 +匆 +竣 +簪 +辙 +敕 +虞 +丹 +缭 +咩 +黟 +m +淤 +瑕 +咂 +铉 +硼 +茨 +嶂 +痒 +畸 +敬 +涿 +粪 +窘 +熟 +叔 +嫔 +盾 +忱 +裘 +憾 +梵 +赡 +珙 +咯 +娘 +庙 +溯 +胺 +葱 +痪 +摊 +荷 +卞 +乒 +髦 +寐 +铭 +坩 +胗 +枷 +爆 +溟 +嚼 +羚 +砬 +轨 +惊 +挠 +罄 +竽 +菏 +氧 +浅 +楣 +盼 +枢 +炸 +阆 +杯 +谏 +噬 +淇 +渺 +俪 +秆 +墓 +泪 +跻 +砌 +痰 +垡 +渡 +耽 +釜 +讶 +鳎 +煞 +呗 +韶 +舶 +绷 +鹳 +缜 +旷 +铊 +皱 +龌 +檀 +霖 +奄 +槐 +艳 +蝶 +旋 +哝 +赶 +骞 +蚧 +腊 +盈 +丁 +` +蜚 +矸 +蝙 +睨 +嚓 +僻 +鬼 +醴 +夜 +彝 +磊 +笔 +拔 +栀 +糕 +厦 +邰 +纫 +逭 +纤 +眦 +膊 +馍 +躇 +烯 +蘼 +冬 +诤 +暄 +骶 +哑 +瘠 +」 +臊 +丕 +愈 +咱 +螺 +擅 +跋 +搏 +硪 +谄 +笠 +淡 +嘿 +骅 +谧 +鼎 +皋 +姚 +歼 +蠢 +驼 +耳 +胬 +挝 +涯 +狗 +蒽 +孓 +犷 +凉 +芦 +箴 +铤 +孤 +嘛 +坤 +V +茴 +朦 +挞 +尖 +橙 +诞 +搴 +碇 +洵 +浚 +帚 +蜍 +漯 +柘 +嚎 +讽 +芭 +荤 +咻 +祠 +秉 +跖 +埃 +吓 +糯 +眷 +馒 +惹 +娼 +鲑 +嫩 +讴 +轮 +瞥 +靶 +褚 +乏 +缤 +宋 +帧 +删 +驱 +碎 +扑 +俩 +俄 +偏 +涣 +竹 +噱 +皙 +佰 +渚 +唧 +斡 +# +镉 +刀 +崎 +筐 +佣 +夭 +贰 +肴 +峙 +哔 +艿 +匐 +牺 +镛 +缘 +仡 +嫡 +劣 +枸 +堀 +梨 +簿 +鸭 +蒸 +亦 +稽 +浴 +{ +衢 +束 +槲 +j +阁 +揍 +疥 +棋 +潋 +聪 +窜 +乓 +睛 +插 +冉 +阪 +苍 +搽 +「 +蟾 +螟 +幸 +仇 +樽 +撂 +慢 +跤 +幔 +俚 +淅 +覃 +觊 +溶 +妖 +帛 +侨 +曰 +妾 +泗 +· +: +瀘 +風 +Ë +( +) +∶ +紅 +紗 +瑭 +雲 +頭 +鶏 +財 +許 +• +¥ +樂 +焗 +麗 +— +; +滙 +東 +榮 +繪 +興 +… +門 +業 +π +楊 +國 +顧 +é +盤 +寳 +Λ +龍 +鳳 +島 +誌 +緣 +結 +銭 +萬 +勝 +祎 +璟 +優 +歡 +臨 +時 +購 += +★ +藍 +昇 +鐵 +觀 +勅 +農 +聲 +畫 +兿 +術 +發 +劉 +記 +專 +耑 +園 +書 +壴 +種 +Ο +● +褀 +號 +銀 +匯 +敟 +锘 +葉 +橪 +廣 +進 +蒄 +鑽 +阝 +祙 +貢 +鍋 +豊 +夬 +喆 +團 +閣 +開 +燁 +賓 +館 +酡 +沔 +順 ++ +硚 +劵 +饸 +陽 +車 +湓 +復 +萊 +氣 +軒 +華 +堃 +迮 +纟 +戶 +馬 +學 +裡 +電 +嶽 +獨 +マ +シ +サ +ジ +燘 +袪 +環 +❤ +臺 +灣 +専 +賣 +孖 +聖 +攝 +線 +▪ +α +傢 +俬 +夢 +達 +莊 +喬 +貝 +薩 +劍 +羅 +壓 +棛 +饦 +尃 +璈 +囍 +醫 +G +I +A +# +N +鷄 +髙 +嬰 +啓 +約 +隹 +潔 +賴 +藝 +~ +寶 +籣 +麺 +  +嶺 +√ +義 +網 +峩 +長 +∧ +魚 +機 +構 +② +鳯 +偉 +L +B +㙟 +畵 +鴿 +' +詩 +溝 +嚞 +屌 +藔 +佧 +玥 +蘭 +織 +1 +3 +9 +0 +7 +點 +砭 +鴨 +鋪 +銘 +廳 +弍 +‧ +創 +湯 +坶 +℃ +卩 +骝 +& +烜 +荘 +當 +潤 +扞 +係 +懷 +碶 +钅 +蚨 +讠 +☆ +叢 +爲 +埗 +涫 +塗 +→ +楽 +現 +鯨 +愛 +瑪 +鈺 +忄 +悶 +藥 +飾 +樓 +視 +孬 +ㆍ +燚 +苪 +師 +① +丼 +锽 +│ +韓 +標 +è +兒 +閏 +匋 +張 +漢 +Ü +髪 +會 +閑 +檔 +習 +裝 +の +峯 +菘 +輝 +И +雞 +釣 +億 +浐 +K +O +R +8 +H +E +P +T +W +D +S +C +M +F +姌 +饹 +» +晞 +廰 +ä +嵯 +鷹 +負 +飲 +絲 +冚 +楗 +澤 +綫 +區 +❋ +← +質 +靑 +揚 +③ +滬 +統 +産 +協 +﹑ +乸 +畐 +經 +運 +際 +洺 +岽 +為 +粵 +諾 +崋 +豐 +碁 +ɔ +V +2 +6 +齋 +誠 +訂 +´ +勑 +雙 +陳 +無 +í +泩 +媄 +夌 +刂 +i +c +t +o +r +a +嘢 +耄 +燴 +暃 +壽 +媽 +靈 +抻 +體 +唻 +É +冮 +甹 +鎮 +錦 +ʌ +蜛 +蠄 +尓 +駕 +戀 +飬 +逹 +倫 +貴 +極 +Я +Й +寬 +磚 +嶪 +郎 +職 +| +間 +n +d +剎 +伈 +課 +飛 +橋 +瘊 +№ +譜 +骓 +圗 +滘 +縣 +粿 +咅 +養 +濤 +彳 +® +% +Ⅱ +啰 +㴪 +見 +矞 +薬 +糁 +邨 +鲮 +顔 +罱 +З +選 +話 +贏 +氪 +俵 +競 +瑩 +繡 +枱 +β +綉 +á +獅 +爾 +™ +麵 +戋 +淩 +徳 +個 +劇 +場 +務 +簡 +寵 +h +實 +膠 +轱 +圖 +築 +嘣 +樹 +㸃 +營 +耵 +孫 +饃 +鄺 +飯 +麯 +遠 +輸 +坫 +孃 +乚 +閃 +鏢 +㎡ +題 +廠 +關 +↑ +爺 +將 +軍 +連 +篦 +覌 +參 +箸 +- +窠 +棽 +寕 +夀 +爰 +歐 +呙 +閥 +頡 +熱 +雎 +垟 +裟 +凬 +勁 +帑 +馕 +夆 +疌 +枼 +馮 +貨 +蒤 +樸 +彧 +旸 +靜 +龢 +暢 +㐱 +鳥 +珺 +鏡 +灡 +爭 +堷 +廚 +Ó +騰 +診 +┅ +蘇 +褔 +凱 +頂 +豕 +亞 +帥 +嘬 +⊥ +仺 +桖 +複 +饣 +絡 +穂 +顏 +棟 +納 +▏ +濟 +親 +設 +計 +攵 +埌 +烺 +ò +頤 +燦 +蓮 +撻 +節 +講 +濱 +濃 +娽 +洳 +朿 +燈 +鈴 +護 +膚 +铔 +過 +補 +Z +U +5 +4 +坋 +闿 +䖝 +餘 +缐 +铞 +貿 +铪 +桼 +趙 +鍊 +[ +㐂 +垚 +菓 +揸 +捲 +鐘 +滏 +𣇉 +爍 +輪 +燜 +鴻 +鮮 +動 +鹞 +鷗 +丄 +慶 +鉌 +翥 +飮 +腸 +⇋ +漁 +覺 +來 +熘 +昴 +翏 +鲱 +圧 +鄉 +萭 +頔 +爐 +嫚 +г +貭 +類 +聯 +幛 +輕 +訓 +鑒 +夋 +锨 +芃 +珣 +䝉 +扙 +嵐 +銷 +處 +ㄱ +語 +誘 +苝 +歸 +儀 +燒 +楿 +內 +粢 +葒 +奧 +麥 +礻 +滿 +蠔 +穵 +瞭 +態 +鱬 +榞 +硂 +鄭 +黃 +煙 +祐 +奓 +逺 +* +瑄 +獲 +聞 +薦 +讀 +這 +樣 +決 +問 +啟 +們 +執 +説 +轉 +單 +隨 +唘 +帶 +倉 +庫 +還 +贈 +尙 +皺 +■ +餅 +產 +○ +∈ +報 +狀 +楓 +賠 +琯 +嗮 +禮 +` +傳 +> +≤ +嗞 +Φ +≥ +換 +咭 +∣ +↓ +曬 +ε +応 +寫 +″ +終 +様 +純 +費 +療 +聨 +凍 +壐 +郵 +ü +黒 +∫ +製 +塊 +調 +軽 +確 +撃 +級 +馴 +Ⅲ +涇 +繹 +數 +碼 +證 +狒 +処 +劑 +< +晧 +賀 +衆 +] +櫥 +兩 +陰 +絶 +對 +鯉 +憶 +◎ +p +e +Y +蕒 +煖 +頓 +測 +試 +鼽 +僑 +碩 +妝 +帯 +≈ +鐡 +舖 +權 +喫 +倆 +ˋ +該 +悅 +ā +俫 +. +f +s +b +m +k +g +u +j +貼 +淨 +濕 +針 +適 +備 +l +/ +給 +謢 +強 +觸 +衛 +與 +⊙ +$ +緯 +變 +⑴ +⑵ +⑶ +㎏ +殺 +∩ +幚 +─ +價 +▲ +離 +ú +ó +飄 +烏 +関 +閟 +﹝ +﹞ +邏 +輯 +鍵 +驗 +訣 +導 +歷 +屆 +層 +▼ +儱 +錄 +熳 +ē +艦 +吋 +錶 +辧 +飼 +顯 +④ +禦 +販 +気 +対 +枰 +閩 +紀 +幹 +瞓 +貊 +淚 +△ +眞 +墊 +Ω +獻 +褲 +縫 +緑 +亜 +鉅 +餠 +{ +} +◆ +蘆 +薈 +█ +◇ +溫 +彈 +晳 +粧 +犸 +穩 +訊 +崬 +凖 +熥 +П +舊 +條 +紋 +圍 +Ⅳ +筆 +尷 +難 +雜 +錯 +綁 +識 +頰 +鎖 +艶 +□ +殁 +殼 +⑧ +├ +▕ +鵬 +ǐ +ō +ǒ +糝 +綱 +▎ +μ +盜 +饅 +醬 +籤 +蓋 +釀 +鹽 +據 +à +ɡ +辦 +◥ +彐 +┌ +婦 +獸 +鲩 +伱 +ī +蒟 +蒻 +齊 +袆 +腦 +寧 +凈 +妳 +煥 +詢 +偽 +謹 +啫 +鯽 +騷 +鱸 +損 +傷 +鎻 +髮 +買 +冏 +儥 +両 +﹢ +∞ +載 +喰 +z +羙 +悵 +燙 +曉 +員 +組 +徹 +艷 +痠 +鋼 +鼙 +縮 +細 +嚒 +爯 +≠ +維 +" +鱻 +壇 +厍 +帰 +浥 +犇 +薡 +軎 +² +應 +醜 +刪 +緻 +鶴 +賜 +噁 +軌 +尨 +镔 +鷺 +槗 +彌 +葚 +濛 +請 +溇 +緹 +賢 +訪 +獴 +瑅 +資 +縤 +陣 +蕟 +栢 +韻 +祼 +恁 +伢 +謝 +劃 +涑 +總 +衖 +踺 +砋 +凉 +籃 +駿 +苼 +瘋 +昽 +紡 +驊 +腎 +﹗ +響 +杋 +剛 +嚴 +禪 +歓 +槍 +傘 +檸 +檫 +炣 +勢 +鏜 +鎢 +銑 +尐 +減 +奪 +惡 +θ +僮 +婭 +臘 +ū +ì +殻 +鉄 +∑ +蛲 +焼 +緖 +續 +紹 +懮 diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java new file mode 100644 index 000000000..9ce3b3876 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java @@ -0,0 +1,500 @@ +package com.baidu.paddle.fastdeploy.app.examples.ocr; + +import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.adapter.BaseResultAdapter; +import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.pipeline.PPOCRv3; +import com.baidu.paddle.fastdeploy.vision.OCRResult; +import com.baidu.paddle.fastdeploy.vision.Visualize; +import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; +import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector; +import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class OcrMainActivity extends Activity implements View.OnClickListener, CameraSurfaceView.OnTextureChangedListener { + private static final String TAG = OcrMainActivity.class.getSimpleName(); + + CameraSurfaceView svPreview; + TextView tvStatus; + ImageButton btnSwitch; + ImageButton btnShutter; + ImageButton btnSettings; + ImageView realtimeToggleButton; + boolean isRealtimeStatusRunning = false; + ImageView backInPreview; + private ImageView albumSelectButton; + private View cameraPageView; + private ViewGroup resultPageView; + private ImageView resultImage; + private ImageView backInResult; + private SeekBar confidenceSeekbar; + private TextView seekbarText; + private float resultNum = 1.0f; + private ResultListView resultView; + private Bitmap picBitmap; + private Bitmap shutterBitmap; + private Bitmap originPicBitmap; + private Bitmap originShutterBitmap; + private boolean isShutterBitmapCopied = false; + + public static final int TYPE_UNKNOWN = -1; + public static final int BTN_SHUTTER = 0; + public static final int ALBUM_SELECT = 1; + public static final int REALTIME_DETECT = 2; + private static int TYPE = REALTIME_DETECT; + + private static final int REQUEST_PERMISSION_CODE_STORAGE = 101; + private static final int INTENT_CODE_PICK_IMAGE = 100; + private static final int TIME_SLEEP_INTERVAL = 50; // ms + + long timeElapsed = 0; + long frameCounter = 0; + + // Call 'init' and 'release' manually later + PPOCRv3 predictor = new PPOCRv3(); + + private String[] texts; + private float[] recScores; + private boolean initialized; + private List results = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Fullscreen + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.ocr_activity_main); + + // Clear all setting items to avoid app crashing due to the incorrect settings + initSettings(); + + // Check and request CAMERA and WRITE_EXTERNAL_STORAGE permissions + if (!checkAllPermissions()) { + requestAllPermissions(); + } + + // Init the camera preview and UI components + initView(); + } + + @SuppressLint("NonConstantResourceId") + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_switch: + svPreview.switchCamera(); + break; + case R.id.btn_shutter: + TYPE = BTN_SHUTTER; + shutterAndPauseCamera(); + resultView.setAdapter(null); + break; + case R.id.btn_settings: + startActivity(new Intent(OcrMainActivity.this, OcrSettingsActivity.class)); + break; + case R.id.realtime_toggle_btn: + toggleRealtimeStyle(); + break; + case R.id.back_in_preview: + finish(); + break; + case R.id.iv_select: + TYPE = ALBUM_SELECT; + // Judge whether authority has been granted. + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + // If this permission was requested before the application but the user refused the request, this method will return true. + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE_STORAGE); + } else { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + startActivityForResult(intent, INTENT_CODE_PICK_IMAGE); + } + resultView.setAdapter(null); + break; + case R.id.back_in_result: + back(); + break; + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + back(); + } + + private void back() { + resultPageView.setVisibility(View.GONE); + cameraPageView.setVisibility(View.VISIBLE); + TYPE = REALTIME_DETECT; + isShutterBitmapCopied = false; + svPreview.onResume(); + results.clear(); + if (texts != null) { + texts = null; + } + if (recScores != null) { + recScores = null; + } + } + + private void shutterAndPauseCamera() { + new Thread(new Runnable() { + @Override + public void run() { + try { + // Sleep some times to ensure picture has been correctly shut. + Thread.sleep(TIME_SLEEP_INTERVAL * 10); // 500ms + } catch (InterruptedException e) { + e.printStackTrace(); + } + runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + public void run() { + // These code will run in main thread. + svPreview.onPause(); + cameraPageView.setVisibility(View.GONE); + resultPageView.setVisibility(View.VISIBLE); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + if (shutterBitmap != null && !shutterBitmap.isRecycled()) { + resultImage.setImageBitmap(shutterBitmap); + } else { + new AlertDialog.Builder(OcrMainActivity.this) + .setTitle("Empty Result!") + .setMessage("Current picture is empty, please shutting it again!") + .setCancelable(true) + .show(); + } + } + }); + + } + }).start(); + } + + private void copyBitmapFromCamera(Bitmap ARGB8888ImageBitmap) { + if (isShutterBitmapCopied || ARGB8888ImageBitmap == null) { + return; + } + if (!ARGB8888ImageBitmap.isRecycled()) { + synchronized (this) { + shutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true); + originShutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true); + } + SystemClock.sleep(TIME_SLEEP_INTERVAL); + isShutterBitmapCopied = true; + } + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == INTENT_CODE_PICK_IMAGE) { + if (resultCode == Activity.RESULT_OK) { + cameraPageView.setVisibility(View.GONE); + resultPageView.setVisibility(View.VISIBLE); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + Uri uri = data.getData(); + String path = getRealPathFromURI(this, uri); + picBitmap = decodeBitmap(path, 720, 1280); + originPicBitmap = picBitmap.copy(Bitmap.Config.ARGB_8888, true); + resultImage.setImageBitmap(picBitmap); + } + } + } + + private void toggleRealtimeStyle() { + if (isRealtimeStatusRunning) { + isRealtimeStatusRunning = false; + realtimeToggleButton.setImageResource(R.drawable.realtime_stop_btn); + svPreview.setOnTextureChangedListener(this); + tvStatus.setVisibility(View.VISIBLE); + } else { + isRealtimeStatusRunning = true; + realtimeToggleButton.setImageResource(R.drawable.realtime_start_btn); + tvStatus.setVisibility(View.GONE); + isShutterBitmapCopied = false; + svPreview.setOnTextureChangedListener(new CameraSurfaceView.OnTextureChangedListener() { + @Override + public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { + if (TYPE == BTN_SHUTTER) { + copyBitmapFromCamera(ARGB8888ImageBitmap); + } + return false; + } + }); + } + } + + @Override + public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { + if (TYPE == BTN_SHUTTER) { + copyBitmapFromCamera(ARGB8888ImageBitmap); + return false; + } + + boolean modified = false; + + long tc = System.currentTimeMillis(); + OCRResult result = predictor.predict(ARGB8888ImageBitmap); + timeElapsed += (System.currentTimeMillis() - tc); + + Visualize.visOcr(ARGB8888ImageBitmap, result); + modified = result.initialized(); + + frameCounter++; + if (frameCounter >= 30) { + final int fps = (int) (1000 / (timeElapsed / 30)); + runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + public void run() { + tvStatus.setText(Integer.toString(fps) + "fps"); + } + }); + frameCounter = 0; + timeElapsed = 0; + } + return modified; + } + + @Override + protected void onResume() { + super.onResume(); + // Reload settings and re-initialize the predictor + checkAndUpdateSettings(); + // Open camera until the permissions have been granted + if (!checkAllPermissions()) { + svPreview.disableCamera(); + } else { + svPreview.enableCamera(); + } + svPreview.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + svPreview.onPause(); + } + + @Override + protected void onDestroy() { + if (predictor != null) { + predictor.release(); + } + super.onDestroy(); + } + + public void initView() { + TYPE = REALTIME_DETECT; + svPreview = (CameraSurfaceView) findViewById(R.id.sv_preview); + svPreview.setOnTextureChangedListener(this); + tvStatus = (TextView) findViewById(R.id.tv_status); + btnSwitch = (ImageButton) findViewById(R.id.btn_switch); + btnSwitch.setOnClickListener(this); + btnShutter = (ImageButton) findViewById(R.id.btn_shutter); + btnShutter.setOnClickListener(this); + btnSettings = (ImageButton) findViewById(R.id.btn_settings); + btnSettings.setOnClickListener(this); + realtimeToggleButton = findViewById(R.id.realtime_toggle_btn); + realtimeToggleButton.setOnClickListener(this); + backInPreview = findViewById(R.id.back_in_preview); + backInPreview.setOnClickListener(this); + albumSelectButton = findViewById(R.id.iv_select); + albumSelectButton.setOnClickListener(this); + cameraPageView = findViewById(R.id.camera_page); + resultPageView = findViewById(R.id.result_page); + resultImage = findViewById(R.id.result_image); + backInResult = findViewById(R.id.back_in_result); + backInResult.setOnClickListener(this); + confidenceSeekbar = findViewById(R.id.confidence_seekbar); + seekbarText = findViewById(R.id.seekbar_text); + resultView = findViewById(R.id.result_list_view); + + confidenceSeekbar.setMax(100); + confidenceSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + float resultConfidence = seekBar.getProgress() / 100f; + BigDecimal bd = new BigDecimal(resultConfidence); + resultNum = bd.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue(); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + results.clear(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (TYPE == ALBUM_SELECT) { + SystemClock.sleep(TIME_SLEEP_INTERVAL * 10); + detail(picBitmap); + picBitmap = originPicBitmap.copy(Bitmap.Config.ARGB_8888, true); + } else { + SystemClock.sleep(TIME_SLEEP_INTERVAL * 10); + detail(shutterBitmap); + shutterBitmap = originShutterBitmap.copy(Bitmap.Config.ARGB_8888, true); + } + } + }); + } + }); + } + + private void detail(Bitmap bitmap) { + OCRResult result = predictor.predict(bitmap, true); + + texts = result.mText; + recScores = result.mRecScores; + + initialized = result.initialized(); + if (initialized) { + for (int i = 0; i < texts.length; i++) { + if (recScores[i] > resultNum) { + results.add(new BaseResultModel(i + 1, texts[i], recScores[i])); + } + } + } + BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.ocr_result_page_item, results); + resultView.setAdapter(adapter); + resultView.invalidate(); + + resultImage.setImageBitmap(bitmap); + resultNum = 1.0f; + } + + @SuppressLint("ApplySharedPref") + public void initSettings() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.clear(); + editor.commit(); + OcrSettingsActivity.resetSettings(); + } + + public void checkAndUpdateSettings() { + if (OcrSettingsActivity.checkAndUpdateSettings(this)) { + String realModelDir = getCacheDir() + "/" + OcrSettingsActivity.modelDir; + String detModelName = "ch_PP-OCRv3_det_infer"; + // String detModelName = "ch_ppocr_mobile_v2.0_det_infer"; + String clsModelName = "ch_ppocr_mobile_v2.0_cls_infer"; + // String recModelName = "ch_ppocr_mobile_v2.0_rec_infer"; + String recModelName = "ch_PP-OCRv3_rec_infer"; + String realDetModelDir = realModelDir + "/" + detModelName; + String realClsModelDir = realModelDir + "/" + clsModelName; + String realRecModelDir = realModelDir + "/" + recModelName; + String srcDetModelDir = OcrSettingsActivity.modelDir + "/" + detModelName; + String srcClsModelDir = OcrSettingsActivity.modelDir + "/" + clsModelName; + String srcRecModelDir = OcrSettingsActivity.modelDir + "/" + recModelName; + Utils.copyDirectoryFromAssets(this, srcDetModelDir, realDetModelDir); + Utils.copyDirectoryFromAssets(this, srcClsModelDir, realClsModelDir); + Utils.copyDirectoryFromAssets(this, srcRecModelDir, realRecModelDir); + String realLabelPath = getCacheDir() + "/" + OcrSettingsActivity.labelPath; + Utils.copyFileFromAssets(this, OcrSettingsActivity.labelPath, realLabelPath); + + String detModelFile = realDetModelDir + "/" + "inference.pdmodel"; + String detParamsFile = realDetModelDir + "/" + "inference.pdiparams"; + String clsModelFile = realClsModelDir + "/" + "inference.pdmodel"; + String clsParamsFile = realClsModelDir + "/" + "inference.pdiparams"; + String recModelFile = realRecModelDir + "/" + "inference.pdmodel"; + String recParamsFile = realRecModelDir + "/" + "inference.pdiparams"; + String recLabelFilePath = realLabelPath; // ppocr_keys_v1.txt + RuntimeOption detOption = new RuntimeOption(); + RuntimeOption clsOption = new RuntimeOption(); + RuntimeOption recOption = new RuntimeOption(); + detOption.setCpuThreadNum(OcrSettingsActivity.cpuThreadNum); + clsOption.setCpuThreadNum(OcrSettingsActivity.cpuThreadNum); + recOption.setCpuThreadNum(OcrSettingsActivity.cpuThreadNum); + detOption.setLitePowerMode(OcrSettingsActivity.cpuPowerMode); + clsOption.setLitePowerMode(OcrSettingsActivity.cpuPowerMode); + recOption.setLitePowerMode(OcrSettingsActivity.cpuPowerMode); + if (Boolean.parseBoolean(OcrSettingsActivity.enableLiteFp16)) { + detOption.enableLiteFp16(); + clsOption.enableLiteFp16(); + recOption.enableLiteFp16(); + } + DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); + Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); + Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); + predictor.init(detModel, clsModel, recModel); + + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) { + new AlertDialog.Builder(OcrMainActivity.this) + .setTitle("Permission denied") + .setMessage("Click to force quit the app, then open Settings->Apps & notifications->Target " + + "App->Permissions to grant all of the permissions.") + .setCancelable(false) + .setPositiveButton("Exit", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + OcrMainActivity.this.finish(); + } + }).show(); + } + } + + private void requestAllPermissions() { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.CAMERA}, 0); + } + + private boolean checkAllPermissions() { + return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED + && ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; + } +} diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java new file mode 100644 index 000000000..6f8c45ff4 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java @@ -0,0 +1,198 @@ +package com.baidu.paddle.fastdeploy.app.examples.ocr; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.PreferenceManager; +import android.support.v7.app.ActionBar; + +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; + +import java.util.ArrayList; +import java.util.List; + +public class OcrSettingsActivity extends AppCompatPreferenceActivity implements + SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = OcrSettingsActivity.class.getSimpleName(); + + static public int selectedModelIdx = -1; + static public String modelDir = ""; + static public String labelPath = ""; + static public int cpuThreadNum = 2; + static public String cpuPowerMode = ""; + static public float scoreThreshold = 0.4f; + static public String enableLiteFp16 = "true"; + + ListPreference lpChoosePreInstalledModel = null; + EditTextPreference etModelDir = null; + EditTextPreference etLabelPath = null; + ListPreference lpCPUThreadNum = null; + ListPreference lpCPUPowerMode = null; + EditTextPreference etScoreThreshold = null; + ListPreference lpEnableLiteFp16 = null; + + List preInstalledModelDirs = null; + List preInstalledLabelPaths = null; + List preInstalledCPUThreadNums = null; + List preInstalledCPUPowerModes = null; + List preInstalledScoreThresholds = null; + List preInstalledEnableLiteFp16s = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.ocr_settings); + ActionBar supportActionBar = getSupportActionBar(); + if (supportActionBar != null) { + supportActionBar.setDisplayHomeAsUpEnabled(true); + } + + // Initialize pre-installed models + preInstalledModelDirs = new ArrayList(); + preInstalledLabelPaths = new ArrayList(); + preInstalledCPUThreadNums = new ArrayList(); + preInstalledCPUPowerModes = new ArrayList(); + preInstalledScoreThresholds = new ArrayList(); + preInstalledEnableLiteFp16s = new ArrayList(); + preInstalledModelDirs.add(getString(R.string.OCR_MODEL_DIR_DEFAULT)); + preInstalledLabelPaths.add(getString(R.string.OCR_REC_LABEL_DEFAULT)); + preInstalledCPUThreadNums.add(getString(R.string.CPU_THREAD_NUM_DEFAULT)); + preInstalledCPUPowerModes.add(getString(R.string.CPU_POWER_MODE_DEFAULT)); + preInstalledScoreThresholds.add(getString(R.string.SCORE_THRESHOLD_DEFAULT)); + preInstalledEnableLiteFp16s.add(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + + // Setup UI components + lpChoosePreInstalledModel = + (ListPreference) findPreference(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY)); + String[] preInstalledModelNames = new String[preInstalledModelDirs.size()]; + for (int i = 0; i < preInstalledModelDirs.size(); i++) { + preInstalledModelNames[i] = preInstalledModelDirs.get(i).substring(preInstalledModelDirs.get(i).lastIndexOf("/") + 1); + } + lpChoosePreInstalledModel.setEntries(preInstalledModelNames); + lpChoosePreInstalledModel.setEntryValues(preInstalledModelDirs.toArray(new String[preInstalledModelDirs.size()])); + lpCPUThreadNum = (ListPreference) findPreference(getString(R.string.CPU_THREAD_NUM_KEY)); + lpCPUPowerMode = (ListPreference) findPreference(getString(R.string.CPU_POWER_MODE_KEY)); + etModelDir = (EditTextPreference) findPreference(getString(R.string.MODEL_DIR_KEY)); + etModelDir.setTitle("Model dir (SDCard: " + Utils.getSDCardDirectory() + ")"); + etLabelPath = (EditTextPreference) findPreference(getString(R.string.LABEL_PATH_KEY)); + etLabelPath.setTitle("Label path (SDCard: " + Utils.getSDCardDirectory() + ")"); + etScoreThreshold = (EditTextPreference) findPreference(getString(R.string.SCORE_THRESHOLD_KEY)); + lpEnableLiteFp16 = (ListPreference) findPreference(getString(R.string.ENABLE_LITE_FP16_MODE_KEY)); + } + + @SuppressLint("ApplySharedPref") + private void reloadSettingsAndUpdateUI() { + SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences(); + + String selected_model_dir = sharedPreferences.getString(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY), + getString(R.string.OCR_MODEL_DIR_DEFAULT)); + int selected_model_idx = lpChoosePreInstalledModel.findIndexOfValue(selected_model_dir); + if (selected_model_idx >= 0 && selected_model_idx < preInstalledModelDirs.size() && selected_model_idx != selectedModelIdx) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(getString(R.string.MODEL_DIR_KEY), preInstalledModelDirs.get(selected_model_idx)); + editor.putString(getString(R.string.LABEL_PATH_KEY), preInstalledLabelPaths.get(selected_model_idx)); + editor.putString(getString(R.string.CPU_THREAD_NUM_KEY), preInstalledCPUThreadNums.get(selected_model_idx)); + editor.putString(getString(R.string.CPU_POWER_MODE_KEY), preInstalledCPUPowerModes.get(selected_model_idx)); + editor.putString(getString(R.string.SCORE_THRESHOLD_KEY), preInstalledScoreThresholds.get(selected_model_idx)); + editor.putString(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT), preInstalledEnableLiteFp16s.get(selected_model_idx)); + editor.commit(); + lpChoosePreInstalledModel.setSummary(selected_model_dir); + selectedModelIdx = selected_model_idx; + } + + String model_dir = sharedPreferences.getString(getString(R.string.MODEL_DIR_KEY), + getString(R.string.OCR_MODEL_DIR_DEFAULT)); + String label_path = sharedPreferences.getString(getString(R.string.LABEL_PATH_KEY), + getString(R.string.OCR_REC_LABEL_DEFAULT)); + String cpu_thread_num = sharedPreferences.getString(getString(R.string.CPU_THREAD_NUM_KEY), + getString(R.string.CPU_THREAD_NUM_DEFAULT)); + String cpu_power_mode = sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY), + getString(R.string.CPU_POWER_MODE_DEFAULT)); + String score_threshold = sharedPreferences.getString(getString(R.string.SCORE_THRESHOLD_KEY), + getString(R.string.SCORE_THRESHOLD_DEFAULT)); + String enable_lite_fp16 = sharedPreferences.getString(getString(R.string.ENABLE_LITE_FP16_MODE_KEY), + getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + + etModelDir.setSummary(model_dir); + etLabelPath.setSummary(label_path); + lpCPUThreadNum.setValue(cpu_thread_num); + lpCPUThreadNum.setSummary(cpu_thread_num); + lpCPUPowerMode.setValue(cpu_power_mode); + lpCPUPowerMode.setSummary(cpu_power_mode); + etScoreThreshold.setSummary(score_threshold); + etScoreThreshold.setText(score_threshold); + lpEnableLiteFp16.setValue(enable_lite_fp16); + lpEnableLiteFp16.setSummary(enable_lite_fp16); + + } + + static boolean checkAndUpdateSettings(Context ctx) { + boolean settingsChanged = false; + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx); + + String model_dir = sharedPreferences.getString(ctx.getString(R.string.MODEL_DIR_KEY), + ctx.getString(R.string.OCR_MODEL_DIR_DEFAULT)); + settingsChanged |= !modelDir.equalsIgnoreCase(model_dir); + modelDir = model_dir; + + String label_path = sharedPreferences.getString(ctx.getString(R.string.LABEL_PATH_KEY), + ctx.getString(R.string.OCR_REC_LABEL_DEFAULT)); + settingsChanged |= !labelPath.equalsIgnoreCase(label_path); + labelPath = label_path; + + String cpu_thread_num = sharedPreferences.getString(ctx.getString(R.string.CPU_THREAD_NUM_KEY), + ctx.getString(R.string.CPU_THREAD_NUM_DEFAULT)); + settingsChanged |= cpuThreadNum != Integer.parseInt(cpu_thread_num); + cpuThreadNum = Integer.parseInt(cpu_thread_num); + + String cpu_power_mode = sharedPreferences.getString(ctx.getString(R.string.CPU_POWER_MODE_KEY), + ctx.getString(R.string.CPU_POWER_MODE_DEFAULT)); + settingsChanged |= !cpuPowerMode.equalsIgnoreCase(cpu_power_mode); + cpuPowerMode = cpu_power_mode; + + String score_threshold = sharedPreferences.getString(ctx.getString(R.string.SCORE_THRESHOLD_KEY), + ctx.getString(R.string.SCORE_THRESHOLD_DEFAULT)); + settingsChanged |= scoreThreshold != Float.parseFloat(score_threshold); + scoreThreshold = Float.parseFloat(score_threshold); + + String enable_lite_fp16 = sharedPreferences.getString(ctx.getString(R.string.ENABLE_LITE_FP16_MODE_KEY), + ctx.getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + settingsChanged |= !enableLiteFp16.equalsIgnoreCase(enable_lite_fp16); + enableLiteFp16 = enable_lite_fp16; + + return settingsChanged; + } + + static void resetSettings() { + selectedModelIdx = -1; + modelDir = ""; + labelPath = ""; + cpuThreadNum = 2; + cpuPowerMode = ""; + scoreThreshold = 0.4f; + enableLiteFp16 = "true"; + } + + @Override + protected void onResume() { + super.onResume(); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + reloadSettingsAndUpdateUI(); + } + + @Override + protected void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + reloadSettingsAndUpdateUI(); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java similarity index 99% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java index 14217181d..e90874c62 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java @@ -12,6 +12,7 @@ import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLUtils; import android.opengl.Matrix; +import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; @@ -305,7 +306,6 @@ public class CameraSurfaceView extends GLSurfaceView implements Renderer, boolean rotate = degree == 90 || degree == 270; textureWidth = rotate ? previewSize.height : previewSize.width; textureHeight = rotate ? previewSize.width : previewSize.height; - // Destroy FBO and draw textures GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GLES20.glDeleteFramebuffers(1, fbo, 0); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/BaseResultAdapter.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/BaseResultAdapter.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/BaseResultAdapter.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/BaseResultAdapter.java diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java b/examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java similarity index 100% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/action_button_layer.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/action_button_layer.xml new file mode 100644 index 000000000..a0d2e76bf --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/action_button_layer.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/album_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/album_btn.xml new file mode 100644 index 000000000..26d01c584 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/album_btn.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 000000000..1f6bb2906 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_start_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_start_btn.xml new file mode 100644 index 000000000..664134453 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_start_btn.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_stop_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_stop_btn.xml new file mode 100644 index 000000000..8869a1b2b --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/realtime_stop_btn.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/result_page_border_section_bk.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/result_page_border_section_bk.xml new file mode 100644 index 000000000..bd068f169 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/result_page_border_section_bk.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/round_corner_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/round_corner_btn.xml new file mode 100644 index 000000000..c5dcc45d5 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/round_corner_btn.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_realtime.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_realtime.xml new file mode 100644 index 000000000..b349d15a6 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_realtime.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_result.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_result.xml new file mode 100644 index 000000000..17cb68ed8 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_progress_result.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb.xml new file mode 100644 index 000000000..96bd95e0a --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb_shape.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb_shape.xml new file mode 100644 index 000000000..26d033b6d --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/seekbar_thumb_shape.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/switch_side_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/switch_side_btn.xml new file mode 100644 index 000000000..b9b2edfb6 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/switch_side_btn.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/take_picture_btn.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/take_picture_btn.xml new file mode 100644 index 000000000..4966675c3 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-v24/take_picture_btn.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album.png new file mode 100644 index 000000000..3a6fdedae Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album_pressed.png new file mode 100644 index 000000000..aa873424e Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/album_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/back_btn.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/back_btn.png new file mode 100644 index 000000000..ff121e85f Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/back_btn.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/more_menu.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/more_menu.png new file mode 100644 index 000000000..edf9f3ccc Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/more_menu.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start.png new file mode 100644 index 000000000..94ab08172 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start_pressed.png new file mode 100644 index 000000000..feef0fea6 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_start_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop.png new file mode 100644 index 000000000..8c926367d Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop_pressed.png new file mode 100644 index 000000000..309082788 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/realtime_stop_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/scan_icon.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/scan_icon.png new file mode 100644 index 000000000..7517d99d0 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/scan_icon.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_handle.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_handle.png new file mode 100644 index 000000000..55f5f7399 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_handle.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_progress_dotted.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_progress_dotted.png new file mode 100644 index 000000000..e6241d12e Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_progress_dotted.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_thumb_invisible.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_thumb_invisible.png new file mode 100644 index 000000000..acfe8d374 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/seekbar_thumb_invisible.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side.png new file mode 100644 index 000000000..3e6ae9a94 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side_pressed.png new file mode 100644 index 000000000..25e152276 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/switch_side_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture.png new file mode 100644 index 000000000..d6ced986e Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture_pressed.png new file mode 100644 index 000000000..5f9c8ee3b Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xhdpi/take_picture_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_default.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_default.png new file mode 100644 index 000000000..b9e66c7f6 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_default.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_pressed.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_pressed.png new file mode 100644 index 000000000..9544133bd Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable-xxhdpi-v4/btn_switch_pressed.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings.xml new file mode 100644 index 000000000..917897b99 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_default.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_default.xml new file mode 100644 index 000000000..e19589a97 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_default.xml @@ -0,0 +1,13 @@ + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_pressed.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_pressed.xml new file mode 100644 index 000000000..c4af2a042 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_settings_pressed.xml @@ -0,0 +1,13 @@ + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter.xml new file mode 100644 index 000000000..4f9826d3a --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_default.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_default.xml new file mode 100644 index 000000000..234ca014a --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_default.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_pressed.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_pressed.xml new file mode 100644 index 000000000..accc7aced --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_shutter_pressed.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_switch.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_switch.xml new file mode 100644 index 000000000..691e8c2e9 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/btn_switch.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/ic_launcher_background.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..0d025f9bf --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout-land/ocr_activity_main.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout-land/ocr_activity_main.xml new file mode 100644 index 000000000..b30f35edf --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout-land/ocr_activity_main.xml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_activity_main.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_activity_main.xml new file mode 100644 index 000000000..b30f35edf --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_activity_main.xml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_camera_page.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_camera_page.xml new file mode 100644 index 000000000..6f31c2c7e --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_camera_page.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_result_page.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_result_page.xml new file mode 100644 index 000000000..958a85940 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_result_page.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/android/app/src/main/res/layout/ocr_result_page_item.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_result_page_item.xml similarity index 100% rename from java/android/app/src/main/res/layout/ocr_result_page_item.xml rename to examples/vision/ocr/PP-OCRv3/android/app/src/main/res/layout/ocr_result_page_item.xml diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..eca70cfe5 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..eca70cfe5 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..898f3ed59 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..dffca3601 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..64ba76f75 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..dae5e0823 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..e5ed46597 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..14ed0af35 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..b0907cac3 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..d8ae03154 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..2c18de9e6 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..beed3cdd2 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/arrays.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/arrays.xml new file mode 100644 index 000000000..c7cf12378 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/arrays.xml @@ -0,0 +1,39 @@ + + + + 1 threads + 2 threads + 4 threads + 8 threads + + + 1 + 2 + 4 + 8 + + + HIGH(only big cores) + LOW(only LITTLE cores) + FULL(all cores) + NO_BIND(depends on system) + RAND_HIGH + RAND_LOW + + + LITE_POWER_HIGH + LITE_POWER_LOW + LITE_POWER_FULL + LITE_POWER_NO_BIND + LITE_POWER_RAND_HIGH + LITE_POWER_RAND_LOW + + + true + false + + + true + false + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/colors.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..f8ec1f0c3 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/colors.xml @@ -0,0 +1,22 @@ + + + #008577 + #00574B + #D81B60 + #FF000000 + #00000000 + #00000000 + #FFFFFFFF + + #000000 + #3B85F5 + #F5A623 + #FFFFFF + + #EEEEEE + + #3B85F5 + #333333 + #E5E5E5 + #3b85f5 + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/dimens.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..2df89499d --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/dimens.xml @@ -0,0 +1,17 @@ + + + 26dp + 36dp + 34dp + 60dp + 16dp + 67dp + 67dp + 56dp + 56dp + 46dp + 46dp + 32dp + 24dp + 16dp + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/strings.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..b5c396f5f --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/strings.xml @@ -0,0 +1,51 @@ + + + EasyEdge + + EasyEdge + EasyEdge + EasyEdge + EasyEdge + EasyEdge + + CHOOSE_INSTALLED_MODEL_KEY + MODEL_DIR_KEY + LABEL_PATH_KEY + CPU_THREAD_NUM_KEY + CPU_POWER_MODE_KEY + SCORE_THRESHOLD_KEY + ENABLE_LITE_FP16_MODE_KEY + + 2 + LITE_POWER_HIGH + 0.4 + 0.1 + 0.25 + true + + + models/picodet_s_320_coco_lcnet + labels/coco_label_list.txt + + models + labels/ppocr_keys_v1.txt + + models/MobileNetV1_x0_25_infer + labels/imagenet1k_label_list.txt + + models/scrfd_500m_bnkps_shape320x320_pd + + models/human_pp_humansegv1_lite_192x192_inference_model + + 拍照识别 + 实时识别 + < + 模型名称 + 识别结果 + 序号 + 名称 + 置信度 + 阈值控制 + 重新识别 + 保存结果 + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/styles.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..67c147594 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/styles.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/values.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/values.xml new file mode 100644 index 000000000..156146d9a --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/values/values.xml @@ -0,0 +1,17 @@ + + + 120dp + 46px + + 126px + 136px + + 46px + + 36px + + 15dp + + 15dp + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/xml/ocr_settings.xml b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/xml/ocr_settings.xml new file mode 100644 index 000000000..692b74b4c --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/app/src/main/res/xml/ocr_settings.xml @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/android/build.gradle b/examples/vision/ocr/PP-OCRv3/android/build.gradle new file mode 100644 index 000000000..d8d678b3f --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/build.gradle @@ -0,0 +1,37 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +//plugins { +// id 'com.android.application' version '7.2.2' apply false +// id 'com.android.library' version '7.2.2' apply false +//} +// +//task clean(type: Delete) { +// delete rootProject.buildDir +//} + +buildscript { + repositories { + google() + jcenter() + // mavenCentral() + + } + dependencies { + classpath 'com.android.tools.build:gradle:7.2.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + // mavenCentral() + + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/examples/vision/ocr/PP-OCRv3/android/gradle.properties b/examples/vision/ocr/PP-OCRv3/android/gradle.properties new file mode 100644 index 000000000..ae995d47c --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx3096m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.jar b/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.properties b/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..7855fafe4 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Oct 08 17:24:34 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/examples/vision/ocr/PP-OCRv3/android/gradlew b/examples/vision/ocr/PP-OCRv3/android/gradlew new file mode 100644 index 000000000..e69de29bb diff --git a/examples/vision/ocr/PP-OCRv3/android/gradlew.bat b/examples/vision/ocr/PP-OCRv3/android/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/vision/ocr/PP-OCRv3/android/local.properties b/examples/vision/ocr/PP-OCRv3/android/local.properties new file mode 100644 index 000000000..aaa0de9aa --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Tue Nov 29 18:47:20 CST 2022 +sdk.dir=D\:\\androidsdk diff --git a/examples/vision/ocr/PP-OCRv3/android/settings.gradle b/examples/vision/ocr/PP-OCRv3/android/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/android/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/examples/vision/ocr/PP-OCRv3/cpp/README.md b/examples/vision/ocr/PP-OCRv3/cpp/README.md index 369265809..bfbc0fc4a 100644 --- a/examples/vision/ocr/PP-OCRv3/cpp/README.md +++ b/examples/vision/ocr/PP-OCRv3/cpp/README.md @@ -48,103 +48,9 @@ wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/ppocr/utils/ppocr_ - -## PPOCRv3 C++接口 - -### PPOCRv3类 - -``` -fastdeploy::pipeline::PPOCRv3(fastdeploy::vision::ocr::DBDetector* det_model, - fastdeploy::vision::ocr::Classifier* cls_model, - fastdeploy::vision::ocr::Recognizer* rec_model); -``` - -PPOCRv3 的初始化,由检测,分类和识别模型串联构成 - -**参数** - -> * **DBDetector**(model): OCR中的检测模型 -> * **Classifier**(model): OCR中的分类模型 -> * **Recognizer**(model): OCR中的识别模型 - -``` -fastdeploy::pipeline::PPOCRv3(fastdeploy::vision::ocr::DBDetector* det_model, - fastdeploy::vision::ocr::Recognizer* rec_model); -``` -PPOCRv3 的初始化,由检测,识别模型串联构成(无分类器) - -**参数** - -> * **DBDetector**(model): OCR中的检测模型 -> * **Recognizer**(model): OCR中的识别模型 - -#### Predict函数 - -> ``` -> bool Predict(cv::Mat* img, fastdeploy::vision::OCRResult* result); -> ``` -> -> 模型预测接口,输入一张图片,返回OCR预测结果 -> -> **参数** -> -> > * **img**: 输入图像,注意需为HWC,BGR格式 -> > * **result**: OCR预测结果,包括由检测模型输出的检测框位置,分类模型输出的方向分类,以及识别模型输出的识别结果, OCRResult说明参考[视觉模型预测结果](../../../../../docs/api/vision_results/) - - -## DBDetector C++接口 - -### DBDetector类 - -``` -fastdeploy::vision::ocr::DBDetector(const std::string& model_file, const std::string& params_file = "", - const RuntimeOption& custom_option = RuntimeOption(), - const ModelFormat& model_format = ModelFormat::PADDLE); -``` - -DBDetector模型加载和初始化,其中模型为paddle模型格式。 - -**参数** - -> * **model_file**(str): 模型文件路径 -> * **params_file**(str): 参数文件路径,当模型格式为ONNX时,此参数传入空字符串即可 -> * **runtime_option**(RuntimeOption): 后端推理配置,默认为None,即采用默认配置 -> * **model_format**(ModelFormat): 模型格式,默认为Paddle格式 - -### Classifier类与DBDetector类相同 - -### Recognizer类 -``` - Recognizer(const std::string& model_file, - const std::string& params_file = "", - const std::string& label_path = "", - const RuntimeOption& custom_option = RuntimeOption(), - const ModelFormat& model_format = ModelFormat::PADDLE); -``` -Recognizer类初始化时,需要在label_path参数中,输入识别模型所需的label文件,其他参数均与DBDetector类相同 - -**参数** -> * **label_path**(str): 识别模型的label文件路径 - - -### 类成员变量 -#### DBDetector预处理参数 -用户可按照自己的实际需求,修改下列预处理参数,从而影响最终的推理和部署效果 - -> > * **max_side_len**(int): 检测算法前向时图片长边的最大尺寸,当长边超出这个值时会将长边resize到这个大小,短边等比例缩放,默认为960 -> > * **det_db_thresh**(double): DB模型输出预测图的二值化阈值,默认为0.3 -> > * **det_db_box_thresh**(double): DB模型输出框的阈值,低于此值的预测框会被丢弃,默认为0.6 -> > * **det_db_unclip_ratio**(double): DB模型输出框扩大的比例,默认为1.5 -> > * **det_db_score_mode**(string):DB后处理中计算文本框平均得分的方式,默认为slow,即求polygon区域的平均分数的方式 -> > * **use_dilation**(bool):是否对检测输出的feature map做膨胀处理,默认为Fasle - -#### Classifier预处理参数 -用户可按照自己的实际需求,修改下列预处理参数,从而影响最终的推理和部署效果 - -> > * **cls_thresh**(double): 当分类模型输出的得分超过此阈值,输入的图片将被翻转,默认为0.9 - ## 其它文档 +- [C++ API查阅](https://baidu-paddle.github.io/fastdeploy-api/cpp/html/) - [PPOCR 系列模型介绍](../../) - [PPOCRv3 Python部署](../python) - [模型预测结果说明](../../../../../docs/cn/faq/how_to_change_backend.md) diff --git a/examples/vision/ocr/PP-OCRv3/cpp/infer.cc b/examples/vision/ocr/PP-OCRv3/cpp/infer.cc index 911b311e3..90b77679f 100644 --- a/examples/vision/ocr/PP-OCRv3/cpp/infer.cc +++ b/examples/vision/ocr/PP-OCRv3/cpp/infer.cc @@ -33,13 +33,19 @@ void InitAndInfer(const std::string& det_model_dir, const std::string& cls_model auto cls_option = option; auto rec_option = option; + // The cls and rec model can inference a batch of images now. + // User could initialize the inference batch size and set them after create PPOCR model. + int cls_batch_size = 1; + int rec_batch_size = 6; + // If use TRT backend, the dynamic shape will be set as follow. // We recommend that users set the length and height of the detection model to a multiple of 32. + // We also recommend that users set the Trt input shape as follow. det_option.SetTrtInputShape("x", {1, 3, 64,64}, {1, 3, 640, 640}, {1, 3, 960, 960}); - cls_option.SetTrtInputShape("x", {1, 3, 48, 10}, {10, 3, 48, 320}, {64, 3, 48, 1024}); - rec_option.SetTrtInputShape("x", {1, 3, 48, 10}, {10, 3, 48, 320}, - {64, 3, 48, 2304}); + cls_option.SetTrtInputShape("x", {1, 3, 48, 10}, {cls_batch_size, 3, 48, 320}, {cls_batch_size, 3, 48, 1024}); + rec_option.SetTrtInputShape("x", {1, 3, 48, 10}, {rec_batch_size, 3, 48, 320}, + {rec_batch_size, 3, 48, 2304}); // Users could save TRT cache file to disk as follow. // det_option.SetTrtCacheFile(det_model_dir + sep + "det_trt_cache.trt"); @@ -57,6 +63,12 @@ void InitAndInfer(const std::string& det_model_dir, const std::string& cls_model // The classification model is optional, so the PP-OCR can also be connected in series as follows // auto ppocr_v3 = fastdeploy::pipeline::PPOCRv3(&det_model, &rec_model); auto ppocr_v3 = fastdeploy::pipeline::PPOCRv3(&det_model, &cls_model, &rec_model); + + // Set inference batch size for cls model and rec model, the value could be -1 and 1 to positive infinity. + // When inference batch size is set to -1, it means that the inference batch size + // of the cls and rec models will be the same as the number of boxes detected by the det model. + ppocr_v3.SetClsBatchSize(cls_batch_size); + ppocr_v3.SetRecBatchSize(rec_batch_size); if(!ppocr_v3.Initialized()){ std::cerr << "Failed to initialize PP-OCR." << std::endl; diff --git a/examples/vision/ocr/PP-OCRv3/python/README.md b/examples/vision/ocr/PP-OCRv3/python/README.md index a51abba98..280ae7016 100644 --- a/examples/vision/ocr/PP-OCRv3/python/README.md +++ b/examples/vision/ocr/PP-OCRv3/python/README.md @@ -38,89 +38,12 @@ python infer.py --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2 运行完成可视化结果如下图所示 -## PPOCRv3 Python接口 - -``` -fd.vision.ocr.PPOCRv3(det_model=det_model, cls_model=cls_model, rec_model=rec_model) -``` -PPOCRv3的初始化,输入的参数是检测模型,分类模型和识别模型,其中cls_model可选,如无需求,可设置为None - -**参数** - -> * **det_model**(model): OCR中的检测模型 -> * **cls_model**(model): OCR中的分类模型 -> * **rec_model**(model): OCR中的识别模型 - -### predict函数 - -> ``` -> result = ppocr_v3.predict(im) -> ``` -> -> 模型预测接口,输入是一张图片 -> -> **参数** -> -> > * **im**(np.ndarray): 输入数据,每张图片注意需为HWC,BGR格式 - -> **返回** -> -> > 返回`fastdeploy.vision.OCRResult`结构体,结构体说明参考文档[视觉模型预测结果](../../../../../docs/api/vision_results/) - - - -## DBDetector Python接口 - -### DBDetector类 - -``` -fastdeploy.vision.ocr.DBDetector(model_file, params_file, runtime_option=None, model_format=ModelFormat.PADDLE) -``` - -DBDetector模型加载和初始化,其中模型为paddle模型格式。 - -**参数** - -> * **model_file**(str): 模型文件路径 -> * **params_file**(str): 参数文件路径,当模型格式为ONNX时,此参数传入空字符串即可 -> * **runtime_option**(RuntimeOption): 后端推理配置,默认为None,即采用默认配置 -> * **model_format**(ModelFormat): 模型格式,默认为PADDLE格式 - -### Classifier类与DBDetector类相同 - -### Recognizer类 -``` -fastdeploy.vision.ocr.Recognizer(rec_model_file,rec_params_file,rec_label_file, - runtime_option=rec_runtime_option,model_format=ModelFormat.PADDLE) -``` -Recognizer类初始化时,需要在rec_label_file参数中,输入识别模型所需的label文件路径,其他参数均与DBDetector类相同 - -**参数** -> * **label_path**(str): 识别模型的label文件路径 - - - -### 类成员变量 - -#### DBDetector预处理参数 -用户可按照自己的实际需求,修改下列预处理参数,从而影响最终的推理和部署效果 - -> > * **max_side_len**(int): 检测算法前向时图片长边的最大尺寸,当长边超出这个值时会将长边resize到这个大小,短边等比例缩放,默认为960 -> > * **det_db_thresh**(double): DB模型输出预测图的二值化阈值,默认为0.3 -> > * **det_db_box_thresh**(double): DB模型输出框的阈值,低于此值的预测框会被丢弃,默认为0.6 -> > * **det_db_unclip_ratio**(double): DB模型输出框扩大的比例,默认为1.5 -> > * **det_db_score_mode**(string):DB后处理中计算文本框平均得分的方式,默认为slow,即求polygon区域的平均分数的方式 -> > * **use_dilation**(bool):是否对检测输出的feature map做膨胀处理,默认为Fasle - -#### Classifier预处理参数 -用户可按照自己的实际需求,修改下列预处理参数,从而影响最终的推理和部署效果 - -> > * **cls_thresh**(double): 当分类模型输出的得分超过此阈值,输入的图片将被翻转,默认为0.9 ## 其它文档 +- [Python API文档查阅](https://baidu-paddle.github.io/fastdeploy-api/python/html/) - [PPOCR 系列模型介绍](../../) - [PPOCRv3 C++部署](../cpp) - [模型预测结果说明](../../../../../docs/api/vision_results/) diff --git a/examples/vision/ocr/PP-OCRv3/python/infer.py b/examples/vision/ocr/PP-OCRv3/python/infer.py index b6b27b240..1ec962cb5 100644 --- a/examples/vision/ocr/PP-OCRv3/python/infer.py +++ b/examples/vision/ocr/PP-OCRv3/python/infer.py @@ -106,6 +106,11 @@ rec_label_file = args.rec_label_file # 用户也可根据自行需求分别配置 runtime_option = build_option(args) +# PPOCR的cls和rec模型现在已经支持推理一个Batch的数据 +# 定义下面两个变量后, 可用于设置trt输入shape, 并在PPOCR模型初始化后, 完成Batch推理设置 +cls_batch_size = 1 +rec_batch_size = 6 + # 当使用TRT时,分别给三个模型的runtime设置动态shape,并完成模型的创建. # 注意: 需要在检测模型创建完成后,再设置分类模型的动态输入并创建分类模型, 识别模型同理. # 如果用户想要自己改动检测模型的输入shape, 我们建议用户把检测模型的长和高设置为32的倍数. @@ -118,16 +123,18 @@ det_model = fd.vision.ocr.DBDetector( det_model_file, det_params_file, runtime_option=det_option) cls_option = runtime_option -cls_option.set_trt_input_shape("x", [1, 3, 48, 10], [10, 3, 48, 320], - [64, 3, 48, 1024]) +cls_option.set_trt_input_shape("x", [1, 3, 48, 10], + [cls_batch_size, 3, 48, 320], + [cls_batch_size, 3, 48, 1024]) # 用户可以把TRT引擎文件保存至本地 # cls_option.set_trt_cache_file(args.cls_model + "/cls_trt_cache.trt") cls_model = fd.vision.ocr.Classifier( cls_model_file, cls_params_file, runtime_option=cls_option) rec_option = runtime_option -rec_option.set_trt_input_shape("x", [1, 3, 48, 10], [10, 3, 48, 320], - [64, 3, 48, 2304]) +rec_option.set_trt_input_shape("x", [1, 3, 48, 10], + [rec_batch_size, 3, 48, 320], + [rec_batch_size, 3, 48, 2304]) # 用户可以把TRT引擎文件保存至本地 # rec_option.set_trt_cache_file(args.rec_model + "/rec_trt_cache.trt") rec_model = fd.vision.ocr.Recognizer( @@ -137,6 +144,12 @@ rec_model = fd.vision.ocr.Recognizer( ppocr_v3 = fd.vision.ocr.PPOCRv3( det_model=det_model, cls_model=cls_model, rec_model=rec_model) +# 给cls和rec模型设置推理时的batch size +# 此值能为-1, 和1到正无穷 +# 当此值为-1时, cls和rec模型的batch size将默认和det模型检测出的框的数量相同 +ppocr_v3.cls_batch_size = cls_batch_size +ppocr_v3.rec_batch_size = rec_batch_size + # 预测图片准备 im = cv2.imread(args.image) diff --git a/examples/vision/ocr/PP-OCRv3/serving/README.md b/examples/vision/ocr/PP-OCRv3/serving/README.md old mode 100644 new mode 100755 index ec53fb8d6..31db5a72c --- a/examples/vision/ocr/PP-OCRv3/serving/README.md +++ b/examples/vision/ocr/PP-OCRv3/serving/README.md @@ -1,5 +1,9 @@ # PP-OCR服务化部署示例 +在服务化部署前,需确认 + +- 1. 服务化镜像的软硬件环境要求和镜像拉取命令请参考[FastDeploy服务化部署](../../../../../serving/README_CN.md) + ## 介绍 本文介绍了使用FastDeploy搭建OCR文字识别服务的方法. @@ -43,14 +47,16 @@ tar xvf ch_PP-OCRv3_rec_infer.tar && mv ch_PP-OCRv3_rec_infer 1 mv 1/inference.pdiparams 1/model.pdiparams && mv 1/inference.pdmodel 1/model.pdmodel mv 1 models/rec_runtime/ && rm -rf ch_PP-OCRv3_rec_infer.tar +mkdir models/pp_ocr/1 && mkdir models/rec_pp/1 && mkdir models/cls_pp/1 + wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/ppocr/utils/ppocr_keys_v1.txt mv ppocr_keys_v1.txt models/rec_postprocess/1/ wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/doc/imgs/12.jpg - -docker pull paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 -docker run -dit --net=host --name fastdeploy --shm-size="1g" -v $PWD:/ocr_serving paddlepaddle/fastdeploy:0.6.0-gpu-cuda11.4-trt8.4-21.10 bash +# x.y.z为镜像版本号,需参照serving文档替换为数字 +docker pull paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 +docker run -dit --net=host --name fastdeploy --shm-size="1g" -v $PWD:/ocr_serving paddlepaddle/fastdeploy:x.y.z-gpu-cuda11.4-trt8.4-21.10 bash docker exec -it -u root fastdeploy bash ``` diff --git a/examples/vision/ocr/PP-OCRv3/serving/client.py b/examples/vision/ocr/PP-OCRv3/serving/client.py old mode 100644 new mode 100755 index b7b20644f..1b150b7d0 --- a/examples/vision/ocr/PP-OCRv3/serving/client.py +++ b/examples/vision/ocr/PP-OCRv3/serving/client.py @@ -91,7 +91,7 @@ class SyncGRPCTritonRunner: if __name__ == "__main__": model_name = "pp_ocr" model_version = "1" - url = "localhost:9001" + url = "localhost:8001" runner = SyncGRPCTritonRunner(url, model_name, model_version) im = cv2.imread("12.jpg") im = np.array([im, ]) diff --git a/examples/vision/ocr/PP-OCRv3/serving/models/cls_runtime/config.pbtxt b/examples/vision/ocr/PP-OCRv3/serving/models/cls_runtime/config.pbtxt old mode 100644 new mode 100755 index aa66b1f9b..eb7b25503 --- a/examples/vision/ocr/PP-OCRv3/serving/models/cls_runtime/config.pbtxt +++ b/examples/vision/ocr/PP-OCRv3/serving/models/cls_runtime/config.pbtxt @@ -35,3 +35,18 @@ instance_group [ gpus: [0] } ] + +optimization { + execution_accelerators { + # GPU推理配置, 配合KIND_GPU使用 + gpu_execution_accelerator : [ + { + name : "paddle" + # 设置推理并行计算线程数为4 + parameters { key: "cpu_threads" value: "4" } + # 开启mkldnn加速,设置为0关闭mkldnn + parameters { key: "use_mkldnn" value: "1" } + } + ] + } +} diff --git a/examples/vision/ocr/PP-OCRv3/serving/models/det_runtime/config.pbtxt b/examples/vision/ocr/PP-OCRv3/serving/models/det_runtime/config.pbtxt old mode 100644 new mode 100755 index c3ffe15c1..96d85e3e1 --- a/examples/vision/ocr/PP-OCRv3/serving/models/det_runtime/config.pbtxt +++ b/examples/vision/ocr/PP-OCRv3/serving/models/det_runtime/config.pbtxt @@ -35,3 +35,18 @@ instance_group [ gpus: [0] } ] + +optimization { + execution_accelerators { + # GPU推理配置, 配合KIND_GPU使用 + gpu_execution_accelerator : [ + { + name : "paddle" + # 设置推理并行计算线程数为4 + parameters { key: "cpu_threads" value: "4" } + # 开启mkldnn加速,设置为0关闭mkldnn + parameters { key: "use_mkldnn" value: "1" } + } + ] + } +} \ No newline at end of file diff --git a/examples/vision/ocr/PP-OCRv3/serving/models/rec_postprocess/1/model.py b/examples/vision/ocr/PP-OCRv3/serving/models/rec_postprocess/1/model.py old mode 100644 new mode 100755 index 049173382..fe66e8c3f --- a/examples/vision/ocr/PP-OCRv3/serving/models/rec_postprocess/1/model.py +++ b/examples/vision/ocr/PP-OCRv3/serving/models/rec_postprocess/1/model.py @@ -47,8 +47,6 @@ class TritonPythonModel: * model_version: Model version * model_name: Model name """ - sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) - print(sys.getdefaultencoding()) # 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) diff --git a/examples/vision/ocr/PP-OCRv3/serving/models/rec_runtime/config.pbtxt b/examples/vision/ocr/PP-OCRv3/serving/models/rec_runtime/config.pbtxt old mode 100644 new mode 100755 index d4b3b1212..037d7a9f2 --- a/examples/vision/ocr/PP-OCRv3/serving/models/rec_runtime/config.pbtxt +++ b/examples/vision/ocr/PP-OCRv3/serving/models/rec_runtime/config.pbtxt @@ -35,3 +35,18 @@ instance_group [ gpus: [0] } ] + +optimization { + execution_accelerators { + # GPU推理配置, 配合KIND_GPU使用 + gpu_execution_accelerator : [ + { + name : "paddle" + # 设置推理并行计算线程数为4 + parameters { key: "cpu_threads" value: "4" } + # 开启mkldnn加速,设置为0关闭mkldnn + parameters { key: "use_mkldnn" value: "1" } + } + ] + } +} \ No newline at end of file diff --git a/examples/vision/segmentation/paddleseg/android/README.md b/examples/vision/segmentation/paddleseg/android/README.md index 9b3fe5062..f5fc5cfa7 100644 --- a/examples/vision/segmentation/paddleseg/android/README.md +++ b/examples/vision/segmentation/paddleseg/android/README.md @@ -155,7 +155,7 @@ model.setVerticalScreenFlag(true); model.init(modelFile, paramFile, configFile, option); // Bitmap读取、模型预测、资源释放 同上 ... ``` -更详细的用法请参考 [SegmentationMainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SegmentationMainActivity.java) 中的用法 +更详细的用法请参考 [SegmentationMainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java) 中的用法 ## 替换 FastDeploy SDK和模型 替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-sdk-xxx.aar`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models/portrait_pp_humansegv2_lite_256x144_inference_model`。 diff --git a/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java b/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java index 08ecda611..88b3c3a5b 100644 --- a/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java +++ b/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java @@ -287,6 +287,8 @@ public class SegmentationMainActivity extends Activity implements View.OnClickLi // Open camera until the permissions have been granted if (!checkAllPermissions()) { svPreview.disableCamera(); + } else { + svPreview.enableCamera(); } svPreview.onResume(); } diff --git a/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java b/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java index 94a5fdbd0..14217181d 100644 --- a/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java +++ b/examples/vision/segmentation/paddleseg/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java @@ -278,6 +278,10 @@ public class CameraSurfaceView extends GLSurfaceView implements Renderer, disableCamera = true; } + public void enableCamera() { + disableCamera = false; + } + public void switchCamera() { releaseCamera(); selectedCameraId = (selectedCameraId + 1) % numberOfCameras; diff --git a/examples/vision/segmentation/paddleseg/cpp/README.md b/examples/vision/segmentation/paddleseg/cpp/README.md index 926452ad0..e7b9dc5bf 100644 --- a/examples/vision/segmentation/paddleseg/cpp/README.md +++ b/examples/vision/segmentation/paddleseg/cpp/README.md @@ -9,7 +9,7 @@ 【注意】如你部署的为**PP-Matting**、**PP-HumanMatting**以及**ModNet**请参考[Matting模型部署](../../../matting) -以Linux上推理为例,在本目录执行如下命令即可完成编译测试,支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) +以Linux上推理为例,在本目录执行如下命令即可完成编译测试,支持此模型需保证FastDeploy版本1.0.0以上(x.x.x>=1.0.0) ```bash mkdir build @@ -85,7 +85,7 @@ PaddleSegModel模型加载和初始化,其中model_file为导出的Paddle模 > > * **is_vertical_screen**(bool): PP-HumanSeg系列模型通过设置此参数为`true`表明输入图片是竖屏,即height大于width的图片 #### 后处理参数 -> > * **appy_softmax**(bool): 当模型导出时,并未指定`apply_softmax`参数,可通过此设置此参数为`true`,将预测的输出分割标签(label_map)对应的概率结果(score_map)做softmax归一化处理 +> > * **apply_softmax**(bool): 当模型导出时,并未指定`apply_softmax`参数,可通过此设置此参数为`true`,将预测的输出分割标签(label_map)对应的概率结果(score_map)做softmax归一化处理 - [模型介绍](../../) - [Python部署](../python) diff --git a/examples/vision/segmentation/paddleseg/cpp/infer.cc b/examples/vision/segmentation/paddleseg/cpp/infer.cc index d3c462704..28bb56009 100644 --- a/examples/vision/segmentation/paddleseg/cpp/infer.cc +++ b/examples/vision/segmentation/paddleseg/cpp/infer.cc @@ -37,7 +37,7 @@ void CpuInfer(const std::string& model_dir, const std::string& image_file) { auto im = cv::imread(image_file); fastdeploy::vision::SegmentationResult res; - if (!model.Predict(&im, &res)) { + if (!model.Predict(im, &res)) { std::cerr << "Failed to predict." << std::endl; return; } @@ -66,7 +66,7 @@ void GpuInfer(const std::string& model_dir, const std::string& image_file) { auto im = cv::imread(image_file); fastdeploy::vision::SegmentationResult res; - if (!model.Predict(&im, &res)) { + if (!model.Predict(im, &res)) { std::cerr << "Failed to predict." << std::endl; return; } @@ -96,7 +96,7 @@ void TrtInfer(const std::string& model_dir, const std::string& image_file) { auto im = cv::imread(image_file); fastdeploy::vision::SegmentationResult res; - if (!model.Predict(&im, &res)) { + if (!model.Predict(im, &res)) { std::cerr << "Failed to predict." << std::endl; return; } diff --git a/examples/vision/segmentation/paddleseg/quantize/README.md b/examples/vision/segmentation/paddleseg/quantize/README.md old mode 100644 new mode 100755 index 6199c653a..83a76e384 --- a/examples/vision/segmentation/paddleseg/quantize/README.md +++ b/examples/vision/segmentation/paddleseg/quantize/README.md @@ -4,14 +4,14 @@ FastDeploy已支持部署量化模型,并提供一键模型自动化压缩的工 ## FastDeploy一键模型自动化压缩工具 FastDeploy 提供了一键模型自动化压缩工具, 能够简单地通过输入一个配置文件, 对模型进行量化. -详细教程请见: [一键模型自动化压缩工具](../../../../../tools/auto_compression/) +详细教程请见: [一键模型自动化压缩工具](../../../../../tools/common_tools/auto_compression/) 注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的deploy.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可。 ## 下载量化完成的PaddleSeg模型 用户也可以直接下载下表中的量化模型进行部署.(点击模型名字即可下载) Benchmark表格说明: -- Rtuntime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. +- Runtime时延为模型在各种Runtime上的推理时延,包含CPU->GPU数据拷贝,GPU推理,GPU->CPU数据拷贝时间. 不包含模型各自的前后处理时间. - 端到端时延为模型在实际推理场景中的时延, 包含模型的前后处理. - 所测时延均为推理1000次后求得的平均值, 单位是毫秒. - INT8 + FP16 为在推理INT8量化模型的同时, 给Runtime 开启FP16推理选项 @@ -26,7 +26,7 @@ Benchmark表格说明: | [PP-LiteSeg-T(STDC1)-cityscapes](https://bj.bcebos.com/paddlehub/fastdeploy/PP_LiteSeg_T_STDC1_cityscapes_without_argmax_infer_QAT_new.tar)) | Paddle Inference | CPU | 1138.04| 602.62 |None|None | 1.89 |77.37 | 71.62 |量化蒸馏训练 | #### 端到端 Benchmark -| 模型 |推理后端 |部署硬件 | FP32 Runtime时延 | INT8 Runtime时延 | INT8 + FP16 Runtime时延 | INT8+FP16+PM Runtime时延 | 最大加速比 | FP32 mIoU | INT8 mIoU | 量化方式 | +| 模型 |推理后端 |部署硬件 | FP32 End2End时延 | INT8 End2End时延 | INT8 + FP16 End2End时延 | INT8+FP16+PM End2End时延 | 最大加速比 | FP32 mIoU | INT8 mIoU | 量化方式 | | ------------------- | -----------------|-----------| -------- |-------- |-------- | --------- |-------- |----- |----- |----- | | [PP-LiteSeg-T(STDC1)-cityscapes](https://bj.bcebos.com/paddlehub/fastdeploy/PP_LiteSeg_T_STDC1_cityscapes_without_argmax_infer_QAT_new.tar)) | Paddle Inference | CPU | 4726.65| 4134.91|None|None | 1.14 |77.37 | 71.62 |量化蒸馏训练 | diff --git a/examples/vision/segmentation/paddleseg/quantize/cpp/README.md b/examples/vision/segmentation/paddleseg/quantize/cpp/README.md old mode 100644 new mode 100755 index 0fbaac173..bd17ec634 --- a/examples/vision/segmentation/paddleseg/quantize/cpp/README.md +++ b/examples/vision/segmentation/paddleseg/quantize/cpp/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的deploy.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的deploy.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的PP_LiteSeg_T_STDC1_cityscapes模型为例, 进行部署 在本目录执行如下命令即可完成编译,以及量化模型部署.支持此模型需保证FastDeploy版本0.7.0以上(x.x.x>=0.7.0) diff --git a/examples/vision/segmentation/paddleseg/quantize/cpp/infer.cc b/examples/vision/segmentation/paddleseg/quantize/cpp/infer.cc index 2611e2456..158a30263 100644 --- a/examples/vision/segmentation/paddleseg/quantize/cpp/infer.cc +++ b/examples/vision/segmentation/paddleseg/quantize/cpp/infer.cc @@ -34,7 +34,7 @@ void InitAndInfer(const std::string& model_dir, const std::string& image_file, auto im_bak = im.clone(); fastdeploy::vision::SegmentationResult res; - if (!model.Predict(&im, &res)) { + if (!model.Predict(im, &res)) { std::cerr << "Failed to predict." << std::endl; return; } diff --git a/examples/vision/segmentation/paddleseg/quantize/python/README.md b/examples/vision/segmentation/paddleseg/quantize/python/README.md old mode 100644 new mode 100755 index 2e06ae145..b9cc1c6c4 --- a/examples/vision/segmentation/paddleseg/quantize/python/README.md +++ b/examples/vision/segmentation/paddleseg/quantize/python/README.md @@ -8,7 +8,7 @@ ### 量化模型准备 - 1. 用户可以直接使用由FastDeploy提供的量化模型进行部署. -- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的deploy.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 2. 用户可以使用FastDeploy提供的[一键模型自动化压缩工具](../../../../../../tools/common_tools/auto_compression/),自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的deploy.yaml文件, 自行量化的模型文件夹内不包含此yaml文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) ## 以量化后的PP_LiteSeg_T_STDC1_cityscapes模型为例, 进行部署 diff --git a/examples/vision/segmentation/paddleseg/rknpu2/cpp/infer.cc b/examples/vision/segmentation/paddleseg/rknpu2/cpp/infer.cc index 9004828b7..bfc108d05 100644 --- a/examples/vision/segmentation/paddleseg/rknpu2/cpp/infer.cc +++ b/examples/vision/segmentation/paddleseg/rknpu2/cpp/infer.cc @@ -74,12 +74,12 @@ void InferHumanPPHumansegv2Lite(const std::string& device) { auto im = cv::imread(image_file); if (device == "npu") { - model.DisableNormalizeAndPermute(); + model.GetPreprocessor().DisableNormalizeAndPermute(); } fastdeploy::vision::SegmentationResult res; clock_t start = clock(); - if (!model.Predict(&im, &res)) { + if (!model.Predict(im, &res)) { std::cerr << "Failed to predict." << std::endl; return; } diff --git a/examples/vision/segmentation/paddleseg/rv1126/README.md b/examples/vision/segmentation/paddleseg/rv1126/README.md new file mode 100755 index 000000000..ed5d15080 --- /dev/null +++ b/examples/vision/segmentation/paddleseg/rv1126/README.md @@ -0,0 +1,11 @@ +# PP-LiteSeg 量化模型在 RV1126 上的部署 +目前 FastDeploy 已经支持基于 PaddleLite 部署 PP-LiteSeg 量化模型到 RV1126 上。 + +模型的量化和量化模型的下载请参考:[模型量化](../quantize/README.md) + + +## 详细部署文档 + +在 RV1126 上只支持 C++ 的部署。 + +- [C++部署](cpp) diff --git a/examples/vision/segmentation/paddleseg/rv1126/cpp/CMakeLists.txt b/examples/vision/segmentation/paddleseg/rv1126/cpp/CMakeLists.txt new file mode 100755 index 000000000..baaf8331f --- /dev/null +++ b/examples/vision/segmentation/paddleseg/rv1126/cpp/CMakeLists.txt @@ -0,0 +1,38 @@ +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}) +include_directories(${FastDeploy_INCLUDE_DIRS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc) +# 添加FastDeploy库依赖 +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) + +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build/install) + +install(TARGETS infer_demo DESTINATION ./) + +install(DIRECTORY models DESTINATION ./) +install(DIRECTORY images DESTINATION ./) +# install(DIRECTORY run_with_adb.sh DESTINATION ./) + +file(GLOB FASTDEPLOY_LIBS ${FASTDEPLOY_INSTALL_DIR}/lib/*) +install(PROGRAMS ${FASTDEPLOY_LIBS} DESTINATION lib) + +file(GLOB OPENCV_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/opencv/lib/lib*) +install(PROGRAMS ${OPENCV_LIBS} DESTINATION lib) + +file(GLOB PADDLELITE_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/lib*) +install(PROGRAMS ${PADDLELITE_LIBS} DESTINATION lib) + +file(GLOB TIMVX_LIBS ${FASTDEPLOY_INSTALL_DIR}/third_libs/install/paddlelite/lib/verisilicon_timvx/*) +install(PROGRAMS ${TIMVX_LIBS} DESTINATION lib) + +file(GLOB ADB_TOOLS run_with_adb.sh) +install(PROGRAMS ${ADB_TOOLS} DESTINATION ./) diff --git a/examples/vision/segmentation/paddleseg/rv1126/cpp/README.md b/examples/vision/segmentation/paddleseg/rv1126/cpp/README.md new file mode 100755 index 000000000..6295fa728 --- /dev/null +++ b/examples/vision/segmentation/paddleseg/rv1126/cpp/README.md @@ -0,0 +1,54 @@ +# PP-LiteSeg 量化模型 C++ 部署示例 + +本目录下提供的 `infer.cc`,可以帮助用户快速完成 PP-LiteSeg 量化模型在 RV1126 上的部署推理加速。 + +## 部署准备 +### FastDeploy 交叉编译环境准备 +- 1. 软硬件环境满足要求,以及交叉编译环境的准备,请参考:[FastDeploy 交叉编译环境准备](../../../../../../docs/cn/build_and_install/rv1126.md#交叉编译环境搭建) + +### 模型准备 +- 1. 用户可以直接使用由 FastDeploy 提供的量化模型进行部署。 +- 2. 用户可以使用 FastDeploy 提供的一键模型自动化压缩工具,自行进行模型量化, 并使用产出的量化模型进行部署.(注意: 推理量化后的分类模型仍然需要FP32模型文件夹下的 deploy.yaml 文件, 自行量化的模型文件夹内不包含此 yaml 文件, 用户从FP32模型文件夹下复制此yaml文件到量化后的模型文件夹内即可.) +- 更多量化相关相关信息可查阅[模型量化](../../quantize/README.md) + +## 在 RV1126 上部署量化后的 PP-LiteSeg 分割模型 +请按照以下步骤完成在 RV1126 上部署 PP-LiteSeg 量化模型: +1. 交叉编译编译 FastDeploy 库,具体请参考:[交叉编译 FastDeploy](../../../../../../docs/cn/build_and_install/rv1126.md#基于-paddlelite-的-fastdeploy-交叉编译库编译) + +2. 将编译后的库拷贝到当前目录,可使用如下命令: +```bash +cp -r FastDeploy/build/fastdeploy-tmivx/ FastDeploy/examples/vision/segmentation/paddleseg/rv1126/cpp +``` + +3. 在当前路径下载部署所需的模型和示例图片: +```bash +mkdir models && mkdir images +wget https://bj.bcebos.com/fastdeploy/models/rk1/ppliteseg.tar.gz +tar -xvf ppliteseg.tar.gz +cp -r ppliteseg models +wget https://paddleseg.bj.bcebos.com/dygraph/demo/cityscapes_demo.png +cp -r cityscapes_demo.png images +``` + +4. 编译部署示例,可使入如下命令: +```bash +mkdir build && cd build +cmake -DCMAKE_TOOLCHAIN_FILE=${PWD}/../fastdeploy-tmivx/timvx.cmake -DFASTDEPLOY_INSTALL_DIR=${PWD}/../fastdeploy-tmivx .. +make -j8 +make install +# 成功编译之后,会生成 install 文件夹,里面有一个运行 demo 和部署所需的库 +``` + +5. 基于 adb 工具部署 PP-LiteSeg 分割模型到 Rockchip RV1126,可使用如下命令: +```bash +# 进入 install 目录 +cd FastDeploy/examples/vision/segmentation/paddleseg/rv1126/cpp/build/install/ +# 如下命令表示:bash run_with_adb.sh 需要运行的demo 模型路径 图片路径 设备的DEVICE_ID +bash run_with_adb.sh infer_demo ppliteseg cityscapes_demo.png $DEVICE_ID +``` + +部署成功后运行结果如下: + + + +需要特别注意的是,在 RV1126 上部署的模型需要是量化后的模型,模型的量化请参考:[模型量化](../../../../../../docs/cn/quantize.md) diff --git a/examples/vision/segmentation/paddleseg/rv1126/cpp/infer.cc b/examples/vision/segmentation/paddleseg/rv1126/cpp/infer.cc new file mode 100755 index 000000000..8c9c7456c --- /dev/null +++ b/examples/vision/segmentation/paddleseg/rv1126/cpp/infer.cc @@ -0,0 +1,66 @@ +// 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) { + auto model_file = model_dir + sep + "model.pdmodel"; + auto params_file = model_dir + sep + "model.pdiparams"; + auto config_file = model_dir + sep + "deploy.yaml"; + auto subgraph_file = model_dir + sep + "subgraph.txt"; + + fastdeploy::RuntimeOption option; + option.UseTimVX(); + option.SetLiteSubgraphPartitionPath(subgraph_file); + + auto model = fastdeploy::vision::segmentation::PaddleSegModel( + model_file, params_file, config_file,option); + + assert(model.Initialized()); + + auto im = cv::imread(image_file); + + fastdeploy::vision::SegmentationResult 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::VisSegmentation(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 < 3) { + std::cout << "Usage: infer_demo path/to/quant_model " + "path/to/image " + "run_option, " + "e.g ./infer_demo ./ResNet50_vd_quant ./test.jpeg" + << std::endl; + return -1; + } + + std::string model_dir = argv[1]; + std::string test_image = argv[2]; + InitAndInfer(model_dir, test_image); + return 0; +} \ No newline at end of file diff --git a/examples/vision/segmentation/paddleseg/rv1126/cpp/run_with_adb.sh b/examples/vision/segmentation/paddleseg/rv1126/cpp/run_with_adb.sh new file mode 100755 index 000000000..aacaed4c5 --- /dev/null +++ b/examples/vision/segmentation/paddleseg/rv1126/cpp/run_with_adb.sh @@ -0,0 +1,47 @@ +#!/bin/bash +HOST_SPACE=${PWD} +echo ${HOST_SPACE} +WORK_SPACE=/data/local/tmp/test + +# The first parameter represents the demo name +DEMO_NAME=image_classification_demo +if [ -n "$1" ]; then + DEMO_NAME=$1 +fi + +# The second parameter represents the model name +MODEL_NAME=mobilenet_v1_fp32_224 +if [ -n "$2" ]; then + MODEL_NAME=$2 +fi + +# The third parameter indicates the name of the image to be tested +IMAGE_NAME=0001.jpg +if [ -n "$3" ]; then + IMAGE_NAME=$3 +fi + +# The fourth parameter represents the ID of the device +ADB_DEVICE_NAME= +if [ -n "$4" ]; then + ADB_DEVICE_NAME="-s $4" +fi + +# Set the environment variables required during the running process +EXPORT_ENVIRONMENT_VARIABLES="export GLOG_v=5; export VIV_VX_ENABLE_GRAPH_TRANSFORM=-pcq:1; export VIV_VX_SET_PER_CHANNEL_ENTROPY=100; export TIMVX_BATCHNORM_FUSION_MAX_ALLOWED_QUANT_SCALE_DEVIATION=300000; export VSI_NN_LOG_LEVEL=5;" + +EXPORT_ENVIRONMENT_VARIABLES="${EXPORT_ENVIRONMENT_VARIABLES}export LD_LIBRARY_PATH=${WORK_SPACE}/lib:\$LD_LIBRARY_PATH;" + +# Please install adb, and DON'T run this in the docker. +set -e +adb $ADB_DEVICE_NAME shell "rm -rf $WORK_SPACE" +adb $ADB_DEVICE_NAME shell "mkdir -p $WORK_SPACE" + +# Upload the demo, librarys, model and test images to the device +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/lib $WORK_SPACE +adb $ADB_DEVICE_NAME push ${HOST_SPACE}/${DEMO_NAME} $WORK_SPACE +adb $ADB_DEVICE_NAME push models $WORK_SPACE +adb $ADB_DEVICE_NAME push images $WORK_SPACE + +# Execute the deployment demo +adb $ADB_DEVICE_NAME shell "cd $WORK_SPACE; ${EXPORT_ENVIRONMENT_VARIABLES} chmod +x ./${DEMO_NAME}; ./${DEMO_NAME} ./models/${MODEL_NAME} ./images/$IMAGE_NAME" diff --git a/fastdeploy/backends/lite/lite_backend.cc b/fastdeploy/backends/lite/lite_backend.cc index e3c87aabd..7e3e09f8d 100755 --- a/fastdeploy/backends/lite/lite_backend.cc +++ b/fastdeploy/backends/lite/lite_backend.cc @@ -72,7 +72,7 @@ void LiteBackend::BuildOption(const LiteBackendOption& option) { } } } - if(option_.enable_timvx){ + if(option_.enable_timvx) { config_.set_nnadapter_device_names({"verisilicon_timvx"}); valid_places.push_back( paddle::lite_api::Place{TARGET(kNNAdapter), PRECISION(kInt8)}); @@ -206,21 +206,29 @@ bool LiteBackend::Infer(std::vector& inputs, // Adjust dims only, allocate lazy. tensor->Resize(inputs[i].shape); if (inputs[i].dtype == FDDataType::FP32) { - tensor->CopyFromCpu( + tensor->CopyFromCpu( reinterpret_cast(const_cast( inputs[i].CpuData()))); } else if (inputs[i].dtype == FDDataType::INT32) { - tensor->CopyFromCpu( + tensor->CopyFromCpu( reinterpret_cast(const_cast( inputs[i].CpuData()))); } else if (inputs[i].dtype == FDDataType::INT8) { - tensor->CopyFromCpu( + tensor->CopyFromCpu( reinterpret_cast(const_cast( inputs[i].CpuData()))); } else if (inputs[i].dtype == FDDataType::UINT8) { - tensor->CopyFromCpu( + tensor->CopyFromCpu( reinterpret_cast(const_cast( inputs[i].CpuData()))); + } else if (inputs[i].dtype == FDDataType::INT64) { +#ifdef __aarch64__ + tensor->CopyFromCpu( + reinterpret_cast(const_cast( + inputs[i].CpuData()))); +#else + FDASSERT(false, "FDDataType::INT64 is not support for Arm v7 now!"); +#endif } else { FDASSERT(false, "Unexpected data type of %d.", inputs[i].dtype); } diff --git a/fastdeploy/backends/openvino/ov_backend.cc b/fastdeploy/backends/openvino/ov_backend.cc old mode 100644 new mode 100755 index 9e8c2571a..6858f8547 --- a/fastdeploy/backends/openvino/ov_backend.cc +++ b/fastdeploy/backends/openvino/ov_backend.cc @@ -176,7 +176,7 @@ bool OpenVINOBackend::InitFromPaddle(const std::string& model_file, } ov::AnyMap properties; - if (option_.cpu_thread_num > 0) { + if (option_.device == "CPU" && option_.cpu_thread_num > 0) { properties["INFERENCE_NUM_THREADS"] = option_.cpu_thread_num; } if (option_.device == "CPU") { @@ -306,7 +306,7 @@ bool OpenVINOBackend::InitFromOnnx(const std::string& model_file, } ov::AnyMap properties; - if (option_.cpu_thread_num > 0) { + if (option_.device == "CPU" && option_.cpu_thread_num > 0) { properties["INFERENCE_NUM_THREADS"] = option_.cpu_thread_num; } if (option_.device == "CPU") { diff --git a/fastdeploy/backends/ort/ops/adaptive_pool2d.cc b/fastdeploy/backends/ort/ops/adaptive_pool2d.cc index 7b4ec7ad4..045b42eb6 100755 --- a/fastdeploy/backends/ort/ops/adaptive_pool2d.cc +++ b/fastdeploy/backends/ort/ops/adaptive_pool2d.cc @@ -76,7 +76,7 @@ void AdaptivePool2dKernel::Compute(OrtKernelContext* context) { context, 0, output_size_.data(), output_size_.size()); float* output_data = ort_.GetTensorMutableData(output); - if(this->provider_ == "CUDAExecutionProvider"){ + if(!strcmp(this->provider_, "CUDAExecutionProvider")){ #ifdef WITH_GPU auto compute_stream = ort_.KernelContext_GetGPUComputeStream(context); CudaAdaptivePool(input_size, output_size_, output_data, input_data, compute_stream, pooling_type_); @@ -85,7 +85,7 @@ void AdaptivePool2dKernel::Compute(OrtKernelContext* context) { << "Will force to use CPU to run." << std::endl; CpuAdaptivePool(input_size, output_size_, input_data, output_data); #endif - }else{ + } else { CpuAdaptivePool(input_size, output_size_, input_data, output_data); } } diff --git a/fastdeploy/backends/paddle/paddle_backend.cc b/fastdeploy/backends/paddle/paddle_backend.cc index 866bf578e..49abf02b1 100644 --- a/fastdeploy/backends/paddle/paddle_backend.cc +++ b/fastdeploy/backends/paddle/paddle_backend.cc @@ -22,24 +22,34 @@ void PaddleBackend::BuildOption(const PaddleBackendOption& option) { option_ = option; if (option.use_gpu) { config_.EnableUseGpu(option.gpu_mem_init_size, option.gpu_id); - if(option_.external_stream_) { + if (option_.external_stream_) { config_.SetExecStream(option_.external_stream_); } if (option.enable_trt) { #ifdef ENABLE_TRT_BACKEND + config_.Exp_DisableTensorRtOPs(option.trt_disabled_ops_); auto precision = paddle_infer::PrecisionType::kFloat32; if (option.trt_option.enable_fp16) { precision = paddle_infer::PrecisionType::kHalf; } bool use_static = false; if (option.trt_option.serialize_file != "") { - FDWARNING << "Detect that tensorrt cache file has been set to " << option.trt_option.serialize_file << ", but while enable paddle2trt, please notice that the cache file will save to the directory where paddle model saved." << std::endl; + FDWARNING + << "Detect that tensorrt cache file has been set to " + << option.trt_option.serialize_file + << ", but while enable paddle2trt, please notice that the cache " + "file will save to the directory where paddle model saved." + << std::endl; use_static = true; } - config_.EnableTensorRtEngine(option.trt_option.max_workspace_size, option.trt_option.max_batch_size, 3, precision, use_static); + config_.EnableTensorRtEngine(option.trt_option.max_workspace_size, + option.trt_option.max_batch_size, 3, + precision, use_static); SetTRTDynamicShapeToConfig(option); #else - FDWARNING << "The FastDeploy is not compiled with TensorRT backend, so will fallback to GPU with Paddle Inference Backend." << std::endl; + FDWARNING << "The FastDeploy is not compiled with TensorRT backend, so " + "will fallback to GPU with Paddle Inference Backend." + << std::endl; #endif } } else if (option.use_ipu) { @@ -98,39 +108,48 @@ bool PaddleBackend::InitFromPaddle(const std::string& model_file, if (!ReadBinaryFromFile(model_file, &contents)) { return false; } - auto reader = - paddle2onnx::PaddleReader(contents.c_str(), contents.size()); + auto reader = paddle2onnx::PaddleReader(contents.c_str(), contents.size()); // If it's a quantized model, and use cpu with mkldnn, automaticaly switch to int8 mode if (reader.is_quantize_model) { if (option.use_gpu) { - FDWARNING << "The loaded model is a quantized model, while inference on GPU, please use TensorRT backend to get better performance." << std::endl; + FDWARNING << "The loaded model is a quantized model, while inference on " + "GPU, please use TensorRT backend to get better performance." + << std::endl; if (option.enable_trt) { #ifdef ENABLE_TRT_BACKEND bool use_static = false; if (option.trt_option.serialize_file != "") { - FDWARNING << "Detect that tensorrt cache file has been set to " << option.trt_option.serialize_file << ", but while enable paddle2trt, please notice that the cache file will save to the directory where paddle model saved." << std::endl; + FDWARNING + << "Detect that tensorrt cache file has been set to " + << option.trt_option.serialize_file + << ", but while enable paddle2trt, please notice that the cache " + "file will save to the directory where paddle model saved." + << std::endl; use_static = true; } - config_.EnableTensorRtEngine(option.trt_option.max_workspace_size, option.trt_option.max_batch_size, 3, paddle_infer::PrecisionType::kInt8, use_static, false); + config_.EnableTensorRtEngine(option.trt_option.max_workspace_size, + option.trt_option.max_batch_size, 3, + paddle_infer::PrecisionType::kInt8, + use_static, false); SetTRTDynamicShapeToConfig(option); - #endif } } if (option.enable_mkldnn) { config_.EnableMkldnnInt8(); } else { - FDWARNING << "The loaded model is a quantized model, while inference on CPU, please enable MKLDNN to get better performance." << std::endl; + FDWARNING << "The loaded model is a quantized model, while inference on " + "CPU, please enable MKLDNN to get better performance." + << std::endl; } } inputs_desc_.resize(reader.num_inputs); for (int i = 0; i < reader.num_inputs; ++i) { std::string name(reader.inputs[i].name); - std::vector shape( - reader.inputs[i].shape, - reader.inputs[i].shape + reader.inputs[i].rank); + std::vector shape(reader.inputs[i].shape, + reader.inputs[i].shape + reader.inputs[i].rank); inputs_desc_[i].name = name; inputs_desc_[i].shape.assign(shape.begin(), shape.end()); inputs_desc_[i].dtype = ReaderDataTypeToFD(reader.inputs[i].dtype); @@ -138,7 +157,9 @@ bool PaddleBackend::InitFromPaddle(const std::string& model_file, outputs_desc_.resize(reader.num_outputs); for (int i = 0; i < reader.num_outputs; ++i) { std::string name(reader.outputs[i].name); - std::vector shape(reader.outputs[i].shape, reader.outputs[i].shape + reader.outputs[i].rank); + std::vector shape(reader.outputs[i].shape, + reader.outputs[i].shape + + reader.outputs[i].rank); outputs_desc_[i].name = name; outputs_desc_[i].shape.assign(shape.begin(), shape.end()); outputs_desc_[i].dtype = ReaderDataTypeToFD(reader.outputs[i].dtype); @@ -147,7 +168,8 @@ bool PaddleBackend::InitFromPaddle(const std::string& model_file, if (option.collect_shape) { // Set the shape info file. auto curr_model_dir = GetDirFromPath(model_file); - std::string shape_range_info = PathJoin(curr_model_dir, "shape_range_info.pbtxt"); + std::string shape_range_info = + PathJoin(curr_model_dir, "shape_range_info.pbtxt"); if (!CheckFileExists(shape_range_info)) { FDINFO << "Start generating shape range info file." << std::endl; paddle_infer::Config analysis_config; @@ -164,7 +186,8 @@ bool PaddleBackend::InitFromPaddle(const std::string& model_file, CollectShapeRun(predictor_tmp.get(), opt_shape); FDINFO << "Finish generating shape range info file." << std::endl; } - FDINFO << "Start loading shape range info file "<< shape_range_info << " to set TensorRT dynamic shape." << std::endl; + FDINFO << "Start loading shape range info file " << shape_range_info + << " to set TensorRT dynamic shape." << std::endl; config_.EnableTunedTensorRtDynamicShape(shape_range_info, false); } #endif @@ -194,8 +217,7 @@ std::vector PaddleBackend::GetOutputInfos() { } bool PaddleBackend::Infer(std::vector& inputs, - std::vector* outputs, - bool copy_to_fd) { + std::vector* outputs, bool copy_to_fd) { if (inputs.size() != inputs_desc_.size()) { FDERROR << "[PaddleBackend] Size of inputs(" << inputs.size() << ") should keep same with the inputs of this model(" @@ -211,13 +233,13 @@ bool PaddleBackend::Infer(std::vector& inputs, predictor_->Run(); // output share backend memory only support CPU or GPU - if(option_.use_ipu) { + if (option_.use_ipu) { copy_to_fd = true; } outputs->resize(outputs_desc_.size()); for (size_t i = 0; i < outputs_desc_.size(); ++i) { auto handle = predictor_->GetOutputHandle(outputs_desc_[i].name); - if(copy_to_fd) { + if (copy_to_fd) { (*outputs)[i].is_pinned_memory = option_.enable_pinned_memory; } PaddleTensorToFDTensor(handle, &((*outputs)[i]), copy_to_fd); @@ -225,47 +247,47 @@ bool PaddleBackend::Infer(std::vector& inputs, return true; } -std::unique_ptr PaddleBackend::Clone(void *stream, int device_id) { - std::unique_ptr new_backend = utils::make_unique(); +std::unique_ptr PaddleBackend::Clone(void* stream, int device_id) { + std::unique_ptr new_backend = + utils::make_unique(); auto casted_backend = dynamic_cast(new_backend.get()); - if(device_id > 0 && option_.use_gpu == true && device_id != option_.gpu_id) { + if (device_id > 0 && option_.use_gpu == true && device_id != option_.gpu_id) { auto clone_option = option_; clone_option.gpu_id = device_id; clone_option.external_stream_ = stream; casted_backend->InitFromPaddle(clone_option.model_file, - clone_option.params_file, - clone_option); - FDWARNING << "The target device id:" - << device_id - << " is different from current device id:" - << option_.gpu_id - << ", cannot share memory with current engine." - << std::endl; + clone_option.params_file, clone_option); + FDWARNING << "The target device id:" << device_id + << " is different from current device id:" << option_.gpu_id + << ", cannot share memory with current engine." << std::endl; return new_backend; } casted_backend->inputs_desc_.assign(inputs_desc_.begin(), inputs_desc_.end()); - casted_backend->outputs_desc_.assign(outputs_desc_.begin(), outputs_desc_.end()); + casted_backend->outputs_desc_.assign(outputs_desc_.begin(), + outputs_desc_.end()); casted_backend->predictor_ = std::move(predictor_->Clone(stream)); return new_backend; } #ifdef ENABLE_TRT_BACKEND -void PaddleBackend::SetTRTDynamicShapeToConfig(const PaddleBackendOption& option) { - std::map> max_shape; - std::map> min_shape; - std::map> opt_shape; - GetDynamicShapeFromOption(option, &max_shape, &min_shape, &opt_shape); +void PaddleBackend::SetTRTDynamicShapeToConfig( + const PaddleBackendOption& option) { + std::map> max_shape; + std::map> min_shape; + std::map> opt_shape; + GetDynamicShapeFromOption(option, &max_shape, &min_shape, &opt_shape); + if (min_shape.size() > 0) { FDINFO << "Start setting trt dynamic shape." << std::endl; - if (min_shape.size() > 0) { - config_.SetTRTDynamicShapeInfo(min_shape, max_shape, opt_shape); - } + config_.SetTRTDynamicShapeInfo(min_shape, max_shape, opt_shape); FDINFO << "Finish setting trt dynamic shape." << std::endl; + } } -void PaddleBackend::GetDynamicShapeFromOption(const PaddleBackendOption& option, - std::map>* max_shape, - std::map>* min_shape, - std::map>* opt_shape) const { +void PaddleBackend::GetDynamicShapeFromOption( + const PaddleBackendOption& option, + std::map>* max_shape, + std::map>* min_shape, + std::map>* opt_shape) const { auto print_shape = [](const std::vector& shape) -> std::string { std::ostringstream oss; oss << "["; @@ -281,24 +303,35 @@ void PaddleBackend::GetDynamicShapeFromOption(const PaddleBackendOption& option, for (const auto& item : option.trt_option.min_shape) { auto max_iter = option.trt_option.max_shape.find(item.first); auto opt_iter = option.trt_option.opt_shape.find(item.first); - FDASSERT(max_iter != option.trt_option.max_shape.end(), "Cannot find %s in TrtBackendOption::min_shape.", item.first.c_str()); - FDASSERT(opt_iter != option.trt_option.opt_shape.end(), "Cannot find %s in TrtBackendOption::opt_shape.", item.first.c_str()); - (*max_shape)[item.first].assign(max_iter->second.begin(), max_iter->second.end()); - (*opt_shape)[item.first].assign(opt_iter->second.begin(), opt_iter->second.end()); + FDASSERT(max_iter != option.trt_option.max_shape.end(), + "Cannot find %s in TrtBackendOption::min_shape.", + item.first.c_str()); + FDASSERT(opt_iter != option.trt_option.opt_shape.end(), + "Cannot find %s in TrtBackendOption::opt_shape.", + item.first.c_str()); + (*max_shape)[item.first].assign(max_iter->second.begin(), + max_iter->second.end()); + (*opt_shape)[item.first].assign(opt_iter->second.begin(), + opt_iter->second.end()); (*min_shape)[item.first].assign(item.second.begin(), item.second.end()); - FDINFO << item.first << ": the max shape = " << print_shape(max_iter->second) + FDINFO << item.first + << ": the max shape = " << print_shape(max_iter->second) << ", the min shape = " << print_shape(item.second) - << ", the opt shape = " << print_shape(opt_iter->second) << std::endl; + << ", the opt shape = " << print_shape(opt_iter->second) + << std::endl; } } -void PaddleBackend::CollectShapeRun(paddle_infer::Predictor* predictor, +void PaddleBackend::CollectShapeRun( + paddle_infer::Predictor* predictor, const std::map>& shape) const { auto input_names = predictor->GetInputNames(); auto input_type = predictor->GetInputTypes(); - for(auto name : input_names) { - FDASSERT(shape.find(name) != shape.end() && input_type.find(name) != input_type.end(), - "Paddle Input name [%s] is not one of the trt dynamic shape.", name.c_str()); + for (auto name : input_names) { + FDASSERT(shape.find(name) != shape.end() && + input_type.find(name) != input_type.end(), + "Paddle Input name [%s] is not one of the trt dynamic shape.", + name.c_str()); auto tensor = predictor->GetInputHandle(name); auto shape_value = shape.at(name); int shape_num = std::accumulate(shape_value.begin(), shape_value.end(), 1, @@ -306,30 +339,30 @@ void PaddleBackend::CollectShapeRun(paddle_infer::Predictor* predictor, tensor->Reshape(shape_value); auto dtype = input_type[name]; switch (dtype) { - case paddle_infer::DataType::FLOAT32: { - std::vector input_data(shape_num, 1.0); - tensor->CopyFromCpu(input_data.data()); - break; - } - case paddle_infer::DataType::INT32: { - std::vector input_data(shape_num, 1); - tensor->CopyFromCpu(input_data.data()); - break; - } - case paddle_infer::DataType::INT64: { - std::vector input_data(shape_num, 1); - tensor->CopyFromCpu(input_data.data()); - break; - } - default: { - FDASSERT(false, "Input data Paddle backend only supports FP32/INT32/INT64 currently."); - break; - } + case paddle_infer::DataType::FLOAT32: { + std::vector input_data(shape_num, 1.0); + tensor->CopyFromCpu(input_data.data()); + break; + } + case paddle_infer::DataType::INT32: { + std::vector input_data(shape_num, 1); + tensor->CopyFromCpu(input_data.data()); + break; + } + case paddle_infer::DataType::INT64: { + std::vector input_data(shape_num, 1); + tensor->CopyFromCpu(input_data.data()); + break; + } + default: { + FDASSERT(false, "Input data Paddle backend only supports " + "FP32/INT32/INT64 currently."); + break; + } } } predictor->Run(); } #endif - } // namespace fastdeploy diff --git a/fastdeploy/backends/paddle/paddle_backend.h b/fastdeploy/backends/paddle/paddle_backend.h old mode 100755 new mode 100644 index ba083ae43..2df0c6739 --- a/fastdeploy/backends/paddle/paddle_backend.h +++ b/fastdeploy/backends/paddle/paddle_backend.h @@ -23,8 +23,8 @@ #ifdef ENABLE_PADDLE_FRONTEND #include "paddle2onnx/converter.h" #endif -#include "paddle_inference_api.h" // NOLINT #include "fastdeploy/utils/unique_ptr.h" +#include "paddle_inference_api.h" // NOLINT #ifdef ENABLE_TRT_BACKEND #include "fastdeploy/backends/tensorrt/trt_backend.h" @@ -60,6 +60,7 @@ struct PaddleBackendOption { #ifdef ENABLE_TRT_BACKEND TrtBackendOption trt_option; bool collect_shape = false; + std::vector trt_disabled_ops_{}; #endif #ifdef WITH_IPU @@ -91,8 +92,7 @@ void ShareTensorFromFDTensor(paddle_infer::Tensor* tensor, FDTensor& fd_tensor); // if copy_to_fd is true, copy memory data to FDTensor /// else share memory to FDTensor void PaddleTensorToFDTensor(std::unique_ptr& tensor, - FDTensor* fd_tensor, - bool copy_to_fd); + FDTensor* fd_tensor, bool copy_to_fd); // Convert data type from paddle inference to fastdeploy FDDataType PaddleDataTypeToFD(const paddle_infer::DataType& dtype); @@ -106,20 +106,18 @@ class PaddleBackend : public BaseBackend { virtual ~PaddleBackend() = default; void BuildOption(const PaddleBackendOption& option); - bool InitFromPaddle( - const std::string& model_file, const std::string& params_file, - const PaddleBackendOption& option = PaddleBackendOption()); + bool + InitFromPaddle(const std::string& model_file, const std::string& params_file, + const PaddleBackendOption& option = PaddleBackendOption()); - bool Infer(std::vector& inputs, - std::vector* outputs, + bool Infer(std::vector& inputs, std::vector* outputs, bool copy_to_fd = true) override; - int NumInputs() const override { return inputs_desc_.size(); } int NumOutputs() const override { return outputs_desc_.size(); } - std::unique_ptr Clone(void *stream = nullptr, + std::unique_ptr Clone(void* stream = nullptr, int device_id = -1) override; TensorInfo GetInputInfo(int index) override; @@ -129,9 +127,11 @@ class PaddleBackend : public BaseBackend { private: #ifdef ENABLE_TRT_BACKEND - void CollectShapeRun(paddle_infer::Predictor* predictor, - const std::map>& shape) const; - void GetDynamicShapeFromOption(const PaddleBackendOption& option, + void + CollectShapeRun(paddle_infer::Predictor* predictor, + const std::map>& shape) const; + void GetDynamicShapeFromOption( + const PaddleBackendOption& option, std::map>* max_shape, std::map>* min_shape, std::map>* opt_shape) const; diff --git a/fastdeploy/backends/paddle/util.cc b/fastdeploy/backends/paddle/util.cc index 4e493fe16..eff6a361f 100644 --- a/fastdeploy/backends/paddle/util.cc +++ b/fastdeploy/backends/paddle/util.cc @@ -79,7 +79,7 @@ void PaddleTensorToFDTensor(std::unique_ptr& tensor, } else if (fd_tensor->dtype == FDDataType::INT64) { tensor->CopyToCpu(static_cast(fd_tensor->MutableData())); return; - } + } FDASSERT(false, "Unexpected data type(%s) while infer with PaddleBackend.", Str(fd_tensor->dtype).c_str()); } else { @@ -87,14 +87,29 @@ void PaddleTensorToFDTensor(std::unique_ptr& tensor, int size = 0; // TODO(liqi): The tensor->data interface of paddle don't return device id // and don't support return void*. - auto* out_data = tensor->data(&place, &size); + void* out_data = nullptr; + if (fd_dtype == FDDataType::FP32) { + out_data = tensor->data(&place, &size); + } else if (fd_dtype == FDDataType::INT32) { + out_data = tensor->data(&place, &size); + } else if (fd_dtype == FDDataType::INT64) { + out_data = tensor->data(&place, &size); + } else if (fd_dtype == FDDataType::INT8) { + out_data = tensor->data(&place, &size); + } else if (fd_dtype == FDDataType::UINT8) { + out_data = tensor->data(&place, &size); + } else { + FDASSERT(false, "Unexpected data type(%s) while infer shared with PaddleBackend.", + Str(fd_dtype).c_str()); + } Device device = Device::CPU; if(place == paddle_infer::PlaceType::kGPU) { device = Device::GPU; } + fd_tensor->name = tensor->name(); fd_tensor->SetExternalData( shape, fd_dtype, - reinterpret_cast(out_data), device); + out_data, device); } } diff --git a/fastdeploy/backends/rknpu/rknpu2/rknpu2_backend.cc b/fastdeploy/backends/rknpu/rknpu2/rknpu2_backend.cc index 16edf7561..b577c2791 100644 --- a/fastdeploy/backends/rknpu/rknpu2/rknpu2_backend.cc +++ b/fastdeploy/backends/rknpu/rknpu2/rknpu2_backend.cc @@ -190,6 +190,8 @@ bool RKNPU2Backend::GetModelInputOutputInfos() { FDERROR << "rknpu2_backend only support input format is NHWC or UNDEFINED" << std::endl; } + DumpTensorAttr(input_attrs_[i]); + // copy input_attrs_ to input tensor info std::string temp_name = input_attrs_[i].name; std::vector temp_shape{}; @@ -234,6 +236,8 @@ bool RKNPU2Backend::GetModelInputOutputInfos() { << std::endl; } + DumpTensorAttr(output_attrs_[i]); + // copy output_attrs_ to output tensor std::string temp_name = output_attrs_[i].name; std::vector temp_shape{}; @@ -342,7 +346,6 @@ bool RKNPU2Backend::Infer(std::vector& inputs, return false; } // default output type is depend on model, this requires float32 to compute top5 - output_attrs_[i].type = RKNN_TENSOR_FLOAT32; ret = rknn_set_io_mem(ctx, output_mems_[i], &output_attrs_[i]); // set output memory and attribute if (ret != RKNN_SUCC) { @@ -389,6 +392,8 @@ bool RKNPU2Backend::Infer(std::vector& inputs, } (*outputs)[i].Resize(temp_shape, outputs_desc_[i].dtype, outputs_desc_[i].name); + std::vector output_scale = {output_attrs_[i].scale}; + (*outputs)[i].SetQuantizationInfo(output_attrs_[i].zp, output_scale); memcpy((*outputs)[i].MutableData(), (float*)output_mems_[i]->virt_addr, (*outputs)[i].Nbytes()); } diff --git a/fastdeploy/core/fd_tensor.cc b/fastdeploy/core/fd_tensor.cc index 896f2ff3b..484e03913 100644 --- a/fastdeploy/core/fd_tensor.cc +++ b/fastdeploy/core/fd_tensor.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "fastdeploy/core/fd_tensor.h" -#include "fastdeploy/core/fd_scalar.h" #include "fastdeploy/core/float16.h" #include "fastdeploy/utils/utils.h" @@ -81,8 +80,7 @@ const void* FDTensor::CpuData() const { void FDTensor::SetExternalData(const std::vector& new_shape, const FDDataType& data_type, void* data_buffer, - const Device& new_device, - int new_device_id) { + const Device& new_device, int new_device_id) { dtype = data_type; shape.assign(new_shape.begin(), new_shape.end()); external_data_ptr = data_buffer; @@ -140,6 +138,11 @@ void FDTensor::Resize(const std::vector& new_shape) { external_data_ptr = nullptr; } +void FDTensor::SetQuantizationInfo(int32_t zero_point,std::vector& scale){ + quantized_parameter_.first = zero_point; + quantized_parameter_.second = scale; +} + void FDTensor::Resize(const std::vector& new_shape, const FDDataType& data_type, const std::string& tensor_name, @@ -452,4 +455,9 @@ FDTensor& FDTensor::operator=(FDTensor&& other) { return *this; } +const std::pair> +FDTensor::GetQuantizationInfo() const{ + return quantized_parameter_; +} + } // namespace fastdeploy diff --git a/fastdeploy/core/fd_tensor.h b/fastdeploy/core/fd_tensor.h index ef9ff3796..e3e373c43 100644 --- a/fastdeploy/core/fd_tensor.h +++ b/fastdeploy/core/fd_tensor.h @@ -19,13 +19,17 @@ #include #include "fastdeploy/core/allocate.h" +#include "fastdeploy/core/fd_scalar.h" #include "fastdeploy/core/fd_type.h" namespace fastdeploy { -struct Scalar; - struct FASTDEPLOY_DECL FDTensor { + // These two parameters are general parameters of quantitative model. + std::pair> quantized_parameter_ = {0, {0}}; + void SetQuantizationInfo(int32_t zero_point, std::vector& scale); + const std::pair> GetQuantizationInfo() const; + // std::vector data; void* buffer_ = nullptr; std::vector shape = {0}; diff --git a/fastdeploy/function/clip.cc b/fastdeploy/function/clip.cc index bede9e56a..c4b2fa9e0 100644 --- a/fastdeploy/function/clip.cc +++ b/fastdeploy/function/clip.cc @@ -39,14 +39,15 @@ void ClipKernel(const FDTensor& x, double min, double max, FDTensor* out) { "max should be greater than or equal to min. But received min = %f, " "max = %f", static_cast(min_), static_cast(max_)); - - out->Allocate(x.Shape(), x.Dtype()); + FDTensor tmp; + tmp.Allocate(x.Shape(), x.Dtype()); const T* x_data = reinterpret_cast(x.Data()); int64_t numel = x.Numel(); - T* out_data = reinterpret_cast(out->Data()); + T* out_data = reinterpret_cast(tmp.Data()); std::transform(x_data, x_data + numel, out_data, ClipFunctor(min_, max_)); + *out = std::move(tmp); } void Clip(const FDTensor& x, double min, double max, FDTensor* out) { diff --git a/fastdeploy/function/concat.cc b/fastdeploy/function/concat.cc index 295c3c25a..4f0774394 100644 --- a/fastdeploy/function/concat.cc +++ b/fastdeploy/function/concat.cc @@ -88,11 +88,13 @@ template void ConcatKernel(const std::vector& input, FDTensor* output, int axis) { auto output_shape = ComputeAndCheckConcatOutputShape(input, axis); - output->Resize(output_shape, TypeToDataType::dtype, output->name, - input[0].device); + FDTensor output_tmp; + output_tmp.Resize(output_shape, TypeToDataType::dtype, output->name, + input[0].device); ConcatFunctor functor; - functor(input, axis, output); + functor(input, axis, &output_tmp); + *output = std::move(output_tmp); } void Concat(const std::vector& x, FDTensor* out, int axis) { diff --git a/fastdeploy/function/elementwise.cc b/fastdeploy/function/elementwise.cc index 120fe1678..5d94764de 100644 --- a/fastdeploy/function/elementwise.cc +++ b/fastdeploy/function/elementwise.cc @@ -86,4 +86,25 @@ FDTensor operator/(const FDTensor& x, const FDTensor& y) { return out; } +#define INSTANTIATE_OPERATOR(operation_type) \ + template FDTensor operator operation_type(const FDTensor& x, bool y); \ + template FDTensor operator operation_type(const FDTensor& x, uint8_t y); \ + template FDTensor operator operation_type(const FDTensor& x, int16_t y); \ + template FDTensor operator operation_type(const FDTensor& x, int y); \ + template FDTensor operator operation_type(const FDTensor& x, int64_t y); \ + template FDTensor operator operation_type(const FDTensor& x, float y); \ + template FDTensor operator operation_type(const FDTensor& x, double y); \ + template FDTensor operator operation_type(bool x, const FDTensor& y); \ + template FDTensor operator operation_type(uint8_t x, const FDTensor& y); \ + template FDTensor operator operation_type(int16_t x, const FDTensor& y); \ + template FDTensor operator operation_type(int x, const FDTensor& y); \ + template FDTensor operator operation_type(int64_t x, const FDTensor& y); \ + template FDTensor operator operation_type(float x, const FDTensor& y); \ + template FDTensor operator operation_type(double x, const FDTensor& y) + +INSTANTIATE_OPERATOR(+); +INSTANTIATE_OPERATOR(-); +INSTANTIATE_OPERATOR(*); +INSTANTIATE_OPERATOR(/); + } // namespace fastdeploy diff --git a/fastdeploy/function/elementwise.h b/fastdeploy/function/elementwise.h index fd0a9c44b..53d34da6e 100644 --- a/fastdeploy/function/elementwise.h +++ b/fastdeploy/function/elementwise.h @@ -14,9 +14,11 @@ #pragma once +#include "fastdeploy/core/fd_scalar.h" #include "fastdeploy/core/fd_tensor.h" namespace fastdeploy { + namespace function { /** Excute the add operation for input FDTensors. *out = x + y. @@ -62,10 +64,42 @@ FASTDEPLOY_DECL void Maximum(const FDTensor& x, const FDTensor& y, FASTDEPLOY_DECL FDTensor operator+(const FDTensor& x, const FDTensor& y); +template FDTensor operator+(const FDTensor& x, T y) { + return x + FDTensor(Scalar(y)); +} + +template FDTensor operator+(T x, const FDTensor& y) { + return FDTensor(Scalar(x)) + y; +} + FASTDEPLOY_DECL FDTensor operator-(const FDTensor& x, const FDTensor& y); +template FDTensor operator-(const FDTensor& x, T y) { + return x - FDTensor(Scalar(y)); +} + +template FDTensor operator-(T x, const FDTensor& y) { + return FDTensor(Scalar(x)) - y; +} + FASTDEPLOY_DECL FDTensor operator*(const FDTensor& x, const FDTensor& y); +template FDTensor operator*(const FDTensor& x, T y) { + return x * FDTensor(Scalar(y)); +} + +template FDTensor operator*(T x, const FDTensor& y) { + return FDTensor(Scalar(x)) * y; +} + FASTDEPLOY_DECL FDTensor operator/(const FDTensor& x, const FDTensor& y); +template FDTensor operator/(const FDTensor& x, T y) { + return x / FDTensor(Scalar(y)); +} + +template FDTensor operator/(T x, const FDTensor& y) { + return FDTensor(Scalar(x)) / y; +} + } // namespace fastdeploy diff --git a/fastdeploy/function/elementwise_base.h b/fastdeploy/function/elementwise_base.h index e2fab684e..7ce1a694d 100644 --- a/fastdeploy/function/elementwise_base.h +++ b/fastdeploy/function/elementwise_base.h @@ -213,10 +213,12 @@ void CommonElementwiseBroadcastForward(const FDTensor& x, const FDTensor& y, GetBroadcastDimsArrays(x_dims, y_dims, x_dims_array.data(), y_dims_array.data(), out_dims_array.data(), max_dim, axis); - z->Allocate(out_dims_array, TypeToDataType::dtype); + FDTensor tmp; + tmp.Allocate(out_dims_array, TypeToDataType::dtype); CommonForwardBroadcastCPU( - x, y, z, x_dims_array.data(), y_dims_array.data(), out_dims_array.data(), - max_dim, func, is_xsize_larger); + x, y, &tmp, x_dims_array.data(), y_dims_array.data(), + out_dims_array.data(), max_dim, func, is_xsize_larger); + *z = std::move(tmp); } template diff --git a/fastdeploy/function/functions.h b/fastdeploy/function/functions.h index d2ffe6a0c..a43407839 100644 --- a/fastdeploy/function/functions.h +++ b/fastdeploy/function/functions.h @@ -21,6 +21,7 @@ #include "fastdeploy/function/elementwise.h" #include "fastdeploy/function/full.h" #include "fastdeploy/function/gather_scatter_along_axis.h" +#include "fastdeploy/function/gaussian_random.h" #include "fastdeploy/function/isfinite.h" #include "fastdeploy/function/linspace.h" #include "fastdeploy/function/math.h" diff --git a/fastdeploy/function/gaussian_random.cc b/fastdeploy/function/gaussian_random.cc new file mode 100644 index 000000000..18657c4f2 --- /dev/null +++ b/fastdeploy/function/gaussian_random.cc @@ -0,0 +1,46 @@ +// 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/function/gaussian_random.h" +#include +#include +#include + +namespace fastdeploy { +namespace function { + +template +void GaussianRandomKernel(const std::vector& shape, float mean, + float std, int seed, FDTensor* out) { + std::normal_distribution dist(mean, std); + + out->Allocate(shape, TypeToDataType::dtype); + int64_t size = out->Numel(); + T* data = reinterpret_cast(out->Data()); + std::mt19937_64 engine; + engine.seed(seed); + for (int64_t i = 0; i < size; ++i) { + data[i] = dist(engine); + } +} + +void GaussianRandom(const std::vector& shape, FDTensor* out, + FDDataType dtype, float mean, float std, int seed) { + FD_VISIT_FLOAT_TYPES(dtype, "GaussianRandomKernel", [&]() { + GaussianRandomKernel(shape, mean, std, seed, out); + }); +} + +} // namespace function +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/function/gaussian_random.h b/fastdeploy/function/gaussian_random.h new file mode 100644 index 000000000..85a4ff8a6 --- /dev/null +++ b/fastdeploy/function/gaussian_random.h @@ -0,0 +1,36 @@ +// 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/core/fd_tensor.h" + +namespace fastdeploy { +namespace function { + +/** Output is obtained by gathering entries of axis of x indexed by index and + * concatenate them together. + @param shape The output tensor shape. + @param out the output tensor. + @param mean mean value of gaussian random + @param std standard value of gaussian random + @param seed The seed of random generator. + @param dtype The data type of the output Tensor. +*/ +void GaussianRandom(const std::vector& shape, FDTensor* out, + FDDataType dtype = FDDataType::FP32, float mean = 0.0f, + float std = 1.0f, int seed = 0); + +} // namespace function +} // namespace fastdeploy diff --git a/fastdeploy/function/slice.cc b/fastdeploy/function/slice.cc index f374034f2..dab0ea023 100644 --- a/fastdeploy/function/slice.cc +++ b/fastdeploy/function/slice.cc @@ -163,5 +163,20 @@ void Slice(const FDTensor& x, const std::vector& axes, })); } +void Slice(const FDTensor& x, const std::vector& axes, + const std::vector& index, FDTensor* out) { + std::vector ends = index; + for (int i = 0; i < ends.size(); ++i) { + ends[i] += 1; + } + Slice(x, axes, index, ends, out); + for (int i = 0; i < axes.size(); ++i) { + if (out->Shape().size() <= 1) { + break; + } + out->Squeeze(axes[i]); + } +} + } // namespace function } // namespace fastdeploy diff --git a/fastdeploy/function/slice.h b/fastdeploy/function/slice.h index d676a232e..e35ee5762 100644 --- a/fastdeploy/function/slice.h +++ b/fastdeploy/function/slice.h @@ -37,5 +37,8 @@ FASTDEPLOY_DECL void Slice(const FDTensor& x, const std::vector& axes, const std::vector& starts, const std::vector& ends, FDTensor* out); +FASTDEPLOY_DECL void Slice(const FDTensor& x, const std::vector& axes, + const std::vector& index, FDTensor* out); + } // namespace function } // namespace fastdeploy diff --git a/fastdeploy/function/sort.cc b/fastdeploy/function/sort.cc index 23f66b808..5b81a631c 100644 --- a/fastdeploy/function/sort.cc +++ b/fastdeploy/function/sort.cc @@ -73,8 +73,9 @@ void SortKernel(const FDTensor& x, FDTensor* out, FDTensor* indices, axis = (axis < 0) ? (rank + axis) : axis; // Do full sort if (axis == -1 || axis + 1 == rank) { - const int64_t input_width = input_shape[rank - 1]; - const int64_t input_height = x.Numel() / input_width; + int64_t numel = x.Numel(); + int64_t input_width = input_shape[axis]; + int64_t input_height = numel / input_width; FD_VISIT_INT_TYPES(indices_type, "FullSort", ([&] { FullSort(input_height, input_width, rank, &x, out, indices, descending); @@ -93,8 +94,9 @@ void SortKernel(const FDTensor& x, FDTensor* out, FDTensor* indices, FDTensor trans_inp; Transpose(x, &trans_inp, trans); - const int64_t input_width = input_shape[axis]; - const int64_t input_height = x.Numel() / input_width; + int64_t numel = x.Numel(); + int64_t input_width = input_shape[axis]; + int64_t input_height = numel / input_width; FD_VISIT_INT_TYPES(indices_type, "FullSort", ([&] { FullSort(input_height, input_width, rank, &trans_inp, out, indices, @@ -115,4 +117,4 @@ void Sort(const FDTensor& x, FDTensor* out, FDTensor* indices, int axis, } } // namespace function -} // namespace fastdeploy \ No newline at end of file +} // namespace fastdeploy diff --git a/fastdeploy/function/tile.cc b/fastdeploy/function/tile.cc index 6437b4ec6..c6e3095c6 100644 --- a/fastdeploy/function/tile.cc +++ b/fastdeploy/function/tile.cc @@ -49,6 +49,7 @@ void TileFunctor(const FDTensor& x, return; } + FDTensor out_tmp; Eigen::DSizes bcast_dims; for (size_t i = 0; i < repeat_times.size(); ++i) { bcast_dims[i] = repeat_times[i]; @@ -59,12 +60,14 @@ void TileFunctor(const FDTensor& x, out_shape[i] *= repeat_times[i]; } - out->Allocate(out_shape, x.Dtype()); + out_tmp.Allocate(out_shape, x.Dtype()); auto eigen_x = EigenTensor::From(x, x_shape); - auto eigen_out = EigenTensor::From(*out, out_shape); + auto eigen_out = EigenTensor::From(out_tmp, out_shape); const auto& dev = *EigenDeviceWrapper::GetInstance()->GetDevice(); eigen_out.device(dev) = eigen_x.broadcast(bcast_dims); + + *out = std::move(out_tmp); } template diff --git a/fastdeploy/pybind/fd_tensor.cc b/fastdeploy/pybind/fd_tensor.cc index 93b8cbe9a..bf24dec6b 100644 --- a/fastdeploy/pybind/fd_tensor.cc +++ b/fastdeploy/pybind/fd_tensor.cc @@ -181,7 +181,8 @@ void BindFDTensor(pybind11::module& m) { .def("from_numpy", [](FDTensor& self, pybind11::array& pyarray, bool share_buffer = false) { PyArrayToTensor(pyarray, &self, share_buffer); }) - .def("to_dlpack", &FDTensorToDLPack); + .def("to_dlpack", &FDTensorToDLPack) + .def("print_info", &FDTensor::PrintInfo); } } // namespace fastdeploy diff --git a/fastdeploy/pybind/main.cc.in b/fastdeploy/pybind/main.cc.in index 97aafc64a..1b227edc6 100644 --- a/fastdeploy/pybind/main.cc.in +++ b/fastdeploy/pybind/main.cc.in @@ -35,6 +35,8 @@ pybind11::dtype FDDataTypeToNumpyDataType(const FDDataType& fd_dtype) { dt = pybind11::dtype::of(); } else if (fd_dtype == FDDataType::UINT8) { dt = pybind11::dtype::of(); + } else if (fd_dtype == FDDataType::INT8) { + dt = pybind11::dtype::of(); } else if (fd_dtype == FDDataType::FP16) { dt = pybind11::dtype::of(); } else { @@ -55,12 +57,14 @@ FDDataType NumpyDataTypeToFDDataType(const pybind11::dtype& np_dtype) { return FDDataType::FP64; } else if (np_dtype.is(pybind11::dtype::of())) { return FDDataType::UINT8; + } else if (np_dtype.is(pybind11::dtype::of())) { + return FDDataType::INT8; } else if (np_dtype.is(pybind11::dtype::of())) { return FDDataType::FP16; } FDASSERT(false, "NumpyDataTypeToFDDataType() only support " - "int32/int64/float32/float64/float16 now."); + "int8/int32/int64/float32/float64/float16 now."); return FDDataType::FP32; } diff --git a/fastdeploy/pybind/main.h b/fastdeploy/pybind/main.h index 471579ab1..c0ea4497a 100644 --- a/fastdeploy/pybind/main.h +++ b/fastdeploy/pybind/main.h @@ -67,9 +67,11 @@ FDDataType CTypeToFDDataType() { return FDDataType::FP32; } else if (std::is_same::value) { return FDDataType::FP64; + } else if (std::is_same::value) { + return FDDataType::INT8; } - FDASSERT(false, - "CTypeToFDDataType only support int32/int64/float32/float64 now."); + FDASSERT(false, "CTypeToFDDataType only support " + "int8/int32/int64/float32/float64 now."); return FDDataType::FP32; } diff --git a/fastdeploy/pybind/runtime.cc b/fastdeploy/pybind/runtime.cc index 66762ead6..75767c665 100644 --- a/fastdeploy/pybind/runtime.cc +++ b/fastdeploy/pybind/runtime.cc @@ -35,7 +35,8 @@ void BindRuntime(pybind11::module& m) { .def("set_paddle_mkldnn", &RuntimeOption::SetPaddleMKLDNN) .def("set_openvino_device", &RuntimeOption::SetOpenVINODevice) .def("set_openvino_shape_info", &RuntimeOption::SetOpenVINOShapeInfo) - .def("set_openvino_cpu_operators", &RuntimeOption::SetOpenVINOCpuOperators) + .def("set_openvino_cpu_operators", + &RuntimeOption::SetOpenVINOCpuOperators) .def("enable_paddle_log_info", &RuntimeOption::EnablePaddleLogInfo) .def("disable_paddle_log_info", &RuntimeOption::DisablePaddleLogInfo) .def("set_paddle_mkldnn_cache_size", @@ -52,10 +53,15 @@ void BindRuntime(pybind11::module& m) { .def("set_trt_cache_file", &RuntimeOption::SetTrtCacheFile) .def("enable_pinned_memory", &RuntimeOption::EnablePinnedMemory) .def("disable_pinned_memory", &RuntimeOption::DisablePinnedMemory) - .def("enable_paddle_trt_collect_shape", &RuntimeOption::EnablePaddleTrtCollectShape) - .def("disable_paddle_trt_collect_shape", &RuntimeOption::DisablePaddleTrtCollectShape) + .def("enable_paddle_trt_collect_shape", + &RuntimeOption::EnablePaddleTrtCollectShape) + .def("disable_paddle_trt_collect_shape", + &RuntimeOption::DisablePaddleTrtCollectShape) .def("use_ipu", &RuntimeOption::UseIpu) .def("set_ipu_config", &RuntimeOption::SetIpuConfig) + .def("delete_paddle_backend_pass", + &RuntimeOption::DeletePaddleBackendPass) + .def("disable_paddle_trt_ops", &RuntimeOption::DisablePaddleTrtOPs) .def_readwrite("model_file", &RuntimeOption::model_file) .def_readwrite("params_file", &RuntimeOption::params_file) .def_readwrite("model_format", &RuntimeOption::model_format) @@ -117,9 +123,9 @@ void BindRuntime(pybind11::module& m) { auto dtype = NumpyDataTypeToFDDataType(warm_datas[i][j].dtype()); std::vector data_shape; - data_shape.insert( - data_shape.begin(), warm_datas[i][j].shape(), - warm_datas[i][j].shape() + warm_datas[i][j].ndim()); + data_shape.insert(data_shape.begin(), warm_datas[i][j].shape(), + warm_datas[i][j].shape() + + warm_datas[i][j].ndim()); warm_tensors[i][j].Resize(data_shape, dtype); memcpy(warm_tensors[i][j].MutableData(), warm_datas[i][j].mutable_data(), @@ -128,12 +134,6 @@ void BindRuntime(pybind11::module& m) { } return self.Compile(warm_tensors, _option); }) - .def("infer", - [](Runtime& self, std::vector& inputs) { - std::vector outputs(self.NumOutputs()); - self.Infer(inputs, &outputs); - return outputs; - }) .def("infer", [](Runtime& self, std::map& data) { std::vector inputs(data.size()); @@ -166,25 +166,39 @@ void BindRuntime(pybind11::module& m) { } return results; }) - .def("infer", [](Runtime& self, std::map& data) { - std::vector inputs; - inputs.reserve(data.size()); - for (auto iter = data.begin(); iter != data.end(); ++iter) { - FDTensor tensor; - tensor.SetExternalData(iter->second.Shape(), iter->second.Dtype(), iter->second.Data(), iter->second.device); - tensor.name = iter->first; - inputs.push_back(tensor); - } - std::vector outputs; - if (!self.Infer(inputs, &outputs)) { - throw std::runtime_error("Failed to inference with Runtime."); - } - return outputs; - }) - .def("infer", [](Runtime& self, std::vector& inputs) { - std::vector outputs; - return self.Infer(inputs, &outputs); - }) + .def("infer", + [](Runtime& self, std::map& data) { + std::vector inputs; + inputs.reserve(data.size()); + for (auto iter = data.begin(); iter != data.end(); ++iter) { + FDTensor tensor; + tensor.SetExternalData(iter->second.Shape(), + iter->second.Dtype(), iter->second.Data(), + iter->second.device); + tensor.name = iter->first; + inputs.push_back(tensor); + } + std::vector outputs; + if (!self.Infer(inputs, &outputs)) { + throw std::runtime_error("Failed to inference with Runtime."); + } + return outputs; + }) + .def("infer", + [](Runtime& self, std::vector& inputs) { + std::vector outputs; + return self.Infer(inputs, &outputs); + }) + .def("bind_input_tensor", &Runtime::BindInputTensor) + .def("infer", [](Runtime& self) { self.Infer(); }) + .def("get_output_tensor", + [](Runtime& self, const std::string& name) { + FDTensor* output = self.GetOutputTensor(name); + if (output == nullptr) { + return pybind11::cast(nullptr); + } + return pybind11::cast(*output); + }) .def("num_inputs", &Runtime::NumInputs) .def("num_outputs", &Runtime::NumOutputs) .def("get_input_info", &Runtime::GetInputInfo) diff --git a/fastdeploy/runtime.cc b/fastdeploy/runtime.cc old mode 100755 new mode 100644 index 2350817e5..1a51cebea --- a/fastdeploy/runtime.cc +++ b/fastdeploy/runtime.cc @@ -94,7 +94,7 @@ std::string Str(const Backend& b) { return "Backend::POROS"; } else if (b == Backend::RKNPU2) { return "Backend::RKNPU2"; - }else if (b == Backend::OPENVINO) { + } else if (b == Backend::OPENVINO) { return "Backend::OPENVINO"; } else if (b == Backend::LITE) { return "Backend::PDLITE"; @@ -113,7 +113,7 @@ std::ostream& operator<<(std::ostream& out, const Backend& backend) { out << "Backend::OPENVINO"; } else if (backend == Backend::RKNPU2) { out << "Backend::RKNPU2"; - }else if (backend == Backend::POROS) { + } else if (backend == Backend::POROS) { out << "Backend::POROS"; } else if (backend == Backend::LITE) { out << "Backend::PDLITE"; @@ -152,15 +152,17 @@ bool CheckModelFormat(const std::string& model_file, } else if (model_format == ModelFormat::TORCHSCRIPT) { if (model_file.size() < 3 || model_file.substr(model_file.size() - 3, 3) != ".pt") { - FDERROR << "With model format of ModelFormat::TORCHSCRIPT, the model file " - "should ends with `.pt`, but now it's " - << model_file << std::endl; + FDERROR + << "With model format of ModelFormat::TORCHSCRIPT, the model file " + "should ends with `.pt`, but now it's " + << model_file << std::endl; return false; } } else { - FDERROR << "Only support model format with frontend ModelFormat::PADDLE / " - "ModelFormat::ONNX / ModelFormat::RKNN / ModelFormat::TORCHSCRIPT." - << std::endl; + FDERROR + << "Only support model format with frontend ModelFormat::PADDLE / " + "ModelFormat::ONNX / ModelFormat::RKNN / ModelFormat::TORCHSCRIPT." + << std::endl; return false; } return true; @@ -205,9 +207,9 @@ void RuntimeOption::SetModelPath(const std::string& model_path, model_file = model_path; model_format = ModelFormat::TORCHSCRIPT; } else { - FDASSERT( - false, - "The model format only can be ModelFormat::PADDLE/ModelFormat::ONNX/ModelFormat::TORCHSCRIPT."); + FDASSERT(false, + "The model format only can be " + "ModelFormat::PADDLE/ModelFormat::ONNX/ModelFormat::TORCHSCRIPT."); } } @@ -317,13 +319,18 @@ void RuntimeOption::EnablePaddleLogInfo() { pd_enable_log_info = true; } void RuntimeOption::DisablePaddleLogInfo() { pd_enable_log_info = false; } void RuntimeOption::EnablePaddleToTrt() { - FDASSERT(backend == Backend::TRT, "Should call UseTrtBackend() before call EnablePaddleToTrt()."); + FDASSERT(backend == Backend::TRT, + "Should call UseTrtBackend() before call EnablePaddleToTrt()."); #ifdef ENABLE_PADDLE_BACKEND - FDINFO << "While using TrtBackend with EnablePaddleToTrt, FastDeploy will change to use Paddle Inference Backend." << std::endl; + FDINFO << "While using TrtBackend with EnablePaddleToTrt, FastDeploy will " + "change to use Paddle Inference Backend." + << std::endl; backend = Backend::PDINFER; pd_enable_trt = true; #else - FDASSERT(false, "While using TrtBackend with EnablePaddleToTrt, require the FastDeploy is compiled with Paddle Inference Backend, please rebuild your FastDeploy."); + FDASSERT(false, "While using TrtBackend with EnablePaddleToTrt, require the " + "FastDeploy is compiled with Paddle Inference Backend, " + "please rebuild your FastDeploy."); #endif } @@ -336,20 +343,12 @@ void RuntimeOption::SetOpenVINODevice(const std::string& name) { openvino_device = name; } -void RuntimeOption::EnableLiteFP16() { - lite_enable_fp16 = true; -} +void RuntimeOption::EnableLiteFP16() { lite_enable_fp16 = true; } -void RuntimeOption::DisableLiteFP16() { - lite_enable_fp16 = false; -} -void RuntimeOption::EnableLiteInt8() { - lite_enable_int8 = true; -} +void RuntimeOption::DisableLiteFP16() { lite_enable_fp16 = false; } +void RuntimeOption::EnableLiteInt8() { lite_enable_int8 = true; } -void RuntimeOption::DisableLiteInt8() { - lite_enable_int8 = false; -} +void RuntimeOption::DisableLiteInt8() { lite_enable_int8 = false; } void RuntimeOption::SetLitePowerMode(LitePowerMode mode) { lite_power_mode = mode; } @@ -361,7 +360,8 @@ void RuntimeOption::SetLiteOptimizedModelDir( void RuntimeOption::SetLiteSubgraphPartitionPath( const std::string& nnadapter_subgraph_partition_config_path) { - lite_nnadapter_subgraph_partition_config_path = nnadapter_subgraph_partition_config_path; + lite_nnadapter_subgraph_partition_config_path = + nnadapter_subgraph_partition_config_path; } void RuntimeOption::SetTrtInputShape(const std::string& input_name, @@ -387,8 +387,8 @@ void RuntimeOption::SetTrtInputShape(const std::string& input_name, void RuntimeOption::SetTrtMaxWorkspaceSize(size_t max_workspace_size) { trt_max_workspace_size = max_workspace_size; } -void RuntimeOption::SetTrtMaxBatchSize(size_t max_batch_size){ - trt_max_batch_size = max_batch_size; +void RuntimeOption::SetTrtMaxBatchSize(size_t max_batch_size) { + trt_max_batch_size = max_batch_size; } void RuntimeOption::EnableTrtFP16() { trt_enable_fp16 = true; } @@ -422,27 +422,27 @@ bool Runtime::Compile(std::vector>& prewarm_tensors, poros_option.enable_fp16 = option.trt_enable_fp16; poros_option.max_batch_size = option.trt_max_batch_size; poros_option.max_workspace_size = option.trt_max_workspace_size; - FDASSERT(option.model_format == ModelFormat::TORCHSCRIPT, - "PorosBackend only support model format of ModelFormat::TORCHSCRIPT."); + FDASSERT( + option.model_format == ModelFormat::TORCHSCRIPT, + "PorosBackend only support model format of ModelFormat::TORCHSCRIPT."); backend_ = utils::make_unique(); auto casted_backend = dynamic_cast(backend_.get()); FDASSERT( casted_backend->Compile(option.model_file, prewarm_tensors, poros_option), "Load model from Torchscript failed while initliazing PorosBackend."); #else - FDASSERT(false, - "PorosBackend is not available, please compiled with " - "ENABLE_POROS_BACKEND=ON."); + FDASSERT(false, "PorosBackend is not available, please compiled with " + "ENABLE_POROS_BACKEND=ON."); #endif return true; } -void RuntimeOption::EnablePaddleTrtCollectShape() { - pd_collect_shape = true; -} +void RuntimeOption::EnablePaddleTrtCollectShape() { pd_collect_shape = true; } -void RuntimeOption::DisablePaddleTrtCollectShape() { - pd_collect_shape = false; +void RuntimeOption::DisablePaddleTrtCollectShape() { pd_collect_shape = false; } + +void RuntimeOption::DisablePaddleTrtOPs(const std::vector& ops) { + trt_disabled_ops_.insert(trt_disabled_ops_.end(), ops.begin(), ops.end()); } void RuntimeOption::UseIpu(int device_num, int micro_batch_size, @@ -519,9 +519,9 @@ bool Runtime::Init(const RuntimeOption& _option) { } else if (option.backend == Backend::POROS) { FDASSERT(option.device == Device::CPU || option.device == Device::GPU, "Backend::POROS only supports Device::CPU/Device::GPU."); - FDASSERT( - option.model_format == ModelFormat::TORCHSCRIPT, - "Backend::POROS only supports model format of ModelFormat::TORCHSCRIPT."); + FDASSERT(option.model_format == ModelFormat::TORCHSCRIPT, + "Backend::POROS only supports model format of " + "ModelFormat::TORCHSCRIPT."); FDINFO << "Runtime initialized with Backend::POROS in " << Str(option.device) << "." << std::endl; return true; @@ -572,7 +572,7 @@ std::vector Runtime::GetOutputInfos() { bool Runtime::Infer(std::vector& input_tensors, std::vector* output_tensors) { - for (auto& tensor: input_tensors) { + for (auto& tensor : input_tensors) { FDASSERT(tensor.device_id < 0 || tensor.device_id == option.device_id, "Device id of input tensor(%d) and runtime(%d) are not same.", tensor.device_id, option.device_id); @@ -589,17 +589,15 @@ void Runtime::BindInputTensor(const std::string& name, FDTensor& input) { for (auto& t : input_tensors_) { if (t.name == name) { is_exist = true; - t.SetExternalData(input.shape, input.dtype, - input.MutableData(), input.device, - input.device_id); + t.SetExternalData(input.shape, input.dtype, input.MutableData(), + input.device, input.device_id); break; } } - if(!is_exist) { + if (!is_exist) { FDTensor new_tensor(name); - new_tensor.SetExternalData(input.shape, input.dtype, - input.MutableData(), input.device, - input.device_id); + new_tensor.SetExternalData(input.shape, input.dtype, input.MutableData(), + input.device, input.device_id); input_tensors_.emplace_back(std::move(new_tensor)); } } @@ -610,6 +608,7 @@ FDTensor* Runtime::GetOutputTensor(const std::string& name) { return &t; } } + FDWARNING << "The output name [" << name << "] don't exist." << std::endl; return nullptr; } @@ -643,6 +642,7 @@ void Runtime::CreatePaddleBackend() { trt_option.serialize_file = option.trt_serialize_file; trt_option.enable_pinned_memory = option.enable_pinned_memory; pd_option.trt_option = trt_option; + pd_option.trt_disabled_ops_ = option.trt_disabled_ops_; } #endif #ifdef WITH_IPU @@ -668,9 +668,8 @@ void Runtime::CreatePaddleBackend() { pd_option), "Load model from Paddle failed while initliazing PaddleBackend."); #else - FDASSERT(false, - "PaddleBackend is not available, please compiled with " - "ENABLE_PADDLE_BACKEND=ON."); + FDASSERT(false, "PaddleBackend is not available, please compiled with " + "ENABLE_PADDLE_BACKEND=ON."); #endif } @@ -700,9 +699,8 @@ void Runtime::CreateOpenVINOBackend() { "Load model from Paddle failed while initliazing OrtBackend."); } #else - FDASSERT(false, - "OpenVINOBackend is not available, please compiled with " - "ENABLE_OPENVINO_BACKEND=ON."); + FDASSERT(false, "OpenVINOBackend is not available, please compiled with " + "ENABLE_OPENVINO_BACKEND=ON."); #endif } @@ -732,9 +730,8 @@ void Runtime::CreateOrtBackend() { "Load model from Paddle failed while initliazing OrtBackend."); } #else - FDASSERT(false, - "OrtBackend is not available, please compiled with " - "ENABLE_ORT_BACKEND=ON."); + FDASSERT(false, "OrtBackend is not available, please compiled with " + "ENABLE_ORT_BACKEND=ON."); #endif } @@ -771,9 +768,8 @@ void Runtime::CreateTrtBackend() { "Load model from Paddle failed while initliazing TrtBackend."); } #else - FDASSERT(false, - "TrtBackend is not available, please compiled with " - "ENABLE_TRT_BACKEND=ON."); + FDASSERT(false, "TrtBackend is not available, please compiled with " + "ENABLE_TRT_BACKEND=ON."); #endif } @@ -785,7 +781,8 @@ void Runtime::CreateLiteBackend() { lite_option.enable_fp16 = option.lite_enable_fp16; lite_option.power_mode = static_cast(option.lite_power_mode); lite_option.optimized_model_dir = option.lite_optimized_model_dir; - lite_option.nnadapter_subgraph_partition_config_path = option.lite_nnadapter_subgraph_partition_config_path; + lite_option.nnadapter_subgraph_partition_config_path = + option.lite_nnadapter_subgraph_partition_config_path; lite_option.enable_timvx = option.enable_timvx; FDASSERT(option.model_format == ModelFormat::PADDLE, "LiteBackend only support model format of ModelFormat::PADDLE"); @@ -795,9 +792,8 @@ void Runtime::CreateLiteBackend() { lite_option), "Load model from nb file failed while initializing LiteBackend."); #else - FDASSERT(false, - "LiteBackend is not available, please compiled with " - "ENABLE_LITE_BACKEND=ON."); + FDASSERT(false, "LiteBackend is not available, please compiled with " + "ENABLE_LITE_BACKEND=ON."); #endif } @@ -820,10 +816,8 @@ void Runtime::CreateRKNPU2Backend() { Runtime* Runtime::Clone(void* stream, int device_id) { Runtime* runtime = new Runtime(); - if (option.backend != Backend::OPENVINO - && option.backend != Backend::PDINFER - && option.backend != Backend::TRT - ) { + if (option.backend != Backend::OPENVINO && + option.backend != Backend::PDINFER && option.backend != Backend::TRT) { runtime->Init(option); FDWARNING << "Only OpenVINO/Paddle Inference/TensorRT support \ clone engine to reduce CPU/GPU memory usage now. For " @@ -833,8 +827,8 @@ Runtime* Runtime::Clone(void* stream, int device_id) { << std::endl; return runtime; } - FDINFO << "Runtime Clone with Backend:: " << Str(option.backend) << " in " << Str(option.device) - << "." << std::endl; + FDINFO << "Runtime Clone with Backend:: " << Str(option.backend) << " in " + << Str(option.device) << "." << std::endl; runtime->option = option; runtime->backend_ = backend_->Clone(stream, device_id); return runtime; diff --git a/fastdeploy/runtime.h b/fastdeploy/runtime.h old mode 100644 new mode 100755 index e96643345..9c22c929f --- a/fastdeploy/runtime.h +++ b/fastdeploy/runtime.h @@ -24,9 +24,9 @@ #include #include +#include "backends/rknpu/rknpu2/rknpu2_config.h" #include "fastdeploy/backends/backend.h" #include "fastdeploy/utils/perf.h" -#include "backends/rknpu/rknpu2/rknpu2_config.h" /** \brief All C++ FastDeploy APIs are defined inside this namespace * @@ -35,14 +35,14 @@ namespace fastdeploy { /*! Inference backend supported in FastDeploy */ enum Backend { - UNKNOWN, ///< Unknown inference backend - ORT, ///< ONNX Runtime, support Paddle/ONNX format model, CPU / Nvidia GPU - TRT, ///< TensorRT, support Paddle/ONNX format model, Nvidia GPU only + UNKNOWN, ///< Unknown inference backend + ORT, ///< ONNX Runtime, support Paddle/ONNX format model, CPU / Nvidia GPU + TRT, ///< TensorRT, support Paddle/ONNX format model, Nvidia GPU only PDINFER, ///< Paddle Inference, support Paddle format model, CPU / Nvidia GPU POROS, ///< Poros, support TorchScript format model, CPU / Nvidia GPU OPENVINO, ///< Intel OpenVINO, support Paddle/ONNX format, CPU only - LITE, ///< Paddle Lite, support Paddle format model, ARM CPU only - RKNPU2, ///< RKNPU2, support RKNN format model, Rockchip NPU only + LITE, ///< Paddle Lite, support Paddle format model, ARM CPU only + RKNPU2, ///< RKNPU2, support RKNN format model, Rockchip NPU only }; FASTDEPLOY_DECL std::ostream& operator<<(std::ostream& out, @@ -94,10 +94,10 @@ struct FASTDEPLOY_DECL RuntimeOption { /// Use Nvidia GPU to inference void UseGpu(int gpu_id = 0); - void UseRKNPU2(fastdeploy::rknpu2::CpuName rknpu2_name - = fastdeploy::rknpu2::CpuName::RK3588, - fastdeploy::rknpu2::CoreMask rknpu2_core - = fastdeploy::rknpu2::CoreMask::RKNN_NPU_CORE_0); + void UseRKNPU2(fastdeploy::rknpu2::CpuName rknpu2_name = + fastdeploy::rknpu2::CpuName::RK3588, + fastdeploy::rknpu2::CoreMask rknpu2_core = + fastdeploy::rknpu2::CoreMask::RKNN_NPU_CORE_0); /// Use TimVX to inference void UseTimVX(); @@ -116,9 +116,7 @@ struct FASTDEPLOY_DECL RuntimeOption { void UsePaddleBackend(); /// Wrapper function of UsePaddleBackend() - void UsePaddleInferBackend() { - return UsePaddleBackend(); - } + void UsePaddleInferBackend() { return UsePaddleBackend(); } /// Set ONNX Runtime as inference backend, support CPU/GPU void UseOrtBackend(); @@ -136,9 +134,7 @@ struct FASTDEPLOY_DECL RuntimeOption { void UseLiteBackend(); /// Wrapper function of UseLiteBackend() - void UsePaddleLiteBackend() { - return UseLiteBackend(); - } + void UsePaddleLiteBackend() { return UseLiteBackend(); } /// Set mkldnn switch while using Paddle Inference as inference backend void SetPaddleMKLDNN(bool pd_mkldnn = true); @@ -177,7 +173,7 @@ struct FASTDEPLOY_DECL RuntimeOption { * @brief Set shape info for OpenVINO */ void SetOpenVINOShapeInfo( - const std::map>& shape_info) { + const std::map>& shape_info) { ov_shape_infos = shape_info; } @@ -197,7 +193,7 @@ struct FASTDEPLOY_DECL RuntimeOption { * @brief Set nnadapter subgraph partition path for Paddle Lite backend. */ void SetLiteSubgraphPartitionPath( - const std::string& nnadapter_subgraph_partition_config_path); + const std::string& nnadapter_subgraph_partition_config_path); /** * @brief enable half precision while use paddle lite backend @@ -275,6 +271,11 @@ struct FASTDEPLOY_DECL RuntimeOption { */ void DisablePaddleTrtCollectShape(); + /** + * @brief Prevent ops running in paddle trt backend + */ + void DisablePaddleTrtOPs(const std::vector& ops); + /* * @brief Set number of streams by the OpenVINO backends */ @@ -361,8 +362,10 @@ struct FASTDEPLOY_DECL RuntimeOption { std::string trt_serialize_file = ""; bool trt_enable_fp16 = false; bool trt_enable_int8 = false; - size_t trt_max_batch_size = 32; + size_t trt_max_batch_size = 1; size_t trt_max_workspace_size = 1 << 30; + // ======Only for PaddleTrt Backend======= + std::vector trt_disabled_ops_{}; // ======Only for Poros Backend======= bool is_dynamic = false; @@ -378,12 +381,12 @@ struct FASTDEPLOY_DECL RuntimeOption { std::vector ov_cpu_operators; // ======Only for RKNPU2 Backend======= - fastdeploy::rknpu2::CpuName rknpu2_cpu_name_ - = fastdeploy::rknpu2::CpuName::RK3588; - fastdeploy::rknpu2::CoreMask rknpu2_core_mask_ - = fastdeploy::rknpu2::CoreMask::RKNN_NPU_CORE_AUTO; + fastdeploy::rknpu2::CpuName rknpu2_cpu_name_ = + fastdeploy::rknpu2::CpuName::RK3588; + fastdeploy::rknpu2::CoreMask rknpu2_core_mask_ = + fastdeploy::rknpu2::CoreMask::RKNN_NPU_CORE_AUTO; - std::string model_file = ""; // Path of model file + std::string model_file = ""; // Path of model file std::string params_file = ""; // Path of parameters file, can be empty // format of input model ModelFormat model_format = ModelFormat::AUTOREC; @@ -450,8 +453,7 @@ struct FASTDEPLOY_DECL Runtime { * \param[in] stream CUDA Stream, defualt param is nullptr * \return new Runtime* by this clone */ - Runtime* Clone(void* stream = nullptr, - int device_id = -1); + Runtime* Clone(void* stream = nullptr, int device_id = -1); RuntimeOption option; diff --git a/fastdeploy/text/uie/model.cc b/fastdeploy/text/uie/model.cc index 490a4a0fb..cd90db4f1 100644 --- a/fastdeploy/text/uie/model.cc +++ b/fastdeploy/text/uie/model.cc @@ -230,7 +230,7 @@ bool UIEModel::Initialize() { void UIEModel::SetValidBackend() { // TODO(zhoushunjie): Add lite backend in future - valid_cpu_backends = {Backend::ORT, Backend::OPENVINO, Backend::PDINFER}; + valid_cpu_backends = {Backend::ORT, Backend::OPENVINO, Backend::PDINFER, Backend::LITE}; valid_gpu_backends = {Backend::ORT, Backend::PDINFER, Backend::TRT}; } diff --git a/fastdeploy/utils/utils.h b/fastdeploy/utils/utils.h index 9b2a0fe20..0dff28f8b 100644 --- a/fastdeploy/utils/utils.h +++ b/fastdeploy/utils/utils.h @@ -66,7 +66,8 @@ class FASTDEPLOY_DECL FDLogger { if (!verbose_ && line_ != "") { std::cout << line_ << std::endl; #ifdef __ANDROID__ - __android_log_print(ANDROID_LOG_INFO, prefix_.c_str(), "%s", line_.c_str()); + __android_log_print(ANDROID_LOG_INFO, prefix_.c_str(), "%s", + line_.c_str()); #endif } } @@ -122,6 +123,8 @@ FASTDEPLOY_DECL bool ReadBinaryFromFile(const std::string& file, [&] { \ const auto& __dtype__ = TYPE; \ switch (__dtype__) { \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::UINT8, uint8_t, \ + __VA_ARGS__) \ FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::BOOL, bool, \ __VA_ARGS__) \ FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT32, int32_t, \ @@ -141,26 +144,26 @@ FASTDEPLOY_DECL bool ReadBinaryFromFile(const std::string& file, } \ }() -#define FD_VISIT_INT_FLOAT_TYPES(TYPE, NAME, ...) \ - [&] { \ - const auto& __dtype__ = TYPE; \ - switch (__dtype__) { \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT32, int32_t, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT64, int64_t, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::FP32, float, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::FP64, double, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::UINT8, uint8_t, \ - __VA_ARGS__) \ - default: \ - FDASSERT(false, \ - "Invalid enum data type. Expect to accept data type INT32, " \ - "INT64, FP32, FP64, UINT8 but receive type %s.", \ - Str(__dtype__).c_str()); \ - } \ +#define FD_VISIT_INT_FLOAT_TYPES(TYPE, NAME, ...) \ + [&] { \ + const auto& __dtype__ = TYPE; \ + switch (__dtype__) { \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT32, int32_t, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT64, int64_t, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::FP32, float, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::FP64, double, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::UINT8, uint8_t, \ + __VA_ARGS__) \ + default: \ + FDASSERT(false, \ + "Invalid enum data type. Expect to accept data type INT32, " \ + "INT64, FP32, FP64, UINT8 but receive type %s.", \ + Str(__dtype__).c_str()); \ + } \ }() #define FD_VISIT_FLOAT_TYPES(TYPE, NAME, ...) \ @@ -179,22 +182,22 @@ FASTDEPLOY_DECL bool ReadBinaryFromFile(const std::string& file, } \ }() -#define FD_VISIT_INT_TYPES(TYPE, NAME, ...) \ - [&] { \ - const auto& __dtype__ = TYPE; \ - switch (__dtype__) { \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT32, int32_t, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT64, int64_t, \ - __VA_ARGS__) \ - FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::UINT8, uint8_t, \ - __VA_ARGS__) \ - default: \ - FDASSERT(false, \ - "Invalid enum data type. Expect to accept data type INT32, " \ - "INT64, UINT8 but receive type %s.", \ - Str(__dtype__).c_str()); \ - } \ +#define FD_VISIT_INT_TYPES(TYPE, NAME, ...) \ + [&] { \ + const auto& __dtype__ = TYPE; \ + switch (__dtype__) { \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT32, int32_t, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::INT64, int64_t, \ + __VA_ARGS__) \ + FD_PRIVATE_CASE_TYPE(NAME, ::fastdeploy::FDDataType::UINT8, uint8_t, \ + __VA_ARGS__) \ + default: \ + FDASSERT(false, \ + "Invalid enum data type. Expect to accept data type INT32, " \ + "INT64, UINT8 but receive type %s.", \ + Str(__dtype__).c_str()); \ + } \ }() FASTDEPLOY_DECL std::vector diff --git a/fastdeploy/vision.h b/fastdeploy/vision.h index 9bea1550e..5ccaeb2dd 100644 --- a/fastdeploy/vision.h +++ b/fastdeploy/vision.h @@ -28,6 +28,7 @@ #include "fastdeploy/vision/detection/contrib/yolov7end2end_ort.h" #include "fastdeploy/vision/detection/contrib/yolov7end2end_trt.h" #include "fastdeploy/vision/detection/contrib/yolox.h" +#include "fastdeploy/vision/detection/contrib/rknpu2/model.h" #include "fastdeploy/vision/detection/ppdet/model.h" #include "fastdeploy/vision/facealign/contrib/face_landmark_1000.h" #include "fastdeploy/vision/facealign/contrib/pfld.h" diff --git a/fastdeploy/vision/detection/contrib/rknpu2/model.h b/fastdeploy/vision/detection/contrib/rknpu2/model.h new file mode 100644 index 000000000..9a0fd423d --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/model.h @@ -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. + +#pragma once +#include "fastdeploy/vision/detection/contrib/rknpu2/rkyolo.h" +namespace fastdeploy { +namespace vision { +namespace detection { + +class FASTDEPLOY_DECL RKYOLOV5 : public RKYOLO { + 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 picodet/model.pdmodel + * \param[in] params_file Path of parameter file, e.g picodet/model.pdiparams, if the model format is ONNX, this parameter will be ignored + * \param[in] config_file Path of configuration file for deployment, e.g picodet/infer_cfg.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 + */ + RKYOLOV5(const std::string& model_file, + const RuntimeOption& custom_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::RKNN) + : RKYOLO(model_file, custom_option, model_format) { + valid_cpu_backends = {}; + valid_gpu_backends = {}; + valid_rknpu_backends = {Backend::RKNPU2}; + GetPostprocessor().SetModelType(ModelType::RKYOLOV5); + } + + virtual std::string ModelName() const { return "RKYOLOV5"; } +}; + +class FASTDEPLOY_DECL RKYOLOV7 : public RKYOLO { + 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 picodet/model.pdmodel + * \param[in] params_file Path of parameter file, e.g picodet/model.pdiparams, if the model format is ONNX, this parameter will be ignored + * \param[in] config_file Path of configuration file for deployment, e.g picodet/infer_cfg.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 + */ + RKYOLOV7(const std::string& model_file, + const RuntimeOption& custom_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::RKNN) + : RKYOLO(model_file, custom_option, model_format) { + valid_cpu_backends = {}; + valid_gpu_backends = {}; + valid_rknpu_backends = {Backend::RKNPU2}; + GetPostprocessor().SetModelType(ModelType::RKYOLOV7); + } + + virtual std::string ModelName() const { return "RKYOLOV7"; } +}; + +class FASTDEPLOY_DECL RKYOLOX : public RKYOLO { + 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 picodet/model.pdmodel + * \param[in] params_file Path of parameter file, e.g picodet/model.pdiparams, if the model format is ONNX, this parameter will be ignored + * \param[in] config_file Path of configuration file for deployment, e.g picodet/infer_cfg.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 + */ + RKYOLOX(const std::string& model_file, + const RuntimeOption& custom_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::RKNN) + : RKYOLO(model_file, custom_option, model_format) { + valid_cpu_backends = {}; + valid_gpu_backends = {}; + valid_rknpu_backends = {Backend::RKNPU2}; + GetPostprocessor().SetModelType(ModelType::RKYOLOX); + } + + virtual std::string ModelName() const { return "RKYOLOV7"; } +}; + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.cc b/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.cc new file mode 100755 index 000000000..bb46eff5c --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.cc @@ -0,0 +1,239 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2 (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 +// +// 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/detection/contrib/rknpu2/postprocessor.h" +#include "fastdeploy/vision/utils/utils.h" + +namespace fastdeploy { +namespace vision { +namespace detection { + +RKYOLOPostprocessor::RKYOLOPostprocessor() {} + +void RKYOLOPostprocessor::SetModelType(ModelType model_type) { + model_type_ = model_type; + if (model_type == RKYOLOV5) { + anchors_ = {10, 13, 16, 30, 33, 23, 30, 61, 62, + 45, 59, 119, 116, 90, 156, 198, 373, 326}; + anchor_per_branch_ = 3; + } else if (model_type == RKYOLOX) { + anchors_ = {10, 13, 16, 30, 33, 23, 30, 61, 62, + 45, 59, 119, 116, 90, 156, 198, 373, 326}; + anchor_per_branch_ = 1; + } else if (model_type == RKYOLOV7) { + anchors_ = {12, 16, 19, 36, 40, 28, 36, 75, 76, + 55, 72, 146, 142, 110, 192, 243, 459, 401}; + anchor_per_branch_ = 3; + } else { + return; + } +} + +bool RKYOLOPostprocessor::Run(const std::vector& tensors, + std::vector* results) { + if (model_type_ == ModelType::UNKNOWN) { + FDERROR << "RKYOLO Only Support YOLOV5,YOLOV7,YOLOX" << std::endl; + return false; + } + + results->resize(tensors[0].shape[0]); + for (int num = 0; num < tensors[0].shape[0]; ++num) { + int validCount = 0; + std::vector filterBoxes; + std::vector boxesScore; + std::vector classId; + for (int i = 0; i < tensors.size(); i++) { + auto tensor_shape = tensors[i].shape; + auto skip_num = std::accumulate(tensor_shape.begin(), tensor_shape.end(), + 1, std::multiplies()); + int skip_address = num * skip_num; + int stride = strides_[i]; + int grid_h = height_ / stride; + int grid_w = width_ / stride; + int* anchor = &(anchors_.data()[i * 2 * anchor_per_branch_]); + if (tensors[i].dtype == FDDataType::INT8 || tensors[i].dtype == FDDataType::UINT8) { + auto quantization_info = tensors[i].GetQuantizationInfo(); + validCount = validCount + + ProcessInt8((int8_t*)tensors[i].Data() + skip_address, + anchor, grid_h, grid_w, stride, filterBoxes, + boxesScore, classId, conf_threshold_, + quantization_info.first, quantization_info.second[0]); + } else { + FDERROR << "RKYOLO Only Support INT8 Model" << std::endl; + } + } + + // no object detect + if (validCount <= 0) { + FDINFO << "The number of object detect is 0." << std::endl; + return true; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) { + indexArray.push_back(i); + } + + QuickSortIndiceInverse(boxesScore, 0, validCount - 1, indexArray); + + if (model_type_ == RKYOLOV5 || model_type_ == RKYOLOV7) { + NMS(validCount, filterBoxes, classId, indexArray, nms_threshold_, false); + } else if (model_type_ == RKYOLOX) { + NMS(validCount, filterBoxes, classId, indexArray, nms_threshold_, true); + } + + int last_count = 0; + (*results)[num].Clear(); + (*results)[num].Reserve(validCount); + + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) { + if (indexArray[i] == -1 || boxesScore[i] < conf_threshold_ || + last_count >= obj_num_bbox_max_size) { + continue; + } + int n = indexArray[i]; + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + (*results)[num].boxes.emplace_back(std::array{ + (float)((clamp(x1, 0, width_) - pad_hw_values_[num][1] / 2) / + scale_[num]), + (float)((clamp(y1, 0, height_) - pad_hw_values_[num][0] / 2) / + scale_[num]), + (float)((clamp(x2, 0, width_) - pad_hw_values_[num][1] / 2) / + scale_[num]), + (float)((clamp(y2, 0, height_) - pad_hw_values_[num][0] / 2) / + scale_[0])}); + (*results)[num].label_ids.push_back(id); + (*results)[num].scores.push_back(boxesScore[i]); + last_count++; + } + std::cout << "last_count" << last_count << std::endl; + } + return true; +} + +int RKYOLOPostprocessor::ProcessInt8(int8_t* input, int* anchor, int grid_h, + int grid_w, int stride, + std::vector& boxes, + std::vector& boxScores, + std::vector& classId, float threshold, + int32_t zp, float scale) { + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = threshold; + auto thres_i8 = QntF32ToAffine(thres, zp, scale); + for (int a = 0; a < anchor_per_branch_; a++) { + for (int i = 0; i < grid_h; i++) { + for (int j = 0; j < grid_w; j++) { + int8_t box_confidence = + input[(prob_box_size * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_i8) { + int offset = (prob_box_size * a) * grid_len + i * grid_w + j; + int8_t* in_ptr = input + offset; + + int8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < obj_class_num; ++k) { + int8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) { + maxClassId = k; + maxClassProbs = prob; + } + } + + float box_conf_f32 = DeqntAffineToF32(box_confidence, zp, scale); + float class_prob_f32 = DeqntAffineToF32(maxClassProbs, zp, scale); + float limit_score = 0; + if (model_type_ == RKYOLOX) { + limit_score = box_conf_f32 * class_prob_f32; + } else { + limit_score = class_prob_f32; + } + //printf("limit score: %f\n", limit_score); + if (limit_score > conf_threshold_) { + float box_x, box_y, box_w, box_h; + if (model_type_ == RKYOLOX) { + box_x = DeqntAffineToF32(*in_ptr, zp, scale); + box_y = DeqntAffineToF32(in_ptr[grid_len], zp, scale); + box_w = DeqntAffineToF32(in_ptr[2 * grid_len], zp, scale); + box_h = DeqntAffineToF32(in_ptr[3 * grid_len], zp, scale); + box_w = exp(box_w) * stride; + box_h = exp(box_h) * stride; + } else { + box_x = DeqntAffineToF32(*in_ptr, zp, scale) * 2.0 - 0.5; + box_y = DeqntAffineToF32(in_ptr[grid_len], zp, scale) * 2.0 - 0.5; + box_w = DeqntAffineToF32(in_ptr[2 * grid_len], zp, scale) * 2.0; + box_h = DeqntAffineToF32(in_ptr[3 * grid_len], zp, scale) * 2.0; + box_w = box_w * box_w; + box_h = box_h * box_h; + } + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w *= (float)anchor[a * 2]; + box_h *= (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + boxScores.push_back(box_conf_f32 * class_prob_f32); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + } + return validCount; +} + +int RKYOLOPostprocessor::QuickSortIndiceInverse(std::vector& input, + int left, int right, + std::vector& indices) { + float key; + int key_index; + int low = left; + int high = right; + if (left < right) { + key_index = indices[left]; + key = input[left]; + while (low < high) { + while (low < high && input[high] <= key) { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + QuickSortIndiceInverse(input, left, low - 1, indices); + QuickSortIndiceInverse(input, low + 1, right, indices); + } + return low; +} + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.h b/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.h new file mode 100755 index 000000000..0332b2efd --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/postprocessor.h @@ -0,0 +1,105 @@ +// 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" +#include "fastdeploy/vision/detection/contrib/rknpu2/utils.h" +#include +namespace fastdeploy { +namespace vision { +namespace detection { +/*! @brief Postprocessor object for YOLOv5 serials model. + */ +class FASTDEPLOY_DECL RKYOLOPostprocessor { + public: + /** \brief Create a postprocessor instance for YOLOv5 serials model + */ + RKYOLOPostprocessor(); + + /** \brief Process the result of runtime and fill to DetectionResult 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& tensors, + std::vector* results); + + /// Set nms_threshold, default 0.45 + void SetNMSThreshold(const float& nms_threshold) { + nms_threshold_ = nms_threshold; + } + + /// Set conf_threshold, default 0.25 + void SetConfThreshold(const float& conf_threshold) { + conf_threshold_ = conf_threshold; + } + + /// Get conf_threshold, default 0.25 + float GetConfThreshold() const { return conf_threshold_; } + + /// Get nms_threshold, default 0.45 + float GetNMSThreshold() const { return nms_threshold_; } + + // Set model_type + void SetModelType(ModelType model_type); + + // Set height and weight + void SetHeightAndWeight(int& height, int& width) { + height_ = height; + width_ = width; + } + + // Set pad_hw_values + void SetPadHWValues(std::vector> pad_hw_values) { + pad_hw_values_ = pad_hw_values; + } + + // Set scale + void SetScale(std::vector scale) { scale_ = scale; } + + private: + ModelType model_type_ = ModelType::UNKNOWN; + std::vector anchors_ = {10, 13, 16, 30, 33, 23, 30, 61, 62, + 45, 59, 119, 116, 90, 156, 198, 373, 326}; + int strides_[3] = {8, 16, 32}; + int height_ = 0; + int width_ = 0; + int anchor_per_branch_ = 0; + + // Process Int8 Model + int ProcessInt8(int8_t* input, int* anchor, int grid_h, int grid_w, + int stride, std::vector& boxes, + std::vector& boxScores, std::vector& classId, + float threshold, int32_t zp, float scale); + + // Model + int QuickSortIndiceInverse(std::vector& input, int left, int right, + std::vector& indices); + + // post_process values + std::vector> pad_hw_values_; + std::vector scale_; + float nms_threshold_ = 0.45; + float conf_threshold_ = 0.25; + int prob_box_size = 85; + int obj_class_num = 80; + int obj_num_bbox_max_size = 200; +}; + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.cc b/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.cc new file mode 100755 index 000000000..29480459b --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.cc @@ -0,0 +1,127 @@ +// 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/detection/contrib/rknpu2/preprocessor.h" +#include "fastdeploy/function/concat.h" + +namespace fastdeploy { +namespace vision { +namespace detection { + +RKYOLOPreprocessor::RKYOLOPreprocessor() { + size_ = {640, 640}; + padding_value_ = {114.0, 114.0, 114.0}; + is_mini_pad_ = false; + is_no_pad_ = false; + is_scale_up_ = true; + stride_ = 32; + max_wh_ = 7680.0; +} + +void RKYOLOPreprocessor::LetterBox(FDMat* mat) { + std::cout << "mat->Height() = " << mat->Height() << std::endl; + std::cout << "mat->Width() = " << mat->Width() << std::endl; + + float scale = + std::min(size_[1] * 1.0 / mat->Height(), size_[0] * 1.0 / mat->Width()); + std::cout << "RKYOLOPreprocessor scale_ = " << scale << std::endl; + if (!is_scale_up_) { + scale = std::min(scale, 1.0f); + } + std::cout << "RKYOLOPreprocessor scale_ = " << scale << std::endl; + scale_.push_back(scale); + + int resize_h = int(round(mat->Height() * scale)); + int resize_w = int(round(mat->Width() * scale)); + + int pad_w = size_[0] - resize_w; + int pad_h = size_[1] - resize_h; + if (is_mini_pad_) { + pad_h = pad_h % stride_; + pad_w = pad_w % stride_; + } else if (is_no_pad_) { + pad_h = 0; + pad_w = 0; + resize_h = size_[1]; + resize_w = size_[0]; + } + + pad_hw_values_.push_back({pad_h,pad_w}); + + if (std::fabs(scale - 1.0f) > 1e-06) { + Resize::Run(mat, resize_w, resize_h); + } + if (pad_h > 0 || pad_w > 0) { + float half_h = pad_h * 1.0 / 2; + int top = int(round(half_h - 0.1)); + int bottom = int(round(half_h + 0.1)); + float half_w = pad_w * 1.0 / 2; + int left = int(round(half_w - 0.1)); + int right = int(round(half_w + 0.1)); + Pad::Run(mat, top, bottom, left, right, padding_value_); + } +} + +bool RKYOLOPreprocessor::Preprocess(FDMat* mat, FDTensor* output) { + // process after image load +// float ratio = std::min(size_[1] * 1.0f / static_cast(mat->Height()), +// size_[0] * 1.0f / static_cast(mat->Width())); +// if (std::fabs(ratio - 1.0f) > 1e-06) { +// int interp = cv::INTER_AREA; +// if (ratio > 1.0) { +// interp = cv::INTER_LINEAR; +// } +// int resize_h = int(mat->Height() * ratio); +// int resize_w = int(mat->Width() * ratio); +// Resize::Run(mat, resize_w, resize_h, -1, -1, interp); +// } + + // RKYOLO's preprocess steps + // 1. letterbox + // 2. convert_and_permute(swap_rb=true) + LetterBox(mat); + BGR2RGB::Run(mat); + mat->ShareWithTensor(output); + output->ExpandDim(0); // reshape to n, h, w, c + return true; +} + +bool RKYOLOPreprocessor::Run(std::vector* images, + std::vector* outputs) { + if (images->size() == 0) { + FDERROR << "The size of input images should be greater than 0." + << std::endl; + return false; + } + outputs->resize(1); + // Concat all the preprocessed data to a batch tensor + std::vector tensors(images->size()); + for (size_t i = 0; i < images->size(); ++i) { + if (!Preprocess(&(*images)[i], &tensors[i])) { + FDERROR << "Failed to preprocess input image." << std::endl; + return false; + } + } + + if (tensors.size() == 1) { + (*outputs)[0] = std::move(tensors[0]); + } else { + function::Concat(tensors, &((*outputs)[0]), 0); + } + return true; +} + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.h b/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.h new file mode 100755 index 000000000..e6ecfe452 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/preprocessor.h @@ -0,0 +1,100 @@ +// 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 detection { +/*! @brief Preprocessor object for YOLOv5 serials model. + */ +class FASTDEPLOY_DECL RKYOLOPreprocessor { + public: + /** \brief Create a preprocessor instance for YOLOv5 serials model + */ + RKYOLOPreprocessor(); + + /** \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 Run(std::vector* images, std::vector* outputs); + + /// Set target size, tuple of (width, height), default size = {640, 640} + void SetSize(const std::vector& size) { size_ = size; } + + /// Get target size, tuple of (width, height), default size = {640, 640} + std::vector GetSize() const { return size_; } + + /// Set padding value, size should be the same as channels + void SetPaddingValue(const std::vector& padding_value) { + padding_value_ = padding_value; + } + + /// Get padding value, size should be the same as channels + std::vector GetPaddingValue() const { return padding_value_; } + + /// Set is_scale_up, if is_scale_up is false, the input image only + /// can be zoom out, the maximum resize scale cannot exceed 1.0, default true + void SetScaleUp(bool is_scale_up) { is_scale_up_ = is_scale_up; } + + /// Get is_scale_up, default true + bool GetScaleUp() const { return is_scale_up_; } + + std::vector> GetPadHWValues() const { + return pad_hw_values_; + } + std::vector GetScale() const { return scale_; } + + protected: + bool Preprocess(FDMat* mat, FDTensor* output); + + void LetterBox(FDMat* mat); + + // target size, tuple of (width, height), default size = {640, 640} + std::vector size_; + + // padding value, size should be the same as channels + std::vector padding_value_; + + // only pad to the minimum rectange which height and width is times of stride + bool is_mini_pad_; + + // while is_mini_pad = false and is_no_pad = true, + // will resize the image to the set size + bool is_no_pad_; + + // if is_scale_up is false, the input image only can be zoom out, + // the maximum resize scale cannot exceed 1.0 + bool is_scale_up_; + + // padding stride, for is_mini_pad + int stride_; + + // for offseting the boxes by classes when using NMS + float max_wh_; + + std::vector> pad_hw_values_; + std::vector scale_; +}; + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.cc b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.cc new file mode 100644 index 000000000..017cb1be3 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.cc @@ -0,0 +1,73 @@ +#include "fastdeploy/vision/detection/contrib/rknpu2/rkyolo.h" + +namespace fastdeploy { +namespace vision { +namespace detection { + +RKYOLO::RKYOLO(const std::string& model_file, + const fastdeploy::RuntimeOption& custom_option, + const fastdeploy::ModelFormat& model_format) { + if (model_format == ModelFormat::RKNN) { + valid_cpu_backends = {}; + valid_gpu_backends = {}; + valid_rknpu_backends = {Backend::RKNPU2}; + } else { + FDERROR << "RKYOLO Only Support run in RKNPU2" << std::endl; + } + runtime_option = custom_option; + runtime_option.model_format = model_format; + runtime_option.model_file = model_file; + initialized = Initialize(); +} + +bool RKYOLO::Initialize() { + if (!InitRuntime()) { + FDERROR << "Failed to initialize fastdeploy backend." << std::endl; + return false; + } + auto size = GetPreprocessor().GetSize(); + GetPostprocessor().SetHeightAndWeight(size[0],size[1]); + return true; +} + +bool RKYOLO::Predict(const cv::Mat& im, + DetectionResult* result) { + std::vector results; + if (!BatchPredict({im}, &results)) { + return false; + } + *result = std::move(results[0]); + return true; +} + +bool RKYOLO::BatchPredict(const std::vector& images, + std::vector* results) { + std::vector fd_images = WrapMat(images); + + if (!preprocessor_.Run(&fd_images, &reused_input_tensors_)) { + FDERROR << "Failed to preprocess the input image." << std::endl; + return false; + } + auto pad_hw_values_ = preprocessor_.GetPadHWValues(); + postprocessor_.SetPadHWValues(preprocessor_.GetPadHWValues()); + std::cout << "preprocessor_ scale_ = " << preprocessor_.GetScale()[0] << std::endl; + postprocessor_.SetScale(preprocessor_.GetScale()); + + 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 detection +} // namespace vision +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.h b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.h new file mode 100644 index 000000000..d7190eb73 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo.h @@ -0,0 +1,64 @@ +// 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/detection/contrib/rknpu2/postprocessor.h" +#include "fastdeploy/vision/detection/contrib/rknpu2/preprocessor.h" + +namespace fastdeploy { +namespace vision { +namespace detection { + +class FASTDEPLOY_DECL RKYOLO : public FastDeployModel { + public: + RKYOLO(const std::string& model_file, + const RuntimeOption& custom_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::RKNN); + + std::string ModelName() const { return "RKYOLO"; } + + /** \brief Predict the detection 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 detection result will be writen to this structure + * \return true if the prediction successed, otherwise false + */ + virtual bool Predict(const cv::Mat& img, DetectionResult* result); + + /** \brief Predict the detection 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 detection result list + * \return true if the prediction successed, otherwise false + */ + virtual bool BatchPredict(const std::vector& imgs, + std::vector* results); + + /// Get preprocessor reference of YOLOv5 + RKYOLOPreprocessor& GetPreprocessor() { return preprocessor_; } + + /// Get postprocessor reference of YOLOv5 + RKYOLOPostprocessor& GetPostprocessor() { return postprocessor_; } + + protected: + bool Initialize(); + RKYOLOPreprocessor preprocessor_; + RKYOLOPostprocessor postprocessor_; +}; + +} // namespace detection +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/rkyolo_pybind.cc b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo_pybind.cc new file mode 100755 index 000000000..716464458 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/rkyolo_pybind.cc @@ -0,0 +1,95 @@ +// 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 BindRKYOLO(pybind11::module& m) { + pybind11::class_( + m, "RKYOLOPreprocessor") + .def(pybind11::init<>()) + .def("run", [](vision::detection::RKYOLOPreprocessor& self, + std::vector& im_list) { + std::vector images; + for (size_t i = 0; i < im_list.size(); ++i) { + images.push_back(vision::WrapMat(PyArrayToCvMat(im_list[i]))); + } + std::vector outputs; + if (!self.Run(&images, &outputs)) { + throw std::runtime_error("Failed to preprocess the input data in PaddleClasPreprocessor."); + } + for (size_t i = 0; i < outputs.size(); ++i) { + outputs[i].StopSharing(); + } + return outputs; + }) + .def_property("size", &vision::detection::RKYOLOPreprocessor::GetSize, + &vision::detection::RKYOLOPreprocessor::SetSize) + .def_property("padding_value", &vision::detection::RKYOLOPreprocessor::GetPaddingValue, + &vision::detection::RKYOLOPreprocessor::SetPaddingValue) + .def_property("is_scale_up", &vision::detection::RKYOLOPreprocessor::GetScaleUp, + &vision::detection::RKYOLOPreprocessor::SetScaleUp); + + pybind11::class_( + m, "RKYOLOPostprocessor") + .def(pybind11::init<>()) + .def("run", [](vision::detection::RKYOLOPostprocessor& self, + std::vector& inputs) { + std::vector results; + if (!self.Run(inputs, &results)) { + throw std::runtime_error("Failed to postprocess the runtime result in RKYOLOV5Postprocessor."); + } + return results; + }) + .def("run", [](vision::detection::RKYOLOPostprocessor& self, + std::vector& input_array) { + std::vector results; + std::vector inputs; + PyArrayToTensorList(input_array, &inputs, /*share_buffer=*/true); + if (!self.Run(inputs, &results)) { + throw std::runtime_error("Failed to postprocess the runtime result in RKYOLOV5Postprocessor."); + } + return results; + }) + .def_property("conf_threshold", &vision::detection::RKYOLOPostprocessor::GetConfThreshold, + &vision::detection::RKYOLOPostprocessor::SetConfThreshold) + .def_property("nms_threshold", &vision::detection::RKYOLOPostprocessor::GetNMSThreshold, + &vision::detection::RKYOLOPostprocessor::SetNMSThreshold); + + pybind11::class_(m, "RKYOLOV5") + .def(pybind11::init()) + .def("predict", + [](vision::detection::RKYOLOV5& self, + pybind11::array& data) { + auto mat = PyArrayToCvMat(data); + vision::DetectionResult res; + self.Predict(mat, &res); + return res; + }) + .def("batch_predict", [](vision::detection::RKYOLOV5& self, + std::vector& data) { + std::vector images; + for (size_t i = 0; i < data.size(); ++i) { + images.push_back(PyArrayToCvMat(data[i])); + } + std::vector results; + self.BatchPredict(images, &results); + return results; + }) + .def_property_readonly("preprocessor", &vision::detection::RKYOLOV5::GetPreprocessor) + .def_property_readonly("postprocessor", &vision::detection::RKYOLOV5::GetPostprocessor); +} +} // namespace fastdeploy diff --git a/fastdeploy/vision/detection/contrib/rknpu2/utils.cc b/fastdeploy/vision/detection/contrib/rknpu2/utils.cc new file mode 100644 index 000000000..faac26983 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/utils.cc @@ -0,0 +1,93 @@ +// 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. +#include "fastdeploy/vision/detection/contrib/rknpu2/utils.h" +float clamp(float val, int min, int max) { + return val > min ? (val < max ? val : max) : min; +} + +float Sigmoid(float x) { return 1.0 / (1.0 + expf(-x)); } + +float UnSigmoid(float y) { return -1.0 * logf((1.0 / y) - 1.0); } + +inline int32_t __clip(float val, float min, float max) { + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +int8_t QntF32ToAffine(float f32, int32_t zp, float scale) { + float dst_val = (f32 / scale) + zp; + int8_t res = (int8_t)__clip(dst_val, -128, 127); + return res; +} + +float DeqntAffineToF32(int8_t qnt, int32_t zp, float scale) { + return ((float)qnt - (float)zp) * scale; +} + +static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1) + 1.0); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1) + 1.0); + float i = w * h; + float u = (xmax0 - xmin0 + 1.0) * (ymax0 - ymin0 + 1.0) + (xmax1 - xmin1 + 1.0) * (ymax1 - ymin1 + 1.0) - i; + return u <= 0.f ? 0.f : (i / u); +} + +int NMS(int validCount, + std::vector &outputLocations, + std::vector &class_id, + std::vector &order, + float threshold, + bool class_agnostic) +{ + // printf("class_agnostic: %d\n", class_agnostic); + for (int i = 0; i < validCount; ++i) + { + if (order[i] == -1) + { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) + { + int m = order[j]; + if (m == -1) + { + continue; + } + + if (!class_agnostic && class_id[n] != class_id[m]){ + continue; + } + + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) + { + order[j] = -1; + } + } + } + return 0; +} \ No newline at end of file diff --git a/fastdeploy/vision/detection/contrib/rknpu2/utils.h b/fastdeploy/vision/detection/contrib/rknpu2/utils.h new file mode 100644 index 000000000..4414cb8a5 --- /dev/null +++ b/fastdeploy/vision/detection/contrib/rknpu2/utils.h @@ -0,0 +1,26 @@ +// 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 +#include +typedef enum { RKYOLOX = 0, RKYOLOV5, RKYOLOV7, UNKNOWN } ModelType; +float clamp(float val, int min, int max); +float Sigmoid(float x); +float UnSigmoid(float y); +inline static int32_t __clip(float val, float min, float max); +int8_t QntF32ToAffine(float f32, int32_t zp, float scale); +float DeqntAffineToF32(int8_t qnt, int32_t zp, float scale); +int NMS(int validCount, std::vector& outputLocations, + std::vector& class_id, std::vector& order, float threshold, + bool class_agnostic); diff --git a/fastdeploy/vision/detection/contrib/yolov5/yolov5.cc b/fastdeploy/vision/detection/contrib/yolov5/yolov5.cc index 422cf501c..92d53dd10 100755 --- a/fastdeploy/vision/detection/contrib/yolov5/yolov5.cc +++ b/fastdeploy/vision/detection/contrib/yolov5/yolov5.cc @@ -27,6 +27,7 @@ YOLOv5::YOLOv5(const std::string& model_file, const std::string& params_file, } else { valid_cpu_backends = {Backend::PDINFER, Backend::ORT, Backend::LITE}; valid_gpu_backends = {Backend::PDINFER, Backend::ORT, Backend::TRT}; + valid_timvx_backends = {Backend::LITE}; } runtime_option = custom_option; runtime_option.model_format = model_format; diff --git a/fastdeploy/vision/detection/detection_pybind.cc b/fastdeploy/vision/detection/detection_pybind.cc index b3a7a6ad9..9d585e18c 100644 --- a/fastdeploy/vision/detection/detection_pybind.cc +++ b/fastdeploy/vision/detection/detection_pybind.cc @@ -27,6 +27,7 @@ void BindNanoDetPlus(pybind11::module& m); void BindPPDet(pybind11::module& m); void BindYOLOv7End2EndTRT(pybind11::module& m); void BindYOLOv7End2EndORT(pybind11::module& m); +void BindRKYOLO(pybind11::module& m); void BindDetection(pybind11::module& m) { auto detection_module = @@ -42,5 +43,6 @@ void BindDetection(pybind11::module& m) { BindNanoDetPlus(detection_module); BindYOLOv7End2EndTRT(detection_module); BindYOLOv7End2EndORT(detection_module); + BindRKYOLO(detection_module); } } // namespace fastdeploy diff --git a/fastdeploy/vision/detection/ppdet/model.h b/fastdeploy/vision/detection/ppdet/model.h old mode 100644 new mode 100755 index a686198eb..44f574435 --- a/fastdeploy/vision/detection/ppdet/model.h +++ b/fastdeploy/vision/detection/ppdet/model.h @@ -64,6 +64,7 @@ class FASTDEPLOY_DECL PPYOLOE : public PPDetBase { valid_cpu_backends = {Backend::OPENVINO, Backend::ORT, Backend::PDINFER, Backend::LITE}; valid_gpu_backends = {Backend::ORT, Backend::PDINFER, Backend::TRT}; + valid_timvx_backends = {Backend::LITE}; initialized = Initialize(); } diff --git a/fastdeploy/vision/ocr/ppocr/classifier.cc b/fastdeploy/vision/ocr/ppocr/classifier.cc index 130329735..216d50fd2 100755 --- a/fastdeploy/vision/ocr/ppocr/classifier.cc +++ b/fastdeploy/vision/ocr/ppocr/classifier.cc @@ -50,10 +50,29 @@ bool Classifier::Initialize() { return true; } +bool Classifier::Predict(const cv::Mat& img, int32_t* cls_label, float* cls_score) { + std::vector cls_labels(1); + std::vector cls_scores(1); + bool success = BatchPredict({img}, &cls_labels, &cls_scores); + if(!success){ + return success; + } + *cls_label = cls_labels[0]; + *cls_score = cls_scores[0]; + return true; +} + bool Classifier::BatchPredict(const std::vector& images, std::vector* cls_labels, std::vector* cls_scores) { + return BatchPredict(images, cls_labels, cls_scores, 0, images.size()); +} + +bool Classifier::BatchPredict(const std::vector& images, + std::vector* cls_labels, std::vector* cls_scores, + size_t start_index, size_t end_index) { + size_t total_size = images.size(); std::vector fd_images = WrapMat(images); - if (!preprocessor_.Run(&fd_images, &reused_input_tensors_)) { + if (!preprocessor_.Run(&fd_images, &reused_input_tensors_, start_index, end_index)) { FDERROR << "Failed to preprocess the input image." << std::endl; return false; } @@ -63,7 +82,7 @@ bool Classifier::BatchPredict(const std::vector& images, return false; } - if (!postprocessor_.Run(reused_output_tensors_, cls_labels, cls_scores)) { + if (!postprocessor_.Run(reused_output_tensors_, cls_labels, cls_scores, start_index, total_size)) { FDERROR << "Failed to postprocess the inference cls_results by runtime." << std::endl; return false; } diff --git a/fastdeploy/vision/ocr/ppocr/classifier.h b/fastdeploy/vision/ocr/ppocr/classifier.h index d3430e4e0..5a4ed02a0 100755 --- a/fastdeploy/vision/ocr/ppocr/classifier.h +++ b/fastdeploy/vision/ocr/ppocr/classifier.h @@ -43,7 +43,7 @@ class FASTDEPLOY_DECL Classifier : public FastDeployModel { const ModelFormat& model_format = ModelFormat::PADDLE); /// Get model's name std::string ModelName() const { return "ppocr/ocr_cls"; } - + virtual bool Predict(const cv::Mat& img, int32_t* cls_label, float* cls_score); /** \brief BatchPredict the input image and get OCR classification model cls_result. * * \param[in] images The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. @@ -53,6 +53,10 @@ class FASTDEPLOY_DECL Classifier : public FastDeployModel { virtual bool BatchPredict(const std::vector& images, std::vector* cls_labels, std::vector* cls_scores); + virtual bool BatchPredict(const std::vector& images, + std::vector* cls_labels, + std::vector* cls_scores, + size_t start_index, size_t end_index); ClassifierPreprocessor preprocessor_; ClassifierPostprocessor postprocessor_; diff --git a/fastdeploy/vision/ocr/ppocr/cls_postprocessor.cc b/fastdeploy/vision/ocr/ppocr/cls_postprocessor.cc index 5eb6b5d69..c19bcc3a6 100644 --- a/fastdeploy/vision/ocr/ppocr/cls_postprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/cls_postprocessor.cc @@ -20,10 +20,6 @@ namespace fastdeploy { namespace vision { namespace ocr { -ClassifierPostprocessor::ClassifierPostprocessor() { - initialized_ = true; -} - bool SingleBatchPostprocessor(const float* out_data, const size_t& length, int* cls_label, float* cls_score) { *cls_label = std::distance( @@ -37,10 +33,14 @@ bool SingleBatchPostprocessor(const float* out_data, const size_t& length, int* bool ClassifierPostprocessor::Run(const std::vector& tensors, std::vector* cls_labels, std::vector* cls_scores) { - if (!initialized_) { - FDERROR << "Postprocessor is not initialized." << std::endl; - return false; - } + size_t total_size = tensors[0].shape[0]; + return Run(tensors, cls_labels, cls_scores, 0, total_size); +} + +bool ClassifierPostprocessor::Run(const std::vector& tensors, + std::vector* cls_labels, + std::vector* cls_scores, + size_t start_index, size_t total_size) { // Classifier have only 1 output tensor. const FDTensor& tensor = tensors[0]; @@ -48,13 +48,29 @@ bool ClassifierPostprocessor::Run(const std::vector& tensors, size_t batch = tensor.shape[0]; size_t length = accumulate(tensor.shape.begin()+1, tensor.shape.end(), 1, std::multiplies()); - cls_labels->resize(batch); - cls_scores->resize(batch); + if (batch <= 0) { + FDERROR << "The infer outputTensor.shape[0] <=0, wrong infer result." << std::endl; + return false; + } + if (start_index < 0 || total_size <= 0) { + FDERROR << "start_index or total_size error. Correct is: 0 <= start_index < total_size" << std::endl; + return false; + } + if ((start_index + batch) > total_size) { + FDERROR << "start_index or total_size error. Correct is: start_index + batch(outputTensor.shape[0]) <= total_size" << std::endl; + return false; + } + + cls_labels->resize(total_size); + cls_scores->resize(total_size); const float* tensor_data = reinterpret_cast(tensor.Data()); - for (int i_batch = 0; i_batch < batch; ++i_batch) { - if(!SingleBatchPostprocessor(tensor_data, length, &cls_labels->at(i_batch),&cls_scores->at(i_batch))) return false; - tensor_data = tensor_data + length; + if(!SingleBatchPostprocessor(tensor_data+ i_batch * length, + length, + &cls_labels->at(i_batch + start_index), + &cls_scores->at(i_batch + start_index))) { + return false; + } } return true; diff --git a/fastdeploy/vision/ocr/ppocr/cls_postprocessor.h b/fastdeploy/vision/ocr/ppocr/cls_postprocessor.h index 15bf098c7..a755e1294 100644 --- a/fastdeploy/vision/ocr/ppocr/cls_postprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/cls_postprocessor.h @@ -25,11 +25,6 @@ namespace ocr { */ class FASTDEPLOY_DECL ClassifierPostprocessor { public: - /** \brief Create a postprocessor instance for Classifier serials model - * - */ - ClassifierPostprocessor(); - /** \brief Process the result of runtime and fill to ClassifyResult structure * * \param[in] tensors The inference result from runtime @@ -40,10 +35,11 @@ class FASTDEPLOY_DECL ClassifierPostprocessor { bool Run(const std::vector& tensors, std::vector* cls_labels, std::vector* cls_scores); - float cls_thresh_ = 0.9; + bool Run(const std::vector& tensors, + std::vector* cls_labels, std::vector* cls_scores, + size_t start_index, size_t total_size); - private: - bool initialized_ = false; + float cls_thresh_ = 0.9; }; } // namespace ocr diff --git a/fastdeploy/vision/ocr/ppocr/cls_preprocessor.cc b/fastdeploy/vision/ocr/ppocr/cls_preprocessor.cc old mode 100644 new mode 100755 index 1f0993690..dcd76c168 --- a/fastdeploy/vision/ocr/ppocr/cls_preprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/cls_preprocessor.cc @@ -21,58 +21,53 @@ namespace fastdeploy { namespace vision { namespace ocr { -ClassifierPreprocessor::ClassifierPreprocessor() { - initialized_ = true; -} - void OcrClassifierResizeImage(FDMat* mat, const std::vector& cls_image_shape) { - int imgC = cls_image_shape[0]; - int imgH = cls_image_shape[1]; - int imgW = cls_image_shape[2]; + int img_c = cls_image_shape[0]; + int img_h = cls_image_shape[1]; + int img_w = cls_image_shape[2]; float ratio = float(mat->Width()) / float(mat->Height()); int resize_w; - if (ceilf(imgH * ratio) > imgW) - resize_w = imgW; + if (ceilf(img_h * ratio) > img_w) + resize_w = img_w; else - resize_w = int(ceilf(imgH * ratio)); + resize_w = int(ceilf(img_h * ratio)); - Resize::Run(mat, resize_w, imgH); - - std::vector value = {0, 0, 0}; - if (resize_w < imgW) { - Pad::Run(mat, 0, 0, 0, imgW - resize_w, value); - } + Resize::Run(mat, resize_w, img_h); } bool ClassifierPreprocessor::Run(std::vector* images, std::vector* outputs) { - if (!initialized_) { - FDERROR << "The preprocessor is not initialized." << std::endl; - return false; - } - if (images->size() == 0) { - FDERROR << "The size of input images should be greater than 0." << std::endl; + return Run(images, outputs, 0, images->size()); +} + +bool ClassifierPreprocessor::Run(std::vector* images, std::vector* outputs, + size_t start_index, size_t end_index) { + + if (images->size() == 0 || start_index <0 || end_index <= start_index || end_index > images->size()) { + FDERROR << "images->size() or index error. Correct is: 0 <= start_index < end_index <= images->size()" << std::endl; return false; } - for (size_t i = 0; i < images->size(); ++i) { + for (size_t i = start_index; i < end_index; ++i) { FDMat* mat = &(images->at(i)); OcrClassifierResizeImage(mat, cls_image_shape_); - NormalizeAndPermute::Run(mat, mean_, scale_, is_scale_); - /* Normalize::Run(mat, mean_, scale_, is_scale_); + std::vector value = {0, 0, 0}; + if (mat->Width() < cls_image_shape_[2]) { + Pad::Run(mat, 0, 0, 0, cls_image_shape_[2] - mat->Width(), value); + } HWC2CHW::Run(mat); Cast::Run(mat, "float"); - */ } // Only have 1 output Tensor. outputs->resize(1); // Concat all the preprocessed data to a batch tensor - std::vector tensors(images->size()); - for (size_t i = 0; i < images->size(); ++i) { - (*images)[i].ShareWithTensor(&(tensors[i])); + size_t tensor_size = end_index - start_index; + std::vector tensors(tensor_size); + for (size_t i = 0; i < tensor_size; ++i) { + (*images)[i + start_index].ShareWithTensor(&(tensors[i])); tensors[i].ExpandDim(0); } if (tensors.size() == 1) { diff --git a/fastdeploy/vision/ocr/ppocr/cls_preprocessor.h b/fastdeploy/vision/ocr/ppocr/cls_preprocessor.h index a701e7e3a..ed75d55b2 100644 --- a/fastdeploy/vision/ocr/ppocr/cls_preprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/cls_preprocessor.h @@ -24,11 +24,6 @@ namespace ocr { */ class FASTDEPLOY_DECL ClassifierPreprocessor { public: - /** \brief Create a preprocessor instance for Classifier serials model - * - */ - ClassifierPreprocessor(); - /** \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() @@ -36,14 +31,13 @@ class FASTDEPLOY_DECL ClassifierPreprocessor { * \return true if the preprocess successed, otherwise false */ bool Run(std::vector* images, std::vector* outputs); + bool Run(std::vector* images, std::vector* outputs, + size_t start_index, size_t end_index); std::vector mean_ = {0.5f, 0.5f, 0.5f}; std::vector scale_ = {0.5f, 0.5f, 0.5f}; bool is_scale_ = true; std::vector cls_image_shape_ = {3, 48, 192}; - - private: - bool initialized_ = false; }; } // namespace ocr diff --git a/fastdeploy/vision/ocr/ppocr/dbdetector.cc b/fastdeploy/vision/ocr/ppocr/dbdetector.cc index 68a994afc..b490e88d9 100755 --- a/fastdeploy/vision/ocr/ppocr/dbdetector.cc +++ b/fastdeploy/vision/ocr/ppocr/dbdetector.cc @@ -50,14 +50,6 @@ bool DBDetector::Initialize() { return true; } -bool DBDetector::Predict(cv::Mat* img, - std::vector>* boxes_result) { - if (!Predict(*img, boxes_result)) { - return false; - } - return true; -} - bool DBDetector::Predict(const cv::Mat& img, std::vector>* boxes_result) { std::vector>> det_results; diff --git a/fastdeploy/vision/ocr/ppocr/dbdetector.h b/fastdeploy/vision/ocr/ppocr/dbdetector.h index d3b99d598..d2305abd7 100755 --- a/fastdeploy/vision/ocr/ppocr/dbdetector.h +++ b/fastdeploy/vision/ocr/ppocr/dbdetector.h @@ -44,14 +44,6 @@ class FASTDEPLOY_DECL DBDetector : public FastDeployModel { const ModelFormat& model_format = ModelFormat::PADDLE); /// Get model's name std::string ModelName() const { return "ppocr/ocr_det"; } - /** \brief Predict the input image and get OCR detection model result. - * - * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. - * \param[in] boxes_result The output of OCR detection model result will be writen to this structure. - * \return true if the prediction is successed, otherwise false. - */ - virtual bool Predict(cv::Mat* img, - std::vector>* boxes_result); /** \brief Predict the input image and get OCR detection model result. * * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. diff --git a/fastdeploy/vision/ocr/ppocr/det_postprocessor.cc b/fastdeploy/vision/ocr/ppocr/det_postprocessor.cc index 34a88c011..e83dac5e5 100644 --- a/fastdeploy/vision/ocr/ppocr/det_postprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/det_postprocessor.cc @@ -20,10 +20,6 @@ namespace fastdeploy { namespace vision { namespace ocr { -DBDetectorPostprocessor::DBDetectorPostprocessor() { - initialized_ = true; -} - bool DBDetectorPostprocessor::SingleBatchPostprocessor( const float* out_data, int n2, @@ -57,10 +53,10 @@ bool DBDetectorPostprocessor::SingleBatchPostprocessor( std::vector>> boxes; boxes = - post_processor_.BoxesFromBitmap(pred_map, bit_map, det_db_box_thresh_, + util_post_processor_.BoxesFromBitmap(pred_map, bit_map, det_db_box_thresh_, det_db_unclip_ratio_, det_db_score_mode_); - boxes = post_processor_.FilterTagDetRes(boxes, det_img_info); + boxes = util_post_processor_.FilterTagDetRes(boxes, det_img_info); // boxes to boxes_result for (int i = 0; i < boxes.size(); i++) { @@ -80,10 +76,6 @@ bool DBDetectorPostprocessor::SingleBatchPostprocessor( bool DBDetectorPostprocessor::Run(const std::vector& tensors, std::vector>>* results, const std::vector>& batch_det_img_info) { - if (!initialized_) { - FDERROR << "Postprocessor is not initialized." << std::endl; - return false; - } // DBDetector have only 1 output tensor. const FDTensor& tensor = tensors[0]; diff --git a/fastdeploy/vision/ocr/ppocr/det_postprocessor.h b/fastdeploy/vision/ocr/ppocr/det_postprocessor.h index f98b89b02..115228843 100644 --- a/fastdeploy/vision/ocr/ppocr/det_postprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/det_postprocessor.h @@ -25,11 +25,6 @@ namespace ocr { */ class FASTDEPLOY_DECL DBDetectorPostprocessor { public: - /** \brief Create a postprocessor instance for DBDetector serials model - * - */ - DBDetectorPostprocessor(); - /** \brief Process the result of runtime and fill to results structure * * \param[in] tensors The inference result from runtime @@ -48,8 +43,7 @@ class FASTDEPLOY_DECL DBDetectorPostprocessor { bool use_dilation_ = false; private: - bool initialized_ = false; - PostProcessor post_processor_; + PostProcessor util_post_processor_; bool SingleBatchPostprocessor(const float* out_data, int n2, int n3, diff --git a/fastdeploy/vision/ocr/ppocr/det_preprocessor.cc b/fastdeploy/vision/ocr/ppocr/det_preprocessor.cc index 89a8d6d39..28b7e47af 100644 --- a/fastdeploy/vision/ocr/ppocr/det_preprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/det_preprocessor.cc @@ -21,10 +21,6 @@ namespace fastdeploy { namespace vision { namespace ocr { -DBDetectorPreprocessor::DBDetectorPreprocessor() { - initialized_ = true; -} - std::array OcrDetectorGetInfo(FDMat* img, int max_size_len) { int w = img->Width(); int h = img->Height(); @@ -63,10 +59,6 @@ bool OcrDetectorResizeImage(FDMat* img, bool DBDetectorPreprocessor::Run(std::vector* images, std::vector* outputs, std::vector>* batch_det_img_info_ptr) { - if (!initialized_) { - FDERROR << "The preprocessor is not initialized." << std::endl; - return false; - } if (images->size() == 0) { FDERROR << "The size of input images should be greater than 0." << std::endl; return false; diff --git a/fastdeploy/vision/ocr/ppocr/det_preprocessor.h b/fastdeploy/vision/ocr/ppocr/det_preprocessor.h index 39c48691d..d66e785d3 100644 --- a/fastdeploy/vision/ocr/ppocr/det_preprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/det_preprocessor.h @@ -24,11 +24,6 @@ namespace ocr { */ class FASTDEPLOY_DECL DBDetectorPreprocessor { public: - /** \brief Create a preprocessor instance for DBDetector serials model - * - */ - DBDetectorPreprocessor(); - /** \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() @@ -44,9 +39,6 @@ class FASTDEPLOY_DECL DBDetectorPreprocessor { std::vector mean_ = {0.485f, 0.456f, 0.406f}; std::vector scale_ = {0.229f, 0.224f, 0.225f}; bool is_scale_ = true; - - private: - bool initialized_ = false; }; } // namespace ocr diff --git a/fastdeploy/vision/ocr/ppocr/ocrmodel_pybind.cc b/fastdeploy/vision/ocr/ppocr/ocrmodel_pybind.cc index b7e7dcbf3..f84e99ed5 100755 --- a/fastdeploy/vision/ocr/ppocr/ocrmodel_pybind.cc +++ b/fastdeploy/vision/ocr/ppocr/ocrmodel_pybind.cc @@ -20,14 +20,8 @@ void BindPPOCRModel(pybind11::module& m) { vision::ocr::SortBoxes(&boxes); return boxes; }); + // DBDetector - pybind11::class_(m, "DBDetector") - .def(pybind11::init()) - .def(pybind11::init<>()) - .def_readwrite("preprocessor", &vision::ocr::DBDetector::preprocessor_) - .def_readwrite("postprocessor", &vision::ocr::DBDetector::postprocessor_); - pybind11::class_(m, "DBDetectorPreprocessor") .def(pybind11::init<>()) .def_readwrite("max_side_len", &vision::ocr::DBDetectorPreprocessor::max_side_len_) @@ -45,7 +39,7 @@ void BindPPOCRModel(pybind11::module& m) { for(size_t i = 0; i< outputs.size(); ++i){ outputs[i].StopSharing(); } - return make_pair(outputs, batch_det_img_info); + return std::make_pair(outputs, batch_det_img_info); }); pybind11::class_(m, "DBDetectorPostprocessor") @@ -77,15 +71,31 @@ void BindPPOCRModel(pybind11::module& m) { return results; }); - // Classifier - pybind11::class_(m, "Classifier") + pybind11::class_(m, "DBDetector") .def(pybind11::init()) .def(pybind11::init<>()) - .def_readwrite("preprocessor", &vision::ocr::Classifier::preprocessor_) - .def_readwrite("postprocessor", &vision::ocr::Classifier::postprocessor_); + .def_readwrite("preprocessor", &vision::ocr::DBDetector::preprocessor_) + .def_readwrite("postprocessor", &vision::ocr::DBDetector::postprocessor_) + .def("predict", [](vision::ocr::DBDetector& self, + pybind11::array& data) { + auto mat = PyArrayToCvMat(data); + std::vector> boxes_result; + self.Predict(mat, &boxes_result); + return boxes_result; + }) + .def("batch_predict", [](vision::ocr::DBDetector& self, std::vector& data) { + std::vector images; + std::vector>> det_results; + for (size_t i = 0; i < data.size(); ++i) { + images.push_back(PyArrayToCvMat(data[i])); + } + self.BatchPredict(images, &det_results); + return det_results; + }); - pybind11::class_(m, "ClassifierPreprocessor") + // Classifier + pybind11::class_(m, "ClassifierPreprocessor") .def(pybind11::init<>()) .def_readwrite("cls_image_shape", &vision::ocr::ClassifierPreprocessor::cls_image_shape_) .def_readwrite("mean", &vision::ocr::ClassifierPreprocessor::mean_) @@ -116,7 +126,7 @@ void BindPPOCRModel(pybind11::module& m) { if (!self.Run(inputs, &cls_labels, &cls_scores)) { throw std::runtime_error("Failed to preprocess the input data in ClassifierPostprocessor."); } - return make_pair(cls_labels,cls_scores); + return std::make_pair(cls_labels,cls_scores); }) .def("run", [](vision::ocr::ClassifierPostprocessor& self, std::vector& input_array) { @@ -127,39 +137,56 @@ void BindPPOCRModel(pybind11::module& m) { if (!self.Run(inputs, &cls_labels, &cls_scores)) { throw std::runtime_error("Failed to preprocess the input data in ClassifierPostprocessor."); } - return make_pair(cls_labels,cls_scores); + return std::make_pair(cls_labels,cls_scores); }); - - - // Recognizer - pybind11::class_(m, "Recognizer") - .def(pybind11::init(m, "Classifier") + .def(pybind11::init()) .def(pybind11::init<>()) - .def_readwrite("preprocessor", &vision::ocr::Recognizer::preprocessor_) - .def_readwrite("postprocessor", &vision::ocr::Recognizer::postprocessor_); - - pybind11::class_(m, "RecognizerPreprocessor") - .def(pybind11::init<>()) - .def_readwrite("rec_image_shape", &vision::ocr::RecognizerPreprocessor::rec_image_shape_) - .def_readwrite("mean", &vision::ocr::RecognizerPreprocessor::mean_) - .def_readwrite("scale", &vision::ocr::RecognizerPreprocessor::scale_) - .def_readwrite("is_scale", &vision::ocr::RecognizerPreprocessor::is_scale_) - .def("run", [](vision::ocr::RecognizerPreprocessor& self, std::vector& im_list) { - std::vector images; - for (size_t i = 0; i < im_list.size(); ++i) { - images.push_back(vision::WrapMat(PyArrayToCvMat(im_list[i]))); + .def_readwrite("preprocessor", &vision::ocr::Classifier::preprocessor_) + .def_readwrite("postprocessor", &vision::ocr::Classifier::postprocessor_) + .def("predict", [](vision::ocr::Classifier& self, + pybind11::array& data) { + auto mat = PyArrayToCvMat(data); + int32_t cls_label; + float cls_score; + self.Predict(mat, &cls_label, &cls_score); + return std::make_pair(cls_label, cls_score); + }) + .def("batch_predict", [](vision::ocr::Classifier& self, std::vector& data) { + std::vector images; + std::vector cls_labels; + std::vector cls_scores; + for (size_t i = 0; i < data.size(); ++i) { + images.push_back(PyArrayToCvMat(data[i])); } - std::vector outputs; - if (!self.Run(&images, &outputs)) { - throw std::runtime_error("Failed to preprocess the input data in RecognizerPreprocessor."); - } - for(size_t i = 0; i< outputs.size(); ++i){ - outputs[i].StopSharing(); - } - return outputs; + self.BatchPredict(images, &cls_labels, &cls_scores); + return std::make_pair(cls_labels, cls_scores); }); + // Recognizer + pybind11::class_(m, "RecognizerPreprocessor") + .def(pybind11::init<>()) + .def_readwrite("rec_image_shape", &vision::ocr::RecognizerPreprocessor::rec_image_shape_) + .def_readwrite("mean", &vision::ocr::RecognizerPreprocessor::mean_) + .def_readwrite("scale", &vision::ocr::RecognizerPreprocessor::scale_) + .def_readwrite("is_scale", &vision::ocr::RecognizerPreprocessor::is_scale_) + .def("run", [](vision::ocr::RecognizerPreprocessor& self, std::vector& im_list) { + std::vector images; + for (size_t i = 0; i < im_list.size(); ++i) { + images.push_back(vision::WrapMat(PyArrayToCvMat(im_list[i]))); + } + std::vector outputs; + if (!self.Run(&images, &outputs)) { + throw std::runtime_error("Failed to preprocess the input data in RecognizerPreprocessor."); + } + for(size_t i = 0; i< outputs.size(); ++i){ + outputs[i].StopSharing(); + } + return outputs; + }); + pybind11::class_(m, "RecognizerPostprocessor") .def(pybind11::init()) .def("run", [](vision::ocr::RecognizerPostprocessor& self, @@ -169,7 +196,7 @@ void BindPPOCRModel(pybind11::module& m) { if (!self.Run(inputs, &texts, &rec_scores)) { throw std::runtime_error("Failed to preprocess the input data in RecognizerPostprocessor."); } - return make_pair(texts, rec_scores); + return std::make_pair(texts, rec_scores); }) .def("run", [](vision::ocr::RecognizerPostprocessor& self, std::vector& input_array) { @@ -180,7 +207,32 @@ void BindPPOCRModel(pybind11::module& m) { if (!self.Run(inputs, &texts, &rec_scores)) { throw std::runtime_error("Failed to preprocess the input data in RecognizerPostprocessor."); } - return make_pair(texts, rec_scores); + return std::make_pair(texts, rec_scores); + }); + + pybind11::class_(m, "Recognizer") + .def(pybind11::init()) + .def(pybind11::init<>()) + .def_readwrite("preprocessor", &vision::ocr::Recognizer::preprocessor_) + .def_readwrite("postprocessor", &vision::ocr::Recognizer::postprocessor_) + .def("predict", [](vision::ocr::Recognizer& self, + pybind11::array& data) { + auto mat = PyArrayToCvMat(data); + std::string text; + float rec_score; + self.Predict(mat, &text, &rec_score); + return std::make_pair(text, rec_score); + }) + .def("batch_predict", [](vision::ocr::Recognizer& self, std::vector& data) { + std::vector images; + std::vector texts; + std::vector rec_scores; + for (size_t i = 0; i < data.size(); ++i) { + images.push_back(PyArrayToCvMat(data[i])); + } + self.BatchPredict(images, &texts, &rec_scores); + return std::make_pair(texts, rec_scores); }); } } // namespace fastdeploy diff --git a/fastdeploy/vision/ocr/ppocr/ppocr_pybind.cc b/fastdeploy/vision/ocr/ppocr/ppocr_pybind.cc index fcbbe0224..7542793fe 100755 --- a/fastdeploy/vision/ocr/ppocr/ppocr_pybind.cc +++ b/fastdeploy/vision/ocr/ppocr/ppocr_pybind.cc @@ -25,6 +25,8 @@ void BindPPOCRv3(pybind11::module& m) { fastdeploy::vision::ocr::Recognizer*>()) .def(pybind11::init()) + .def_property("cls_batch_size", &pipeline::PPOCRv3::GetClsBatchSize, &pipeline::PPOCRv3::SetClsBatchSize) + .def_property("rec_batch_size", &pipeline::PPOCRv3::GetRecBatchSize, &pipeline::PPOCRv3::SetRecBatchSize) .def("predict", [](pipeline::PPOCRv3& self, pybind11::array& data) { auto mat = PyArrayToCvMat(data); @@ -52,6 +54,8 @@ void BindPPOCRv2(pybind11::module& m) { fastdeploy::vision::ocr::Recognizer*>()) .def(pybind11::init()) + .def_property("cls_batch_size", &pipeline::PPOCRv2::GetClsBatchSize, &pipeline::PPOCRv2::SetClsBatchSize) + .def_property("rec_batch_size", &pipeline::PPOCRv2::GetRecBatchSize, &pipeline::PPOCRv2::SetRecBatchSize) .def("predict", [](pipeline::PPOCRv2& self, pybind11::array& data) { auto mat = PyArrayToCvMat(data); diff --git a/fastdeploy/vision/ocr/ppocr/ppocr_v2.cc b/fastdeploy/vision/ocr/ppocr/ppocr_v2.cc index daa40692d..756604dde 100755 --- a/fastdeploy/vision/ocr/ppocr/ppocr_v2.cc +++ b/fastdeploy/vision/ocr/ppocr/ppocr_v2.cc @@ -33,6 +33,32 @@ PPOCRv2::PPOCRv2(fastdeploy::vision::ocr::DBDetector* det_model, recognizer_->preprocessor_.rec_image_shape_[1] = 32; } +bool PPOCRv2::SetClsBatchSize(int cls_batch_size) { + if (cls_batch_size < -1 || cls_batch_size == 0) { + FDERROR << "batch_size > 0 or batch_size == -1." << std::endl; + return false; + } + cls_batch_size_ = cls_batch_size; + return true; +} + +int PPOCRv2::GetClsBatchSize() { + return cls_batch_size_; +} + +bool PPOCRv2::SetRecBatchSize(int rec_batch_size) { + if (rec_batch_size < -1 || rec_batch_size == 0) { + FDERROR << "batch_size > 0 or batch_size == -1." << std::endl; + return false; + } + rec_batch_size_ = rec_batch_size; + return true; +} + +int PPOCRv2::GetRecBatchSize() { + return rec_batch_size_; +} + bool PPOCRv2::Initialized() const { if (detector_ != nullptr && !detector_->Initialized()) { @@ -48,11 +74,18 @@ bool PPOCRv2::Initialized() const { } return true; } - bool PPOCRv2::Predict(cv::Mat* img, fastdeploy::vision::OCRResult* result) { + return Predict(*img, result); +} + +bool PPOCRv2::Predict(const cv::Mat& img, + fastdeploy::vision::OCRResult* result) { std::vector batch_result(1); - BatchPredict({*img},&batch_result); + bool success = BatchPredict({img},&batch_result); + if(!success){ + return success; + } *result = std::move(batch_result[0]); return true; }; @@ -67,12 +100,12 @@ bool PPOCRv2::BatchPredict(const std::vector& images, FDERROR << "There's error while detecting image in PPOCR." << std::endl; return false; } + for(int i_batch = 0; i_batch < batch_boxes.size(); ++i_batch) { vision::ocr::SortBoxes(&(batch_boxes[i_batch])); (*batch_result)[i_batch].boxes = batch_boxes[i_batch]; } - for(int i_batch = 0; i_batch < images.size(); ++i_batch) { fastdeploy::vision::OCRResult& ocr_result = (*batch_result)[i_batch]; // Get croped images by detection result @@ -93,22 +126,34 @@ bool PPOCRv2::BatchPredict(const std::vector& images, std::vector* text_ptr = &ocr_result.text; std::vector* rec_scores_ptr = &ocr_result.rec_scores; - if (nullptr != classifier_){ - if (!classifier_->BatchPredict(image_list, cls_labels_ptr, cls_scores_ptr)) { - FDERROR << "There's error while recognizing image in PPOCR." << std::endl; - return false; - }else{ - for (size_t i_img = 0; i_img < image_list.size(); ++i_img) { - if(cls_labels_ptr->at(i_img) % 2 == 1 && cls_scores_ptr->at(i_img) > classifier_->postprocessor_.cls_thresh_) { - cv::rotate(image_list[i_img], image_list[i_img], 1); + if (nullptr != classifier_) { + for(size_t start_index = 0; start_index < image_list.size(); start_index+=cls_batch_size_) { + size_t end_index = std::min(start_index + cls_batch_size_, image_list.size()); + if (!classifier_->BatchPredict(image_list, cls_labels_ptr, cls_scores_ptr, start_index, end_index)) { + FDERROR << "There's error while recognizing image in PPOCR." << std::endl; + return false; + }else{ + for (size_t i_img = start_index; i_img < end_index; ++i_img) { + if(cls_labels_ptr->at(i_img) % 2 == 1 && cls_scores_ptr->at(i_img) > classifier_->postprocessor_.cls_thresh_) { + cv::rotate(image_list[i_img], image_list[i_img], 1); + } } } } } - - if (!recognizer_->BatchPredict(image_list, text_ptr, rec_scores_ptr)) { - FDERROR << "There's error while recognizing image in PPOCR." << std::endl; - return false; + + std::vector width_list; + for (int i = 0; i < image_list.size(); i++) { + width_list.push_back(float(image_list[i].cols) / image_list[i].rows); + } + std::vector indices = vision::ocr::ArgSort(width_list); + + for(size_t start_index = 0; start_index < image_list.size(); start_index+=rec_batch_size_) { + size_t end_index = std::min(start_index + rec_batch_size_, image_list.size()); + if (!recognizer_->BatchPredict(image_list, text_ptr, rec_scores_ptr, start_index, end_index, indices)) { + FDERROR << "There's error while recognizing image in PPOCR." << std::endl; + return false; + } } } return true; diff --git a/fastdeploy/vision/ocr/ppocr/ppocr_v2.h b/fastdeploy/vision/ocr/ppocr/ppocr_v2.h index d021d6c32..f603a45f9 100755 --- a/fastdeploy/vision/ocr/ppocr/ppocr_v2.h +++ b/fastdeploy/vision/ocr/ppocr/ppocr_v2.h @@ -59,6 +59,7 @@ class FASTDEPLOY_DECL PPOCRv2 : public FastDeployModel { * \return true if the prediction successed, otherwise false. */ virtual bool Predict(cv::Mat* img, fastdeploy::vision::OCRResult* result); + virtual bool Predict(const cv::Mat& img, fastdeploy::vision::OCRResult* result); /** \brief BatchPredict the input image and get OCR result. * * \param[in] images The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. @@ -68,11 +69,19 @@ class FASTDEPLOY_DECL PPOCRv2 : public FastDeployModel { virtual bool BatchPredict(const std::vector& images, std::vector* batch_result); bool Initialized() const override; + bool SetClsBatchSize(int cls_batch_size); + int GetClsBatchSize(); + bool SetRecBatchSize(int rec_batch_size); + int GetRecBatchSize(); protected: fastdeploy::vision::ocr::DBDetector* detector_ = nullptr; fastdeploy::vision::ocr::Classifier* classifier_ = nullptr; fastdeploy::vision::ocr::Recognizer* recognizer_ = nullptr; + + private: + int cls_batch_size_ = 1; + int rec_batch_size_ = 6; /// Launch the detection process in OCR. }; diff --git a/fastdeploy/vision/ocr/ppocr/rec_postprocessor.cc b/fastdeploy/vision/ocr/ppocr/rec_postprocessor.cc index cdc302e28..d93c16907 100644 --- a/fastdeploy/vision/ocr/ppocr/rec_postprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/rec_postprocessor.cc @@ -34,7 +34,7 @@ std::vector ReadDict(const std::string& path) { } RecognizerPostprocessor::RecognizerPostprocessor(){ - initialized_ = true; + initialized_ = false; } RecognizerPostprocessor::RecognizerPostprocessor(const std::string& label_path) { @@ -84,24 +84,53 @@ bool RecognizerPostprocessor::SingleBatchPostprocessor(const float* out_data, bool RecognizerPostprocessor::Run(const std::vector& tensors, std::vector* texts, std::vector* rec_scores) { + // Recognizer have only 1 output tensor. + // For Recognizer, the output tensor shape = [batch, ?, 6625] + size_t total_size = tensors[0].shape[0]; + return Run(tensors, texts, rec_scores, 0, total_size, {}); +} + +bool RecognizerPostprocessor::Run(const std::vector& tensors, + std::vector* texts, std::vector* rec_scores, + size_t start_index, size_t total_size, const std::vector& indices) { if (!initialized_) { FDERROR << "Postprocessor is not initialized." << std::endl; return false; } + // Recognizer have only 1 output tensor. const FDTensor& tensor = tensors[0]; // For Recognizer, the output tensor shape = [batch, ?, 6625] size_t batch = tensor.shape[0]; size_t length = accumulate(tensor.shape.begin()+1, tensor.shape.end(), 1, std::multiplies()); - texts->resize(batch); - rec_scores->resize(batch); + if (batch <= 0) { + FDERROR << "The infer outputTensor.shape[0] <=0, wrong infer result." << std::endl; + return false; + } + if (start_index < 0 || total_size <= 0) { + FDERROR << "start_index or total_size error. Correct is: 0 <= start_index < total_size" << std::endl; + return false; + } + if ((start_index + batch) > total_size) { + FDERROR << "start_index or total_size error. Correct is: start_index + batch(outputTensor.shape[0]) <= total_size" << std::endl; + return false; + } + texts->resize(total_size); + rec_scores->resize(total_size); + const float* tensor_data = reinterpret_cast(tensor.Data()); - for (int i_batch = 0; i_batch < batch; ++i_batch) { - if(!SingleBatchPostprocessor(tensor_data, tensor.shape, &texts->at(i_batch), &rec_scores->at(i_batch))) { + for (int i_batch = 0; i_batch < batch; ++i_batch) { + size_t real_index = i_batch+start_index; + if (indices.size() != 0) { + real_index = indices[i_batch+start_index]; + } + if(!SingleBatchPostprocessor(tensor_data + i_batch * length, + tensor.shape, + &texts->at(real_index), + &rec_scores->at(real_index))) { return false; } - tensor_data = tensor_data + length; } return true; diff --git a/fastdeploy/vision/ocr/ppocr/rec_postprocessor.h b/fastdeploy/vision/ocr/ppocr/rec_postprocessor.h index d1aa0124b..711ae3a01 100644 --- a/fastdeploy/vision/ocr/ppocr/rec_postprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/rec_postprocessor.h @@ -32,7 +32,7 @@ class FASTDEPLOY_DECL RecognizerPostprocessor { */ explicit RecognizerPostprocessor(const std::string& label_path); - /** \brief Process the result of runtime and fill to ClassifyResult structure + /** \brief Process the result of runtime and fill to RecognizerResult * * \param[in] tensors The inference result from runtime * \param[in] texts The output result of recognizer @@ -42,6 +42,11 @@ class FASTDEPLOY_DECL RecognizerPostprocessor { bool Run(const std::vector& tensors, std::vector* texts, std::vector* rec_scores); + bool Run(const std::vector& tensors, + std::vector* texts, std::vector* rec_scores, + size_t start_index, size_t total_size, + const std::vector& indices); + private: bool SingleBatchPostprocessor(const float* out_data, const std::vector& output_shape, diff --git a/fastdeploy/vision/ocr/ppocr/rec_preprocessor.cc b/fastdeploy/vision/ocr/ppocr/rec_preprocessor.cc index 858578d69..a965eb762 100644 --- a/fastdeploy/vision/ocr/ppocr/rec_preprocessor.cc +++ b/fastdeploy/vision/ocr/ppocr/rec_preprocessor.cc @@ -21,69 +21,75 @@ namespace fastdeploy { namespace vision { namespace ocr { -RecognizerPreprocessor::RecognizerPreprocessor() { - initialized_ = true; -} - void OcrRecognizerResizeImage(FDMat* mat, float max_wh_ratio, const std::vector& rec_image_shape) { - int imgC, imgH, imgW; - imgC = rec_image_shape[0]; - imgH = rec_image_shape[1]; - imgW = rec_image_shape[2]; + int img_c, img_h, img_w; + img_c = rec_image_shape[0]; + img_h = rec_image_shape[1]; + img_w = rec_image_shape[2]; - imgW = int(imgH * max_wh_ratio); + img_w = int(img_h * max_wh_ratio); float ratio = float(mat->Width()) / float(mat->Height()); int resize_w; - if (ceilf(imgH * ratio) > imgW) { - resize_w = imgW; + if (ceilf(img_h * ratio) > img_w) { + resize_w = img_w; }else{ - resize_w = int(ceilf(imgH * ratio)); + resize_w = int(ceilf(img_h * ratio)); } - Resize::Run(mat, resize_w, imgH); + Resize::Run(mat, resize_w, img_h); std::vector value = {0, 0, 0}; - Pad::Run(mat, 0, 0, 0, int(imgW - mat->Width()), value); + Pad::Run(mat, 0, 0, 0, int(img_w - mat->Width()), value); } bool RecognizerPreprocessor::Run(std::vector* images, std::vector* outputs) { - if (!initialized_) { - FDERROR << "The preprocessor is not initialized." << std::endl; - return false; - } - if (images->size() == 0) { - FDERROR << "The size of input images should be greater than 0." << std::endl; + return Run(images, outputs, 0, images->size(), {}); +} + +bool RecognizerPreprocessor::Run(std::vector* images, std::vector* outputs, + size_t start_index, size_t end_index, const std::vector& indices) { + if (images->size() == 0 || end_index <= start_index || end_index > images->size()) { + FDERROR << "images->size() or index error. Correct is: 0 <= start_index < end_index <= images->size()" << std::endl; return false; } - int imgH = rec_image_shape_[1]; - int imgW = rec_image_shape_[2]; - float max_wh_ratio = imgW * 1.0 / imgH; + int img_h = rec_image_shape_[1]; + int img_w = rec_image_shape_[2]; + float max_wh_ratio = img_w * 1.0 / img_h; float ori_wh_ratio; - for (size_t i = 0; i < images->size(); ++i) { - FDMat* mat = &(images->at(i)); + for (size_t i = start_index; i < end_index; ++i) { + size_t real_index = i; + if (indices.size() != 0) { + real_index = indices[i]; + } + FDMat* mat = &(images->at(real_index)); ori_wh_ratio = mat->Width() * 1.0 / mat->Height(); max_wh_ratio = std::max(max_wh_ratio, ori_wh_ratio); } - for (size_t i = 0; i < images->size(); ++i) { - FDMat* mat = &(images->at(i)); + for (size_t i = start_index; i < end_index; ++i) { + size_t real_index = i; + if (indices.size() != 0) { + real_index = indices[i]; + } + FDMat* mat = &(images->at(real_index)); OcrRecognizerResizeImage(mat, max_wh_ratio, rec_image_shape_); NormalizeAndPermute::Run(mat, mean_, scale_, is_scale_); - /* - Normalize::Run(mat, mean_, scale_, is_scale_); - HWC2CHW::Run(mat); - Cast::Run(mat, "float"); - */ } // Only have 1 output Tensor. outputs->resize(1); + size_t tensor_size = end_index-start_index; // Concat all the preprocessed data to a batch tensor - std::vector tensors(images->size()); - for (size_t i = 0; i < images->size(); ++i) { - (*images)[i].ShareWithTensor(&(tensors[i])); + std::vector tensors(tensor_size); + for (size_t i = 0; i < tensor_size; ++i) { + size_t real_index = i + start_index; + if (indices.size() != 0) { + real_index = indices[i + start_index]; + } + + (*images)[real_index].ShareWithTensor(&(tensors[i])); tensors[i].ExpandDim(0); } if (tensors.size() == 1) { diff --git a/fastdeploy/vision/ocr/ppocr/rec_preprocessor.h b/fastdeploy/vision/ocr/ppocr/rec_preprocessor.h index 3e5c7de82..1dad75870 100644 --- a/fastdeploy/vision/ocr/ppocr/rec_preprocessor.h +++ b/fastdeploy/vision/ocr/ppocr/rec_preprocessor.h @@ -24,12 +24,6 @@ namespace ocr { */ class FASTDEPLOY_DECL RecognizerPreprocessor { public: - /** \brief Create a preprocessor instance for PaddleClas serials model - * - * \param[in] config_file Path of configuration file for deployment, e.g resnet/infer_cfg.yml - */ - RecognizerPreprocessor(); - /** \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() @@ -37,14 +31,14 @@ class FASTDEPLOY_DECL RecognizerPreprocessor { * \return true if the preprocess successed, otherwise false */ bool Run(std::vector* images, std::vector* outputs); + bool Run(std::vector* images, std::vector* outputs, + size_t start_index, size_t end_index, + const std::vector& indices); std::vector rec_image_shape_ = {3, 48, 320}; std::vector mean_ = {0.5f, 0.5f, 0.5f}; std::vector scale_ = {0.5f, 0.5f, 0.5f}; bool is_scale_ = true; - - private: - bool initialized_ = false; }; } // namespace ocr diff --git a/fastdeploy/vision/ocr/ppocr/recognizer.cc b/fastdeploy/vision/ocr/ppocr/recognizer.cc index 59d64a6c4..8965e73d9 100755 --- a/fastdeploy/vision/ocr/ppocr/recognizer.cc +++ b/fastdeploy/vision/ocr/ppocr/recognizer.cc @@ -53,10 +53,33 @@ bool Recognizer::Initialize() { return true; } +bool Recognizer::Predict(const cv::Mat& img, std::string* text, float* rec_score) { + std::vector texts(1); + std::vector rec_scores(1); + bool success = BatchPredict({img}, &texts, &rec_scores); + if (!success) { + return success; + } + *text = std::move(texts[0]); + *rec_score = rec_scores[0]; + return true; +} + bool Recognizer::BatchPredict(const std::vector& images, std::vector* texts, std::vector* rec_scores) { + return BatchPredict(images, texts, rec_scores, 0, images.size(), {}); +} + +bool Recognizer::BatchPredict(const std::vector& images, + std::vector* texts, std::vector* rec_scores, + size_t start_index, size_t end_index, const std::vector& indices) { + size_t total_size = images.size(); + if (indices.size() != 0 && indices.size() != total_size) { + FDERROR << "indices.size() should be 0 or images.size()." << std::endl; + return false; + } std::vector fd_images = WrapMat(images); - if (!preprocessor_.Run(&fd_images, &reused_input_tensors_)) { + if (!preprocessor_.Run(&fd_images, &reused_input_tensors_, start_index, end_index, indices)) { FDERROR << "Failed to preprocess the input image." << std::endl; return false; } @@ -66,7 +89,7 @@ bool Recognizer::BatchPredict(const std::vector& images, return false; } - if (!postprocessor_.Run(reused_output_tensors_, texts, rec_scores)) { + if (!postprocessor_.Run(reused_output_tensors_, texts, rec_scores, start_index, total_size, indices)) { FDERROR << "Failed to postprocess the inference cls_results by runtime." << std::endl; return false; } diff --git a/fastdeploy/vision/ocr/ppocr/recognizer.h b/fastdeploy/vision/ocr/ppocr/recognizer.h index 1cd841eb4..8a5f5bc70 100755 --- a/fastdeploy/vision/ocr/ppocr/recognizer.h +++ b/fastdeploy/vision/ocr/ppocr/recognizer.h @@ -45,6 +45,7 @@ class FASTDEPLOY_DECL Recognizer : public FastDeployModel { const ModelFormat& model_format = ModelFormat::PADDLE); /// Get model's name std::string ModelName() const { return "ppocr/ocr_rec"; } + virtual bool Predict(const cv::Mat& img, std::string* text, float* rec_score); /** \brief BatchPredict the input image and get OCR recognition model result. * * \param[in] images The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. @@ -53,6 +54,10 @@ class FASTDEPLOY_DECL Recognizer : public FastDeployModel { */ virtual bool BatchPredict(const std::vector& images, std::vector* texts, std::vector* rec_scores); + virtual bool BatchPredict(const std::vector& images, + std::vector* texts, std::vector* rec_scores, + size_t start_index, size_t end_index, + const std::vector& indices); RecognizerPreprocessor preprocessor_; RecognizerPostprocessor postprocessor_; diff --git a/fastdeploy/vision/ocr/ppocr/utils/ocr_utils.h b/fastdeploy/vision/ocr/ppocr/utils/ocr_utils.h old mode 100644 new mode 100755 index 0e5c040eb..f12f40f71 --- a/fastdeploy/vision/ocr/ppocr/utils/ocr_utils.h +++ b/fastdeploy/vision/ocr/ppocr/utils/ocr_utils.h @@ -33,6 +33,8 @@ FASTDEPLOY_DECL cv::Mat GetRotateCropImage(const cv::Mat& srcimage, FASTDEPLOY_DECL void SortBoxes(std::vector>* boxes); +FASTDEPLOY_DECL std::vector ArgSort(const std::vector &array); + } // namespace ocr } // namespace vision } // namespace fastdeploy diff --git a/fastdeploy/vision/ocr/ppocr/utils/sorted_boxes.cc b/fastdeploy/vision/ocr/ppocr/utils/sorted_boxes.cc old mode 100644 new mode 100755 index b55d2a9eb..053215e4a --- a/fastdeploy/vision/ocr/ppocr/utils/sorted_boxes.cc +++ b/fastdeploy/vision/ocr/ppocr/utils/sorted_boxes.cc @@ -35,13 +35,29 @@ void SortBoxes(std::vector>* boxes) { if (boxes->size() == 0) { return; } - + for (int i = 0; i < boxes->size() - 1; i++) { - if (std::abs((*boxes)[i + 1][1] - (*boxes)[i][1]) < 10 && - ((*boxes)[i + 1][0] < (*boxes)[i][0])) { - std::swap((*boxes)[i], (*boxes)[i + 1]); + for (int j = i; j >=0 ; j--){ + if (std::abs((*boxes)[j + 1][1] - (*boxes)[j][1]) < 10 && + ((*boxes)[j + 1][0] < (*boxes)[j][0])) { + std::swap((*boxes)[i], (*boxes)[i + 1]); + } } } + +} + +std::vector ArgSort(const std::vector &array) { + const int array_len(array.size()); + std::vector array_index(array_len, 0); + for (int i = 0; i < array_len; ++i) + array_index[i] = i; + + std::sort( + array_index.begin(), array_index.end(), + [&array](int pos1, int pos2) { return (array[pos1] < array[pos2]); }); + + return array_index; } } // namespace ocr diff --git a/fastdeploy/vision/segmentation/ppseg/model.cc b/fastdeploy/vision/segmentation/ppseg/model.cc old mode 100644 new mode 100755 index 1bf83131c..ad2a7773a --- a/fastdeploy/vision/segmentation/ppseg/model.cc +++ b/fastdeploy/vision/segmentation/ppseg/model.cc @@ -27,6 +27,7 @@ PaddleSegModel::PaddleSegModel(const std::string& model_file, valid_cpu_backends = {Backend::OPENVINO, Backend::PDINFER, Backend::ORT, Backend::LITE}; valid_gpu_backends = {Backend::PDINFER, Backend::ORT, Backend::TRT}; valid_rknpu_backends = {Backend::RKNPU2}; + valid_timvx_backends = {Backend::LITE}; runtime_option = custom_option; runtime_option.model_format = model_format; runtime_option.model_file = model_file; diff --git a/fastdeploy/vision/segmentation/ppseg/postprocessor.cc b/fastdeploy/vision/segmentation/ppseg/postprocessor.cc index a2acb8ef7..953cf2c68 100644 --- a/fastdeploy/vision/segmentation/ppseg/postprocessor.cc +++ b/fastdeploy/vision/segmentation/ppseg/postprocessor.cc @@ -280,13 +280,17 @@ bool PaddleSegPostprocessor::Run( FDMat mat; std::vector uint8_result_buffer; + // Resize interpration + int interpolation = cv::INTER_LINEAR; if (is_resized) { if (infer_results_dtype == FDDataType::INT64 || infer_results_dtype == FDDataType::INT32 ){ - FDTensorCast2Uint8(&infer_result, infer_chw, &uint8_result_buffer); - } + FDTensorCast2Uint8(&infer_result, infer_chw, &uint8_result_buffer); + // label map resize with nearest interpolation + interpolation = cv::INTER_NEAREST; + } mat = std::move(Mat::Create(infer_result, ProcLib::OPENCV)); - Resize::Run(&mat, input_width, input_height, -1.0f, -1.0f, 1, false, ProcLib::OPENCV); + Resize::Run(&mat, input_width, input_height, -1.0f, -1.0f, interpolation, false, ProcLib::OPENCV); mat.ShareWithTensor(&infer_result); } result->shape = infer_result.shape; diff --git a/fastdeploy/vision/segmentation/ppseg/postprocessor.h b/fastdeploy/vision/segmentation/ppseg/postprocessor.h index a42e25397..89c8371ee 100644 --- a/fastdeploy/vision/segmentation/ppseg/postprocessor.h +++ b/fastdeploy/vision/segmentation/ppseg/postprocessor.h @@ -20,7 +20,8 @@ namespace fastdeploy { namespace vision { namespace segmentation { - +/*! @brief Postprocessor object for PaddleSeg serials model. + */ class FASTDEPLOY_DECL PaddleSegPostprocessor { public: /** \brief Create a postprocessor instance for PaddleSeg serials model diff --git a/fastdeploy/vision/segmentation/ppseg/preprocessor.h b/fastdeploy/vision/segmentation/ppseg/preprocessor.h index 77ac36d93..faa7fb8de 100644 --- a/fastdeploy/vision/segmentation/ppseg/preprocessor.h +++ b/fastdeploy/vision/segmentation/ppseg/preprocessor.h @@ -18,7 +18,8 @@ namespace fastdeploy { namespace vision { namespace segmentation { - +/*! @brief Preprocessor object for PaddleSeg serials model. + */ class FASTDEPLOY_DECL PaddleSegPreprocessor { public: /** \brief Create a preprocessor instance for PaddleSeg serials model diff --git a/fastdeploy/vision/visualize/segmentation.cc b/fastdeploy/vision/visualize/segmentation.cc index 43f857250..9e4fe4149 100644 --- a/fastdeploy/vision/visualize/segmentation.cc +++ b/fastdeploy/vision/visualize/segmentation.cc @@ -25,6 +25,8 @@ namespace fastdeploy { namespace vision { #ifdef __ARM_NEON +static constexpr int VIS_SEG_OMP_NUM_THREADS=2; + static inline void QuantizeBlendingWeight8( float weight, uint8_t* old_multi_factor, uint8_t* new_multi_factor) { // Quantize the weight to boost blending performance. @@ -53,7 +55,8 @@ static cv::Mat FastVisSegmentationNEON( const uint8_t *im_ptr = static_cast(im.data); if (!quantize_weight) { - #pragma omp parallel for num_threads(2) schedule(static) + #pragma omp parallel for proc_bind(close) \ + num_threads(VIS_SEG_OMP_NUM_THREADS) schedule(static) for (int i = 0; i < size - 15; i += 16) { uint8x16_t labelx16 = vld1q_u8(label_ptr + i); // 16 bytes // e.g 0b00000001 << 7 -> 0b10000000 128; @@ -87,7 +90,8 @@ static cv::Mat FastVisSegmentationNEON( if (new_multi_factor == 8) { // Only keep mask, no need to blending with origin image. - #pragma omp parallel for num_threads(2) schedule(static) + #pragma omp parallel for proc_bind(close) \ + num_threads(VIS_SEG_OMP_NUM_THREADS) schedule(static) for (int i = 0; i < size - 15; i += 16) { uint8x16_t labelx16 = vld1q_u8(label_ptr + i); // 16 bytes // e.g 0b00000001 << 7 -> 0b10000000 128; @@ -112,7 +116,8 @@ static cv::Mat FastVisSegmentationNEON( uint8x16_t old_mulx16 = vdupq_n_u8(old_multi_factor); uint8x16_t new_mulx16 = vdupq_n_u8(new_multi_factor); // Blend the two colors together with quantize 'weight'. - #pragma omp parallel for num_threads(2) schedule(static) + #pragma omp parallel for proc_bind(close) \ + num_threads(VIS_SEG_OMP_NUM_THREADS) schedule(static) for (int i = 0; i < size - 15; i += 16) { uint8x16x3_t bgrx16x3 = vld3q_u8(im_ptr + i * 3); // 48 bytes uint8x16_t labelx16 = vld1q_u8(label_ptr + i); // 16 bytes diff --git a/fastdeploy/vision/visualize/visualize.h b/fastdeploy/vision/visualize/visualize.h index ea543553f..498944c23 100755 --- a/fastdeploy/vision/visualize/visualize.h +++ b/fastdeploy/vision/visualize/visualize.h @@ -20,9 +20,11 @@ #include "fastdeploy/vision/tracking/pptracking/model.h" namespace fastdeploy { +/** \brief All C++ FastDeploy Vision Models APIs are defined inside this namespace +* +*/ namespace vision { -// This class will deprecated, please not use it class FASTDEPLOY_DECL Visualize { public: static int num_classes_; @@ -52,35 +54,108 @@ class FASTDEPLOY_DECL Visualize { std::vector GenerateColorMap(int num_classes = 1000); cv::Mat RemoveSmallConnectedArea(const cv::Mat& alpha_pred, float threshold); +/** \brief Show the visualized results 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] 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 VisDetection(const cv::Mat& im, const DetectionResult& result, 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 VisDetection(const cv::Mat& im, const DetectionResult& result, const std::vector& labels, 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 + * \param[in] result the result produced by model + * \param[in] top_k the length of return values, e.g., if topk==2, the result will include the 2 most possible class label for input image. + * \param[in] score_threshold threshold for top_k scores, the class will not be shown if the score is less than score_threshold + * \param[in] font_size font size + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisClassification( const cv::Mat& im, const ClassifyResult& result, int top_k = 5, float score_threshold = 0.0f, float font_size = 0.5f); +/** \brief Show the visualized results with custom labels for classification 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 custom labels for user, the visualized result will show the corresponding custom labels + * \param[in] top_k the length of return values, e.g., if topk==2, the result will include the 2 most possible class label for input image. + * \param[in] score_threshold threshold for top_k scores, the class will not be shown if the score is less than score_threshold + * \param[in] font_size font size + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisClassification( const cv::Mat& im, const ClassifyResult& result, const std::vector& labels, int top_k = 5, float score_threshold = 0.0f, float font_size = 0.5f); +/** \brief Show the visualized results for face 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] 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 VisFaceDetection(const cv::Mat& im, const FaceDetectionResult& result, int line_size = 1, float font_size = 0.5f); +/** \brief Show the visualized results for face alignment 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] line_size line size for circle point + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisFaceAlignment(const cv::Mat& im, const FaceAlignmentResult& result, int line_size = 1); +/** \brief Show the visualized results for segmentation 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] weight transparent weight of visualized result image + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisSegmentation(const cv::Mat& im, const SegmentationResult& result, float weight = 0.5); +/** \brief Show the visualized results for matting 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] remove_small_connected_area if remove_small_connected_area==true, the visualized result will not include the small connected areas + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisMatting(const cv::Mat& im, const MattingResult& result, bool remove_small_connected_area = false); +/** \brief Show the visualized results for Ocr 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 + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisOcr(const cv::Mat& im, const OCRResult& ocr_result); FASTDEPLOY_DECL cv::Mat VisMOT(const cv::Mat& img, const MOTResult& results, @@ -93,6 +168,13 @@ FASTDEPLOY_DECL cv::Mat SwapBackground(const cv::Mat& im, const cv::Mat& background, const SegmentationResult& result, int background_label); +/** \brief Show the visualized results for key point 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] results the result produced by model + * \param[in] conf_threshold threshold for result scores, the result will not be shown if the score is less than conf_threshold + * \return cv::Mat type stores the visualized results + */ FASTDEPLOY_DECL cv::Mat VisKeypointDetection(const cv::Mat& im, const KeyPointDetectionResult& results, float conf_threshold = 0.5f); diff --git a/java/android/README.md b/java/android/README.md index 4647d916b..d3328f344 100644 --- a/java/android/README.md +++ b/java/android/README.md @@ -26,11 +26,11 @@ FastDeploy Android SDK 目前支持图像分类、目标检测、OCR文字识别
### 下载 FastDeploy Android SDK -Release版本(Java SDK 目前仅支持Android,当前版本为0.8.0 pre-release) +Release版本(Java SDK 目前仅支持Android,当前版本为 1.0.0) | 平台 | 文件 | 说明 | | :--- | :--- | :---- | -| Android Java SDK | [fastdeploy-android-sdk-0.8.0.aar](https://bj.bcebos.com/fastdeploy/release/android/fastdeploy-android-sdk-0.8.0.aar) | NDK 20 编译产出, minSdkVersion 15,targetSdkVersion 28 | +| Android Java SDK | [fastdeploy-android-sdk-1.0.0.aar](https://bj.bcebos.com/fastdeploy/release/android/fastdeploy-android-sdk-1.0.0.aar) | NDK 20 编译产出, minSdkVersion 15,targetSdkVersion 28 | 更多预编译库信息,请参考: [download_prebuilt_libraries.md](../../docs/cn/build_and_install/download_prebuilt_libraries.md) @@ -349,6 +349,8 @@ public class FaceDetectionResult { public class RuntimeOption { public void enableLiteFp16(); // 开启fp16精度推理 public void disableLiteFP16(); // 关闭fp16精度推理 + public void enableLiteInt8(); // 开启int8精度推理,针对量化模型 + public void disableLiteInt8(); // 关闭int8精度推理 public void setCpuThreadNum(int threadNum); // 设置线程数 public void setLitePowerMode(LitePowerMode mode); // 设置能耗模式 public void setLitePowerMode(String modeStr); // 通过字符串形式设置能耗模式 diff --git a/java/android/app/build.gradle b/java/android/app/build.gradle index a92d0a13c..23b204135 100644 --- a/java/android/app/build.gradle +++ b/java/android/app/build.gradle @@ -5,7 +5,7 @@ android { defaultConfig { applicationId 'com.baidu.paddle.fastdeploy.app.examples' - minSdkVersion 15 + minSdkVersion 16 //noinspection ExpiredTargetSdkVersion targetSdkVersion 28 versionCode 1 @@ -19,7 +19,6 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } - } dependencies { @@ -30,6 +29,7 @@ dependencies { implementation 'com.android.support:design:28.0.0' implementation 'org.jetbrains:annotations:15.0' // implementation project(path: ':fastdeploy') + implementation project(path: ':ui') //noinspection GradleDependency testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' @@ -68,6 +68,10 @@ def FD_MODEL = [ [ 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/portrait_pp_humansegv2_lite_256x144_inference_model.tgz', 'dest': 'src/main/assets/models' + ], + [ + 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/PP_TinyPose_128x96_infer.tgz', + 'dest': 'src/main/assets/models' ] ] @@ -75,12 +79,16 @@ def FD_JAVA_SDK = [ [ 'src' : 'https://bj.bcebos.com/fastdeploy/test/fastdeploy-android-sdk-latest-dev.aar', 'dest': 'libs' + ], + [ + 'src' : 'https://bj.bcebos.com/fastdeploy/test/bdasr_V3_20210628_cfe8c44.aar', + 'dest': 'libs' ] ] task downloadAndExtractModels(type: DefaultTask) { doFirst { - println "Downloading and extracting fastdeploy models ..." + println "[INFO] Downloading and extracting fastdeploy models ..." } doLast { String cachePath = "cache" @@ -90,19 +98,24 @@ task downloadAndExtractModels(type: DefaultTask) { FD_MODEL.eachWithIndex { model, index -> String[] modelPaths = model.src.split("/") String modelName = modelPaths[modelPaths.length - 1] - // Download the target model if not exists - boolean copyFiles = !file("${model.dest}").exists() - if (!file("${cachePath}/${modelName}").exists()) { - println "Downloading ${model.src} -> ${cachePath}/${modelName}" - ant.get(src: model.src, dest: file("${cachePath}/${modelName}")) + String modelPrefix = modelName.substring(0, modelName.length() - 4) + boolean copyFiles = false + if (!file("${model.dest}/${modelPrefix}").exists()) { + // Download the target model if not exists + if (!file("${cachePath}/${modelName}").exists()) { + println "[INFO] Downloading ${model.src} -> ${cachePath}/${modelName}" + ant.get(src: model.src, dest: file("${cachePath}/${modelName}")) + } copyFiles = true } if (copyFiles) { - println "Coping ${cachePath}/${modelName} -> ${model.dest}" + println "[INFO] Taring ${cachePath}/${modelName} -> ${model.dest}/${modelPrefix}" copy { from tarTree("${cachePath}/${modelName}") into "${model.dest}" } + } else { + println "[INFO] ${model.dest}/${modelPrefix} already exists!" } } } @@ -110,7 +123,7 @@ task downloadAndExtractModels(type: DefaultTask) { task downloadAndExtractSDKs(type: DefaultTask) { doFirst { - println "Downloading and extracting fastdeploy android java sdk ..." + println "[INFO] Downloading and extracting fastdeploy android java sdk ..." } doLast { String cachePath = "cache" @@ -120,23 +133,27 @@ task downloadAndExtractSDKs(type: DefaultTask) { FD_JAVA_SDK.eachWithIndex { sdk, index -> String[] sdkPaths = sdk.src.split("/") String sdkName = sdkPaths[sdkPaths.length - 1] - // Download the target SDK if not exists - boolean copyFiles = !file("${sdk.dest}/${sdkName}").exists() - if (!file("${cachePath}/${sdkName}").exists()) { - println "Downloading ${sdk.src} -> ${cachePath}/${sdkName}" - ant.get(src: sdk.src, dest: file("${cachePath}/${sdkName}")) + boolean copyFiles = false + if (!file("${sdk.dest}/${sdkName}").exists()) { + // Download the target SDK if not exists + if (!file("${cachePath}/${sdkName}").exists()) { + println "[INFO] Downloading ${sdk.src} -> ${cachePath}/${sdkName}" + ant.get(src: sdk.src, dest: file("${cachePath}/${sdkName}")) + } copyFiles = true } if (copyFiles) { - println "Coping ${cachePath}/${sdkName} -> ${sdk.dest}/${sdkName}" + println "[INFO] Coping ${cachePath}/${sdkName} -> ${sdk.dest}/${sdkName}" copy { from "${cachePath}/${sdkName}" into "${sdk.dest}" } + } else { + println "[INFO] ${sdk.dest}/${sdkName} already exists!" } } } } preBuild.dependsOn downloadAndExtractSDKs -preBuild.dependsOn downloadAndExtractModels \ No newline at end of file +preBuild.dependsOn downloadAndExtractModels diff --git a/java/android/app/src/main/AndroidManifest.xml b/java/android/app/src/main/AndroidManifest.xml index 858ef04f6..9a809c9a4 100644 --- a/java/android/app/src/main/AndroidManifest.xml +++ b/java/android/app/src/main/AndroidManifest.xml @@ -15,12 +15,16 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + + + diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationMainActivity.java index 54fece396..7992a7f89 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationMainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationMainActivity.java @@ -1,8 +1,8 @@ package com.baidu.paddle.fastdeploy.app.examples.classification; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.readTxt; +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; +import static com.baidu.paddle.fastdeploy.ui.Utils.readTxt; import android.Manifest; import android.annotation.SuppressLint; @@ -20,7 +20,6 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -32,13 +31,12 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.adapter.BaseResultAdapter; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.adapter.BaseResultAdapter; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.ClassifyResult; -import com.baidu.paddle.fastdeploy.vision.Visualize; import com.baidu.paddle.fastdeploy.vision.classification.PaddleClasModel; import java.math.BigDecimal; @@ -407,7 +405,7 @@ public class ClassificationMainActivity extends Activity implements View.OnClick } } } - BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.classification_result_page_item, results); + BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.base_result_page_item, results); resultView.setAdapter(adapter); resultView.invalidate(); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationSettingsActivity.java index 23ab16f9a..2f5000195 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationSettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationSettingsActivity.java @@ -10,8 +10,8 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; import java.util.ArrayList; import java.util.List; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationWelcomeActivity.java new file mode 100644 index 000000000..05396dfdd --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/classification/ClassificationWelcomeActivity.java @@ -0,0 +1,31 @@ +package com.baidu.paddle.fastdeploy.app.examples.classification; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class ClassificationWelcomeActivity extends Activity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.classification_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(ClassificationWelcomeActivity.this, ClassificationMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java index 127711767..33e4acea1 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionMainActivity.java @@ -1,5 +1,9 @@ package com.baidu.paddle.fastdeploy.app.examples.detection; +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; +import static com.baidu.paddle.fastdeploy.ui.Utils.readTxt; + import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; @@ -16,7 +20,6 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -28,19 +31,15 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.adapter.BaseResultAdapter; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.adapter.BaseResultAdapter; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.DetectionResult; import com.baidu.paddle.fastdeploy.vision.Visualize; import com.baidu.paddle.fastdeploy.vision.detection.PicoDet; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.readTxt; - import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -406,7 +405,7 @@ public class DetectionMainActivity extends Activity implements View.OnClickListe } } } - BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.detection_result_page_item, results); + BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.base_result_page_item, results); resultView.setAdapter(adapter); resultView.invalidate(); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionSettingsActivity.java index 21984fdcc..510a5a691 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionSettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionSettingsActivity.java @@ -10,8 +10,8 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; -import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; import java.util.ArrayList; import java.util.List; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionWelcomeActivity.java new file mode 100644 index 000000000..a5764a737 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/DetectionWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.detection; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class DetectionWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.detection_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(DetectionWelcomeActivity.this, DetectionMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantMainActivity.java new file mode 100644 index 000000000..cd1592502 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantMainActivity.java @@ -0,0 +1,211 @@ +package com.baidu.paddle.fastdeploy.app.examples.ernie.applications; + +import static com.baidu.paddle.fastdeploy.ui.Utils.isNetworkAvailable; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.baidu.aip.asrwakeup3.core.mini.AutoCheck; +import com.baidu.aip.asrwakeup3.core.util.AuthUtil; +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.speech.EventListener; +import com.baidu.speech.EventManager; +import com.baidu.speech.EventManagerFactory; +import com.baidu.speech.asr.SpeechConstant; + +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class VoiceAssistantMainActivity extends Activity implements View.OnClickListener, EventListener { + private Button startVoiceBtn; + private TextView voiceOutput; + private Button startIntentBtn; + private TextView intentOutput; + private ImageView back; + private EventManager asr; + private Boolean isStartVoice = false; + private String voiceTxt = ""; + private int times = 0; + private final int REQUEST_PERMISSION = 0; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Fullscreen + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.voice_assistant_activity_main); + + init(); + } + + private void init() { + checkPermission(); + asr = EventManagerFactory.create(this, "asr"); + asr.registerListener(this); + startVoiceBtn = findViewById(R.id.btn_voice); + startVoiceBtn.setOnClickListener(this); + voiceOutput = findViewById(R.id.tv_voice_output); + back = findViewById(R.id.iv_back); + back.setOnClickListener(this); + startIntentBtn = findViewById(R.id.btn_intent); + startIntentBtn.setOnClickListener(this); + intentOutput = findViewById(R.id.tv_intent_output); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_voice: + if (!isNetworkAvailable(this)) { + new AlertDialog.Builder(VoiceAssistantMainActivity.this) + .setMessage("请先连接互联网。") + .setCancelable(true) + .show(); + return; + } + if (!isStartVoice) { + isStartVoice = true; + startVoiceBtn.setText("停止录音"); + start(); + } else { + isStartVoice = false; + startVoiceBtn.setText("开始录音"); + stop(); + } + break; + case R.id.iv_back: + finish(); + break; + case R.id.btn_intent: + if (voiceTxt.equals("")) { + new AlertDialog.Builder(VoiceAssistantMainActivity.this) + .setMessage("请先录音。") + .setCancelable(true) + .show(); + return; + } + intentOutput.setText("我刚才说了:" + voiceTxt); + break; + } + } + + @Override + public void onEvent(String name, String params, byte[] data, int offset, int length) { + if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) { + if (params.contains("\"final_result\"")) { + if (params.contains("[")) { + voiceTxt = params.substring(params.lastIndexOf('[') + 1, params.lastIndexOf(']')); + } + voiceOutput.setText(voiceTxt); + } + } + } + + private void start() { + Map params = AuthUtil.getParam(); + String event = null; + event = SpeechConstant.ASR_START; + params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false); + (new AutoCheck(getApplicationContext(), new Handler() { + public void handleMessage(Message msg) { + if (msg.what == 100) { + AutoCheck autoCheck = (AutoCheck) msg.obj; + synchronized (autoCheck) { + String message = autoCheck.obtainErrorMessage(); + Log.e(getClass().getName(), message); + } + } + } + }, false)).checkAsr(params); + String json = null; + json = new JSONObject(params).toString(); + asr.send(event, json, null, 0, 0); + } + + private void stop() { + asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); + } + + @Override + protected void onPause() { + super.onPause(); + asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0); + asr.unregisterListener(this); + } + + private void checkPermission() { + times++; + final List permissionsList = new ArrayList<>(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if ((checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)) + permissionsList.add(Manifest.permission.RECORD_AUDIO); + if ((checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)) + permissionsList.add(Manifest.permission.ACCESS_NETWORK_STATE); + if ((checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED)) { + permissionsList.add(Manifest.permission.INTERNET); + } + if ((checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) { + permissionsList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + if (permissionsList.size() != 0) { + if (times == 1) { + requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), + REQUEST_PERMISSION); + } else { + new AlertDialog.Builder(this) + .setCancelable(true) + .setTitle("提示") + .setMessage("获取不到授权,APP将无法正常使用,请允许APP获取权限!") + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), + REQUEST_PERMISSION); + } + } + }).setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + finish(); + } + }).show(); + } + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + checkPermission(); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantWelcomeActivity.java new file mode 100644 index 000000000..f81c1c0ca --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ernie/applications/VoiceAssistantWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.ernie.applications; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class VoiceAssistantWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.voice_assistant_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(VoiceAssistantWelcomeActivity.this, VoiceAssistantMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java index 1891f99e3..e92c9998e 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetMainActivity.java @@ -1,5 +1,8 @@ package com.baidu.paddle.fastdeploy.app.examples.facedet; +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; + import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; @@ -16,7 +19,6 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -28,18 +30,15 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.adapter.BaseResultAdapter; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.adapter.BaseResultAdapter; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.FaceDetectionResult; import com.baidu.paddle.fastdeploy.vision.Visualize; import com.baidu.paddle.fastdeploy.vision.facedet.SCRFD; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; - import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -405,7 +404,7 @@ public class FaceDetMainActivity extends Activity implements View.OnClickListene } } } - BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.facedet_result_page_item, results); + BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.base_result_page_item, results); resultView.setAdapter(adapter); resultView.invalidate(); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetSettingsActivity.java index ed82c5b59..d56251b73 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetSettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetSettingsActivity.java @@ -10,8 +10,8 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; import java.util.ArrayList; import java.util.List; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetWelcomeActivity.java new file mode 100644 index 000000000..f2fd6c53e --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/facedet/FaceDetWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.facedet; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class FaceDetWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.facedet_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(FaceDetWelcomeActivity.this, FaceDetMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionMainActivity.java new file mode 100644 index 000000000..ab7acc624 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionMainActivity.java @@ -0,0 +1,403 @@ +package com.baidu.paddle.fastdeploy.app.examples.keypointdetection; + +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.vision.SegmentationResult; +import com.baidu.paddle.fastdeploy.vision.Visualize; +import com.baidu.paddle.fastdeploy.vision.KeyPointDetectionResult; +import com.baidu.paddle.fastdeploy.vision.keypointdetection.PPTinyPose; + +import java.util.ArrayList; +import java.util.List; + + +public class KeyPointDetectionMainActivity extends Activity implements View.OnClickListener, CameraSurfaceView.OnTextureChangedListener { + private static final String TAG = KeyPointDetectionMainActivity.class.getSimpleName(); + + CameraSurfaceView svPreview; + TextView tvStatus; + ImageButton btnSwitch; + ImageButton btnShutter; + ImageButton btnSettings; + ImageView realtimeToggleButton; + boolean isRealtimeStatusRunning = false; + ImageView backInPreview; + private ImageView albumSelectButton; + private View cameraPageView; + private ViewGroup resultPageView; + private ImageView resultImage; + private ImageView backInResult; + private ResultListView resultView; + private Bitmap shutterBitmap; + private Bitmap picBitmap; + private boolean isShutterBitmapCopied = false; + + public static final int TYPE_UNKNOWN = -1; + public static final int BTN_SHUTTER = 0; + public static final int ALBUM_SELECT = 1; + public static final int REALTIME_DETECT = 2; + private static int TYPE = REALTIME_DETECT; + + private static final int REQUEST_PERMISSION_CODE_STORAGE = 101; + private static final int INTENT_CODE_PICK_IMAGE = 100; + private static final int TIME_SLEEP_INTERVAL = 50; // ms + + long timeElapsed = 0; + long frameCounter = 0; + + // Call 'init' and 'release' manually later + PPTinyPose predictor = new PPTinyPose(); + private List results = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Fullscreen + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.keypointdetection_activity_main); + + // Clear all setting items to avoid app crashing due to the incorrect settings + initSettings(); + + // Check and request CAMERA and WRITE_EXTERNAL_STORAGE permissions + if (!checkAllPermissions()) { + requestAllPermissions(); + } + + // Init the camera preview and UI components + initView(); + } + + @SuppressLint("NonConstantResourceId") + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_switch: + svPreview.switchCamera(); + break; + case R.id.btn_shutter: + TYPE = BTN_SHUTTER; + shutterAndPauseCamera(); + resultView.setAdapter(null); + break; + case R.id.btn_settings: + startActivity(new Intent(this, KeyPointDetectionSettingsActivity.class)); + break; + case R.id.realtime_toggle_btn: + toggleRealtimeStyle(); + break; + case R.id.back_in_preview: + finish(); + break; + case R.id.album_select: + TYPE = ALBUM_SELECT; + // Judge whether authority has been granted. + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + // If this permission was requested before the application but the user refused the request, this method will return true. + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE_STORAGE); + } else { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + startActivityForResult(intent, INTENT_CODE_PICK_IMAGE); + } + resultView.setAdapter(null); + break; + case R.id.back_in_result: + back(); + break; + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + back(); + } + + private void back() { + resultPageView.setVisibility(View.GONE); + cameraPageView.setVisibility(View.VISIBLE); + TYPE = REALTIME_DETECT; + isShutterBitmapCopied = false; + svPreview.onResume(); + results.clear(); + } + + private void shutterAndPauseCamera() { + new Thread(new Runnable() { + @Override + public void run() { + try { + // Sleep some times to ensure picture has been correctly shut. + Thread.sleep(TIME_SLEEP_INTERVAL * 10); // 500ms + } catch (InterruptedException e) { + e.printStackTrace(); + } + runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + public void run() { + // These codes will run in main thread. + svPreview.onPause(); + cameraPageView.setVisibility(View.GONE); + resultPageView.setVisibility(View.VISIBLE); + if (shutterBitmap != null && !shutterBitmap.isRecycled()) { + detail(shutterBitmap); + } else { + new AlertDialog.Builder(KeyPointDetectionMainActivity.this) + .setTitle("Empty Result!") + .setMessage("Current picture is empty, please shutting it again!") + .setCancelable(true) + .show(); + } + } + }); + } + }).start(); + } + + private void copyBitmapFromCamera(Bitmap ARGB8888ImageBitmap) { + if (isShutterBitmapCopied || ARGB8888ImageBitmap == null) { + return; + } + if (!ARGB8888ImageBitmap.isRecycled()) { + synchronized (this) { + shutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true); + } + SystemClock.sleep(TIME_SLEEP_INTERVAL); + isShutterBitmapCopied = true; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == INTENT_CODE_PICK_IMAGE) { + if (resultCode == Activity.RESULT_OK) { + cameraPageView.setVisibility(View.GONE); + resultPageView.setVisibility(View.VISIBLE); + Uri uri = data.getData(); + String path = getRealPathFromURI(this, uri); + Bitmap bitmap = decodeBitmap(path, 720, 1280); + picBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); + SystemClock.sleep(TIME_SLEEP_INTERVAL * 10); // 500ms + detail(picBitmap); + } + } + } + + private void toggleRealtimeStyle() { + if (isRealtimeStatusRunning) { + isRealtimeStatusRunning = false; + realtimeToggleButton.setImageResource(R.drawable.realtime_stop_btn); + svPreview.setOnTextureChangedListener(this); + tvStatus.setVisibility(View.VISIBLE); + } else { + isRealtimeStatusRunning = true; + realtimeToggleButton.setImageResource(R.drawable.realtime_start_btn); + tvStatus.setVisibility(View.GONE); + isShutterBitmapCopied = false; + // Camera is still working but detecting loop is on pause. + svPreview.setOnTextureChangedListener(new CameraSurfaceView.OnTextureChangedListener() { + @Override + public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { + if (TYPE == BTN_SHUTTER) { + copyBitmapFromCamera(ARGB8888ImageBitmap); + } + return false; + } + }); + } + } + + @Override + public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { + if (TYPE == BTN_SHUTTER) { + copyBitmapFromCamera(ARGB8888ImageBitmap); + return false; + } + + boolean modified = false; + + long tc = System.currentTimeMillis(); + KeyPointDetectionResult result = predictor.predict(ARGB8888ImageBitmap); + timeElapsed += (System.currentTimeMillis() - tc); + + Visualize.visKeypointDetection(ARGB8888ImageBitmap, result, 0.f); + + modified = result.initialized(); + + frameCounter++; + if (frameCounter >= 30) { + final int fps = (int) (1000 / (timeElapsed / 30)); + runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + public void run() { + tvStatus.setText(Integer.toString(fps) + "fps"); + } + }); + frameCounter = 0; + timeElapsed = 0; + } + return modified; + } + + @Override + protected void onResume() { + super.onResume(); + // Reload settings and re-initialize the predictor + checkAndUpdateSettings(); + // Open camera until the permissions have been granted + if (!checkAllPermissions()) { + svPreview.disableCamera(); + } else { + svPreview.enableCamera(); + } + svPreview.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + svPreview.onPause(); + } + + @Override + protected void onDestroy() { + if (predictor != null) { + predictor.release(); + } + super.onDestroy(); + } + + public void initView() { + TYPE = REALTIME_DETECT; + // (1) EXPECTED_PREVIEW_WIDTH should mean 'height' and EXPECTED_PREVIEW_HEIGHT + // should mean 'width' if the camera display orientation is 90 | 270 degree + // (Hold the phone upright to record video) + // (2) Smaller resolution is more suitable for Human Pose detection on mobile + // device. So, we set this preview size (720,480) here. Reference: + // https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.5/configs/keypoint/tiny_pose + CameraSurfaceView.EXPECTED_PREVIEW_WIDTH = 720; + CameraSurfaceView.EXPECTED_PREVIEW_HEIGHT = 480; + svPreview = (CameraSurfaceView) findViewById(R.id.sv_preview); + svPreview.setOnTextureChangedListener(this); + + tvStatus = (TextView) findViewById(R.id.tv_status); + btnSwitch = (ImageButton) findViewById(R.id.btn_switch); + btnSwitch.setOnClickListener(this); + btnShutter = (ImageButton) findViewById(R.id.btn_shutter); + btnShutter.setOnClickListener(this); + btnSettings = (ImageButton) findViewById(R.id.btn_settings); + btnSettings.setOnClickListener(this); + realtimeToggleButton = findViewById(R.id.realtime_toggle_btn); + realtimeToggleButton.setOnClickListener(this); + backInPreview = findViewById(R.id.back_in_preview); + backInPreview.setOnClickListener(this); + albumSelectButton = findViewById(R.id.album_select); + albumSelectButton.setOnClickListener(this); + cameraPageView = findViewById(R.id.camera_page); + resultPageView = findViewById(R.id.result_page); + resultImage = findViewById(R.id.result_image); + backInResult = findViewById(R.id.back_in_result); + backInResult.setOnClickListener(this); + resultView = findViewById(R.id.result_list_view); + } + + private void detail(Bitmap bitmap) { + predictor.predict(bitmap, true, 5.f); + resultImage.setImageBitmap(bitmap); + } + + @SuppressLint("ApplySharedPref") + public void initSettings() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.clear(); + editor.commit(); + KeyPointDetectionSettingsActivity.resetSettings(); + } + + public void checkAndUpdateSettings() { + if (KeyPointDetectionSettingsActivity.checkAndUpdateSettings(this)) { + String realModelDir = getCacheDir() + "/" + KeyPointDetectionSettingsActivity.modelDir; + Utils.copyDirectoryFromAssets(this, KeyPointDetectionSettingsActivity.modelDir, realModelDir); + + String modelFile = realModelDir + "/" + "model.pdmodel"; + String paramsFile = realModelDir + "/" + "model.pdiparams"; + String configFile = realModelDir + "/" + "infer_cfg.yml"; + RuntimeOption option = new RuntimeOption(); + option.setCpuThreadNum(KeyPointDetectionSettingsActivity.cpuThreadNum); + option.setLitePowerMode(KeyPointDetectionSettingsActivity.cpuPowerMode); + if (Boolean.parseBoolean(KeyPointDetectionSettingsActivity.enableLiteFp16)) { + option.enableLiteFp16(); + } + predictor.setUseDark(true); + predictor.init(modelFile, paramsFile, configFile, option); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) { + new AlertDialog.Builder(KeyPointDetectionMainActivity.this) + .setTitle("Permission denied") + .setMessage("Click to force quit the app, then open Settings->Apps & notifications->Target " + + "App->Permissions to grant all of the permissions.") + .setCancelable(false) + .setPositiveButton("Exit", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + KeyPointDetectionMainActivity.this.finish(); + } + }).show(); + } + } + + private void requestAllPermissions() { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.CAMERA}, 0); + } + + private boolean checkAllPermissions() { + return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED + && ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; + } + +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionSettingsActivity.java new file mode 100644 index 000000000..d80abd7bd --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionSettingsActivity.java @@ -0,0 +1,164 @@ +package com.baidu.paddle.fastdeploy.app.examples.keypointdetection; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.PreferenceManager; +import android.support.v7.app.ActionBar; + +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; + +import java.util.ArrayList; +import java.util.List; + + +public class KeyPointDetectionSettingsActivity extends AppCompatPreferenceActivity implements + SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = KeyPointDetectionSettingsActivity.class.getSimpleName(); + + static public int selectedModelIdx = -1; + static public String modelDir = ""; + static public int cpuThreadNum = 2; + static public String cpuPowerMode = ""; + static public String enableLiteFp16 = "true"; + + ListPreference lpChoosePreInstalledModel = null; + EditTextPreference etModelDir = null; + ListPreference lpCPUThreadNum = null; + ListPreference lpCPUPowerMode = null; + ListPreference lpEnableLiteFp16 = null; + + List preInstalledModelDirs = null; + List preInstalledCPUThreadNums = null; + List preInstalledCPUPowerModes = null; + List preInstalledEnableLiteFp16s = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.keypointdetection_settting); + ActionBar supportActionBar = getSupportActionBar(); + if (supportActionBar != null) { + supportActionBar.setDisplayHomeAsUpEnabled(true); + } + + // Initialize pre-installed models + preInstalledModelDirs = new ArrayList(); + preInstalledCPUThreadNums = new ArrayList(); + preInstalledCPUPowerModes = new ArrayList(); + preInstalledEnableLiteFp16s = new ArrayList(); + preInstalledModelDirs.add(getString(R.string.KEYPOINT_DETECTION_MODEL_DIR_DEFAULT)); + preInstalledCPUThreadNums.add(getString(R.string.CPU_THREAD_NUM_DEFAULT)); + preInstalledCPUPowerModes.add(getString(R.string.CPU_POWER_MODE_DEFAULT)); + preInstalledEnableLiteFp16s.add(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + + // Setup UI components + lpChoosePreInstalledModel = + (ListPreference) findPreference(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY)); + String[] preInstalledModelNames = new String[preInstalledModelDirs.size()]; + for (int i = 0; i < preInstalledModelDirs.size(); i++) { + preInstalledModelNames[i] = preInstalledModelDirs.get(i).substring(preInstalledModelDirs.get(i).lastIndexOf("/") + 1); + } + lpChoosePreInstalledModel.setEntries(preInstalledModelNames); + lpChoosePreInstalledModel.setEntryValues(preInstalledModelDirs.toArray(new String[preInstalledModelDirs.size()])); + lpCPUThreadNum = (ListPreference) findPreference(getString(R.string.CPU_THREAD_NUM_KEY)); + lpCPUPowerMode = (ListPreference) findPreference(getString(R.string.CPU_POWER_MODE_KEY)); + etModelDir = (EditTextPreference) findPreference(getString(R.string.MODEL_DIR_KEY)); + etModelDir.setTitle("Model dir (SDCard: " + Utils.getSDCardDirectory() + ")"); + lpEnableLiteFp16 = (ListPreference) findPreference(getString(R.string.ENABLE_LITE_FP16_MODE_KEY)); + } + + @SuppressLint("ApplySharedPref") + private void reloadSettingsAndUpdateUI() { + SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences(); + + String selected_model_dir = sharedPreferences.getString(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY), + getString(R.string.KEYPOINT_DETECTION_MODEL_DIR_DEFAULT)); + int selected_model_idx = lpChoosePreInstalledModel.findIndexOfValue(selected_model_dir); + if (selected_model_idx >= 0 && selected_model_idx < preInstalledModelDirs.size() && selected_model_idx != selectedModelIdx) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(getString(R.string.MODEL_DIR_KEY), preInstalledModelDirs.get(selected_model_idx)); + editor.putString(getString(R.string.CPU_THREAD_NUM_KEY), preInstalledCPUThreadNums.get(selected_model_idx)); + editor.putString(getString(R.string.CPU_POWER_MODE_KEY), preInstalledCPUPowerModes.get(selected_model_idx)); + editor.putString(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT), preInstalledEnableLiteFp16s.get(selected_model_idx)); + editor.commit(); + lpChoosePreInstalledModel.setSummary(selected_model_dir); + selectedModelIdx = selected_model_idx; + } + + String model_dir = sharedPreferences.getString(getString(R.string.MODEL_DIR_KEY), + getString(R.string.KEYPOINT_DETECTION_MODEL_DIR_DEFAULT)); + String cpu_thread_num = sharedPreferences.getString(getString(R.string.CPU_THREAD_NUM_KEY), + getString(R.string.CPU_THREAD_NUM_DEFAULT)); + String cpu_power_mode = sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY), + getString(R.string.CPU_POWER_MODE_DEFAULT)); + String enable_lite_fp16 = sharedPreferences.getString(getString(R.string.ENABLE_LITE_FP16_MODE_KEY), + getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + + etModelDir.setSummary(model_dir); + lpCPUThreadNum.setValue(cpu_thread_num); + lpCPUThreadNum.setSummary(cpu_thread_num); + lpCPUPowerMode.setValue(cpu_power_mode); + lpCPUPowerMode.setSummary(cpu_power_mode); + lpEnableLiteFp16.setValue(enable_lite_fp16); + lpEnableLiteFp16.setSummary(enable_lite_fp16); + } + + static boolean checkAndUpdateSettings(Context ctx) { + boolean settingsChanged = false; + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx); + + String model_dir = sharedPreferences.getString(ctx.getString(R.string.MODEL_DIR_KEY), + ctx.getString(R.string.KEYPOINT_DETECTION_MODEL_DIR_DEFAULT)); + settingsChanged |= !modelDir.equalsIgnoreCase(model_dir); + modelDir = model_dir; + + String cpu_thread_num = sharedPreferences.getString(ctx.getString(R.string.CPU_THREAD_NUM_KEY), + ctx.getString(R.string.CPU_THREAD_NUM_DEFAULT)); + settingsChanged |= cpuThreadNum != Integer.parseInt(cpu_thread_num); + cpuThreadNum = Integer.parseInt(cpu_thread_num); + + String cpu_power_mode = sharedPreferences.getString(ctx.getString(R.string.CPU_POWER_MODE_KEY), + ctx.getString(R.string.CPU_POWER_MODE_DEFAULT)); + settingsChanged |= !cpuPowerMode.equalsIgnoreCase(cpu_power_mode); + cpuPowerMode = cpu_power_mode; + + String enable_lite_fp16 = sharedPreferences.getString(ctx.getString(R.string.ENABLE_LITE_FP16_MODE_KEY), + ctx.getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); + settingsChanged |= !enableLiteFp16.equalsIgnoreCase(enable_lite_fp16); + enableLiteFp16 = enable_lite_fp16; + + return settingsChanged; + } + + static void resetSettings() { + selectedModelIdx = -1; + modelDir = ""; + cpuThreadNum = 2; + cpuPowerMode = ""; + enableLiteFp16 = "true"; + } + + @Override + protected void onResume() { + super.onResume(); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + reloadSettingsAndUpdateUI(); + } + + @Override + protected void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + reloadSettingsAndUpdateUI(); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionWelcomeActivity.java new file mode 100644 index 000000000..19da5d3fd --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/keypointdetection/KeyPointDetectionWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.keypointdetection; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class KeyPointDetectionWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.keypointdetection_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(KeyPointDetectionWelcomeActivity.this, KeyPointDetectionMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java index 4dc1885b3..e66d3e9ff 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrMainActivity.java @@ -1,7 +1,7 @@ package com.baidu.paddle.fastdeploy.app.examples.ocr; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; import android.Manifest; import android.annotation.SuppressLint; @@ -30,12 +30,13 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.adapter.BaseResultAdapter; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.pipeline.PPOCRv2; +import com.baidu.paddle.fastdeploy.pipeline.PPOCRv3; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.adapter.BaseResultAdapter; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.OCRResult; import com.baidu.paddle.fastdeploy.vision.Visualize; import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; @@ -403,7 +404,7 @@ public class OcrMainActivity extends Activity implements View.OnClickListener, C } } } - BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.ocr_result_page_item, results); + BaseResultAdapter adapter = new BaseResultAdapter(getBaseContext(), R.layout.base_result_page_item, results); resultView.setAdapter(adapter); resultView.invalidate(); @@ -424,9 +425,7 @@ public class OcrMainActivity extends Activity implements View.OnClickListener, C if (OcrSettingsActivity.checkAndUpdateSettings(this)) { String realModelDir = getCacheDir() + "/" + OcrSettingsActivity.modelDir; String detModelName = "ch_PP-OCRv2_det_infer"; - // String detModelName = "ch_ppocr_mobile_v2.0_det_infer"; String clsModelName = "ch_ppocr_mobile_v2.0_cls_infer"; - // String recModelName = "ch_ppocr_mobile_v2.0_rec_infer"; String recModelName = "ch_PP-OCRv2_rec_infer"; String realDetModelDir = realModelDir + "/" + detModelName; String realClsModelDir = realModelDir + "/" + clsModelName; @@ -461,11 +460,11 @@ public class OcrMainActivity extends Activity implements View.OnClickListener, C clsOption.enableLiteFp16(); recOption.enableLiteFp16(); } + DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption); Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption); Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption); predictor.init(detModel, clsModel, recModel); - } } diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java index 6f8c45ff4..f359b6593 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrSettingsActivity.java @@ -10,8 +10,8 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; import java.util.ArrayList; import java.util.List; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrWelcomeActivity.java new file mode 100644 index 000000000..553cc093c --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/OcrWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.ocr; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class OcrWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.ocr_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(OcrWelcomeActivity.this, OcrMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java index 3223fc07f..ec2ebbffa 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationMainActivity.java @@ -1,7 +1,7 @@ package com.baidu.paddle.fastdeploy.app.examples.segmentation; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.decodeBitmap; -import static com.baidu.paddle.fastdeploy.app.ui.Utils.getRealPathFromURI; +import static com.baidu.paddle.fastdeploy.ui.Utils.decodeBitmap; +import static com.baidu.paddle.fastdeploy.ui.Utils.getRealPathFromURI; import android.Manifest; import android.annotation.SuppressLint; @@ -19,7 +19,6 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -30,10 +29,10 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.SegmentationResult; import com.baidu.paddle.fastdeploy.vision.Visualize; import com.baidu.paddle.fastdeploy.vision.segmentation.PaddleSegModel; @@ -341,7 +340,7 @@ public class SegmentationMainActivity extends Activity implements View.OnClickLi } private void detail(Bitmap bitmap) { - predictor.predict(bitmap, true, 0.4f); + predictor.predict(bitmap, true, 0.7f); resultImage.setImageBitmap(bitmap); } @@ -368,7 +367,7 @@ public class SegmentationMainActivity extends Activity implements View.OnClickLi if (Boolean.parseBoolean(SegmentationSettingsActivity.enableLiteFp16)) { option.enableLiteFp16(); } - predictor.setVerticalScreenFlag(true); + predictor.setIsVerticalScreen(true); predictor.init(modelFile, paramsFile, configFile, option); } } diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationSettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationSettingsActivity.java index 866c2c712..ae32e960a 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationSettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationSettingsActivity.java @@ -10,8 +10,8 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.Utils; -import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; +import com.baidu.paddle.fastdeploy.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; import java.util.ArrayList; import java.util.List; @@ -96,8 +96,6 @@ public class SegmentationSettingsActivity extends AppCompatPreferenceActivity im getString(R.string.CPU_THREAD_NUM_DEFAULT)); String cpu_power_mode = sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY), getString(R.string.CPU_POWER_MODE_DEFAULT)); - String score_threshold = sharedPreferences.getString(getString(R.string.SCORE_THRESHOLD_KEY), - getString(R.string.SCORE_THRESHOLD_FACEDET)); String enable_lite_fp16 = sharedPreferences.getString(getString(R.string.ENABLE_LITE_FP16_MODE_KEY), getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT)); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationWelcomeActivity.java new file mode 100644 index 000000000..16ba8bf9d --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/segmentation/SegmentationWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.segmentation; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class SegmentationWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.segmentation_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(SegmentationWelcomeActivity.this, SegmentationMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/res/drawable/main_bk.png b/java/android/app/src/main/res/drawable/main_bk.png new file mode 100644 index 000000000..1ff9457d4 Binary files /dev/null and b/java/android/app/src/main/res/drawable/main_bk.png differ diff --git a/java/android/app/src/main/res/drawable/paddle_logo.png b/java/android/app/src/main/res/drawable/paddle_logo.png new file mode 100644 index 000000000..bc1135abf Binary files /dev/null and b/java/android/app/src/main/res/drawable/paddle_logo.png differ diff --git a/java/android/app/src/main/res/layout/classification_camera_page.xml b/java/android/app/src/main/res/layout/classification_camera_page.xml index 441c3e591..fd760b485 100644 --- a/java/android/app/src/main/res/layout/classification_camera_page.xml +++ b/java/android/app/src/main/res/layout/classification_camera_page.xml @@ -12,7 +12,7 @@ android:layout_height="match_parent" android:background="@color/colorWindow"> - @@ -53,9 +53,9 @@ android:textAlignment="center" android:textSize="15sp"/> - + - - - + - + android:dividerHeight="@dimen/result_list_gap_width"> diff --git a/java/android/app/src/main/res/layout/classification_welcome.xml b/java/android/app/src/main/res/layout/classification_welcome.xml new file mode 100644 index 000000000..7adb91dfb --- /dev/null +++ b/java/android/app/src/main/res/layout/classification_welcome.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + +