Add PaddleOCRv3 & PaddleOCRv2 Support (#139)

* Add PaddleOCR Support

* Add PaddleOCR Support

* Add PaddleOCRv3 Support

* Add PaddleOCRv3 Support

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Add PaddleOCRv3 Support

* Add PaddleOCRv3 Supports

* Add PaddleOCRv3 Suport

* Fix Rec diff

* Remove useless functions

* Remove useless comments

* Add PaddleOCRv2 Support
This commit is contained in:
yunyaoXYY
2022-08-27 15:09:30 +08:00
committed by GitHub
parent 820a5c5647
commit d96e98cd4d
45 changed files with 8323 additions and 2 deletions

View File

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

View File

@@ -0,0 +1,139 @@
# PPOCRSystemv2 C++部署示例
本目录下提供`infer.cc`快速完成PPOCRSystemv2在CPU/GPU以及GPU上通过TensorRT加速部署的示例。
在部署前,需确认以下两个步骤
- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../docs/the%20software%20and%20hardware%20requirements.md)
- 2. 根据开发环境下载预编译部署库和samples代码参考[FastDeploy预编译库](../../../../../docs/quick_start)
以Linux上CPU推理为例在本目录执行如下命令即可完成编译测试
```
mkdir build
cd build
wget https://https://bj.bcebos.com/paddlehub/fastdeploy/cpp/fastdeploy-linux-x64-gpu-0.2.0.tgz
tar xvf fastdeploy-linux-x64-0.2.0.tgz
cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/fastdeploy-linux-x64-0.2.0
make -j
# 下载模型,图片和label文件
wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar
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
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://raw.githubusercontent.com/PaddlePaddle/PaddleOCR/release/2.5/doc/imgs/12.jpg
wget https://raw.githubusercontent.com/PaddlePaddle/PaddleOCR/release/2.5/ppocr/utils/ppocr_keys_v1.txt
# CPU推理
./infer_demo ./ch_PP-OCRv2_det_infer ./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv2_rec_infer ./ppocr_keys_v1.txt ./12.jpg 0
# GPU推理
./infer_demo ./ch_PP-OCRv2_det_infer ./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv2_rec_infer ./ppocr_keys_v1.txt ./12.jpg 1
# GPU上TensorRT推理
./infer_demo ./ch_PP-OCRv2_det_infer ./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv2_rec_infer ./ppocr_keys_v1.txt ./12.jpg 2
# OCR还支持det/cls/rec三个模型的组合使用例如当我们不想使用cls模型的时候只需要给cls模型路径的位置传入一个空的字符串, 例子如下
./infer_demo ./ch_PP-OCRv2_det_infer "" ./ch_PP-OCRv2_rec_infer ./ppocr_keys_v1.txt ./12.jpg 0
```
运行完成可视化结果如下图所示
<img width="640" src="https://user-images.githubusercontent.com/109218879/185826024-f7593a0c-1bd2-4a60-b76c-15588484fa08.jpg">
## PPOCRSystemv2 C++接口
### PPOCRSystemv2类
```
fastdeploy::application::ocrsystem::PPOCRSystemv2(fastdeploy::vision::ocr::DBDetector* ocr_det = nullptr,
fastdeploy::vision::ocr::Classifier* ocr_cls = nullptr,
fastdeploy::vision::ocr::Recognizer* ocr_rec = nullptr);
```
PPOCRSystemv2 的初始化,由检测,分类和识别模型串联构成
**参数**
> * **DBDetector**(model): OCR中的检测模型
> * **Classifier**(model): OCR中的分类模型
> * **Recognizer**(model): OCR中的识别模型
#### Predict函数
> ```
> std::vector<std::vector<fastdeploy::vision::OCRResult>> ocr_results =
> PPOCRSystemv2.Predict(std::vector<cv::Mat> cv_all_imgs);
>
> ```
>
> 模型预测接口,输入一个可装入多张图片的图片列表,后可输出检测结果。
>
> **参数**
>
> > * **cv_all_imgs**: 输入图像注意需为HWCBGR格式
> > * **ocr_results**: 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 Frontend& model_format = Frontend::PADDLE);
```
DBDetector模型加载和初始化其中模型为paddle模型格式。
**参数**
> * **model_file**(str): 模型文件路径
> * **params_file**(str): 参数文件路径当模型格式为ONNX时此参数传入空字符串即可
> * **runtime_option**(RuntimeOption): 后端推理配置默认为None即采用默认配置
> * **model_format**(Frontend): 模型格式默认为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 Frontend& model_format = Frontend::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
- [模型介绍](../../)
- [Python部署](../python)
- [视觉模型预测结果](../../../../../docs/api/vision_results/)

View File

@@ -0,0 +1,295 @@
// 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 CpuInfer(const std::string& det_model_dir,
const std::string& cls_model_dir,
const std::string& rec_model_dir,
const std::string& rec_label_file,
const std::string& image_file) {
auto det_model_file = det_model_dir + sep + "inference.pdmodel";
auto det_params_file = det_model_dir + sep + "inference.pdiparams";
auto cls_model_file = cls_model_dir + sep + "inference.pdmodel";
auto cls_params_file = cls_model_dir + sep + "inference.pdiparams";
auto rec_model_file = rec_model_dir + sep + "inference.pdmodel";
auto rec_params_file = rec_model_dir + sep + "inference.pdiparams";
auto rec_label = rec_label_file;
fastdeploy::vision::ocr::DBDetector det_model;
fastdeploy::vision::ocr::Classifier cls_model;
fastdeploy::vision::ocr::Recognizer rec_model;
if (!det_model_dir.empty()) {
auto det_option = fastdeploy::RuntimeOption();
det_option.UseCpu();
det_model = fastdeploy::vision::ocr::DBDetector(
det_model_file, det_params_file, det_option);
if (!det_model.Initialized()) {
std::cerr << "Failed to initialize det_model." << std::endl;
return;
}
}
if (!cls_model_dir.empty()) {
auto cls_option = fastdeploy::RuntimeOption();
cls_option.UseCpu();
cls_model = fastdeploy::vision::ocr::Classifier(
cls_model_file, cls_params_file, cls_option);
if (!cls_model.Initialized()) {
std::cerr << "Failed to initialize cls_model." << std::endl;
return;
}
}
if (!rec_model_dir.empty()) {
auto rec_option = fastdeploy::RuntimeOption();
rec_option.UseCpu();
rec_option.UsePaddleBackend(); // OCRv2的rec模型暂不支持ORT后端
rec_model = fastdeploy::vision::ocr::Recognizer(
rec_model_file, rec_params_file, rec_label, rec_option);
if (!rec_model.Initialized()) {
std::cerr << "Failed to initialize rec_model." << std::endl;
return;
}
}
auto ocrv2_app = fastdeploy::application::ocrsystem::PPOCRSystemv2(
&det_model, &cls_model, &rec_model);
auto im = cv::imread(image_file);
auto im_bak = im.clone();
fastdeploy::vision::OCRResult res;
//开始预测
if (!ocrv2_app.Predict(&im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
//输出预测信息
std::cout << res.Str() << std::endl;
//可视化
auto vis_img = fastdeploy::vision::Visualize::VisOcr(im_bak, res);
cv::imwrite("vis_result.jpg", vis_img);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
}
void GpuInfer(const std::string& det_model_dir,
const std::string& cls_model_dir,
const std::string& rec_model_dir,
const std::string& rec_label_file,
const std::string& image_file) {
auto det_model_file = det_model_dir + sep + "inference.pdmodel";
auto det_params_file = det_model_dir + sep + "inference.pdiparams";
auto cls_model_file = cls_model_dir + sep + "inference.pdmodel";
auto cls_params_file = cls_model_dir + sep + "inference.pdiparams";
auto rec_model_file = rec_model_dir + sep + "inference.pdmodel";
auto rec_params_file = rec_model_dir + sep + "inference.pdiparams";
auto rec_label = rec_label_file;
fastdeploy::vision::ocr::DBDetector det_model;
fastdeploy::vision::ocr::Classifier cls_model;
fastdeploy::vision::ocr::Recognizer rec_model;
//准备模型
if (!det_model_dir.empty()) {
auto det_option = fastdeploy::RuntimeOption();
det_option.UseGpu();
det_model = fastdeploy::vision::ocr::DBDetector(
det_model_file, det_params_file, det_option);
if (!det_model.Initialized()) {
std::cerr << "Failed to initialize det_model." << std::endl;
return;
}
}
if (!cls_model_dir.empty()) {
auto cls_option = fastdeploy::RuntimeOption();
cls_option.UseGpu();
cls_model = fastdeploy::vision::ocr::Classifier(
cls_model_file, cls_params_file, cls_option);
if (!cls_model.Initialized()) {
std::cerr << "Failed to initialize cls_model." << std::endl;
return;
}
}
if (!rec_model_dir.empty()) {
auto rec_option = fastdeploy::RuntimeOption();
rec_option.UseGpu();
rec_option
.UsePaddleBackend(); // OCRv2的rec模型暂不支持ORT后端与PaddleInference
// v2.3.2
rec_model = fastdeploy::vision::ocr::Recognizer(
rec_model_file, rec_params_file, rec_label, rec_option);
if (!rec_model.Initialized()) {
std::cerr << "Failed to initialize rec_model." << std::endl;
return;
}
}
auto ocrv2_app = fastdeploy::application::ocrsystem::PPOCRSystemv2(
&det_model, &cls_model, &rec_model);
auto im = cv::imread(image_file);
auto im_bak = im.clone();
fastdeploy::vision::OCRResult res;
//开始预测
if (!ocrv2_app.Predict(&im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
//输出预测信息
std::cout << res.Str() << std::endl;
//可视化
auto vis_img = fastdeploy::vision::Visualize::VisOcr(im_bak, res);
cv::imwrite("vis_result.jpg", vis_img);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
}
void TrtInfer(const std::string& det_model_dir,
const std::string& cls_model_dir,
const std::string& rec_model_dir,
const std::string& rec_label_file,
const std::string& image_file) {
auto det_model_file = det_model_dir + sep + "inference.pdmodel";
auto det_params_file = det_model_dir + sep + "inference.pdiparams";
auto cls_model_file = cls_model_dir + sep + "inference.pdmodel";
auto cls_params_file = cls_model_dir + sep + "inference.pdiparams";
auto rec_model_file = rec_model_dir + sep + "inference.pdmodel";
auto rec_params_file = rec_model_dir + sep + "inference.pdiparams";
auto rec_label = rec_label_file;
fastdeploy::vision::ocr::DBDetector det_model;
fastdeploy::vision::ocr::Classifier cls_model;
fastdeploy::vision::ocr::Recognizer rec_model;
//准备模型
if (!det_model_dir.empty()) {
auto det_option = fastdeploy::RuntimeOption();
det_option.UseGpu();
det_option.UseTrtBackend();
det_option.SetTrtInputShape("x", {1, 3, 50, 50}, {1, 3, 640, 640},
{1, 3, 960, 960});
det_model = fastdeploy::vision::ocr::DBDetector(
det_model_file, det_params_file, det_option);
if (!det_model.Initialized()) {
std::cerr << "Failed to initialize det_model." << std::endl;
return;
}
}
if (!cls_model_dir.empty()) {
auto cls_option = fastdeploy::RuntimeOption();
cls_option.UseGpu();
cls_option.UseTrtBackend();
cls_option.SetTrtInputShape("x", {1, 3, 48, 192});
cls_model = fastdeploy::vision::ocr::Classifier(
cls_model_file, cls_params_file, cls_option);
if (!cls_model.Initialized()) {
std::cerr << "Failed to initialize cls_model." << std::endl;
return;
}
}
if (!rec_model_dir.empty()) {
auto rec_option = fastdeploy::RuntimeOption();
rec_option.UseGpu();
rec_option.UseTrtBackend();
rec_option.SetTrtInputShape("x", {1, 3, 48, 10}, {1, 3, 48, 320},
{1, 3, 48, 2000});
rec_model = fastdeploy::vision::ocr::Recognizer(
rec_model_file, rec_params_file, rec_label, rec_option);
if (!rec_model.Initialized()) {
std::cerr << "Failed to initialize rec_model." << std::endl;
return;
}
}
auto ocrv2_app = fastdeploy::application::ocrsystem::PPOCRSystemv2(
&det_model, &cls_model, &rec_model);
auto im = cv::imread(image_file);
auto im_bak = im.clone();
fastdeploy::vision::OCRResult res;
//开始预测
if (!ocrv2_app.Predict(&im, &res)) {
std::cerr << "Failed to predict." << std::endl;
return;
}
//输出预测信息
std::cout << res.Str() << std::endl;
//可视化
auto vis_img = fastdeploy::vision::Visualize::VisOcr(im_bak, res);
cv::imwrite("vis_result.jpg", vis_img);
std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
}
int main(int argc, char* argv[]) {
if (argc < 7) {
std::cout << "Usage: infer_demo path/to/det_model path/to/cls_model "
"path/to/rec_model path/to/rec_label_file path/to/image "
"run_option, "
"e.g ./infer_demo ./ch_PP-OCRv2_det_infer "
"./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv2_rec_infer "
"./ppocr_keys_v1.txt ./12.jpg 0"
<< std::endl;
std::cout << "The data type of run_option is int, 0: run with cpu; 1: run "
"with gpu; 2: run with gpu and use tensorrt backend."
<< std::endl;
return -1;
}
if (std::atoi(argv[6]) == 0) {
CpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]);
} else if (std::atoi(argv[6]) == 1) {
GpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]);
} else if (std::atoi(argv[6]) == 2) {
TrtInfer(argv[1], argv[2], argv[3], argv[4], argv[5]);
}
return 0;
}