From abe4cd7a434c52cda7881506af59cf78ec247b83 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 11 May 2022 06:33:28 +0000 Subject: [PATCH 001/129] update doc for v3 det quant --- deploy/slim/quantization/README.md | 4 ++-- deploy/slim/quantization/README_en.md | 4 ++-- doc/doc_ch/inference_ppocr.md | 12 ++++++------ doc/doc_en/inference_ppocr_en.md | 11 +++++------ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/deploy/slim/quantization/README.md b/deploy/slim/quantization/README.md index 894a29be06..4c1d784b99 100644 --- a/deploy/slim/quantization/README.md +++ b/deploy/slim/quantization/README.md @@ -47,9 +47,9 @@ python deploy/slim/quantization/quant.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3 ``` # 下载检测预训练模型: wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar -tar xf https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar -python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3_det/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ +python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ ``` 如果要训练识别模型的量化,修改配置文件和加载的模型参数即可。 diff --git a/deploy/slim/quantization/README_en.md b/deploy/slim/quantization/README_en.md index ea77cb3811..33b2c4784a 100644 --- a/deploy/slim/quantization/README_en.md +++ b/deploy/slim/quantization/README_en.md @@ -54,9 +54,9 @@ Model distillation and model quantization can be used at the same time, taking t ``` # download provided model wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar -tar xf https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar -python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3_det/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ +python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ ``` If you want to quantify the text recognition model, you can modify the configuration file and loaded model parameters. diff --git a/doc/doc_ch/inference_ppocr.md b/doc/doc_ch/inference_ppocr.md index 946307556b..472c0003f9 100644 --- a/doc/doc_ch/inference_ppocr.md +++ b/doc/doc_ch/inference_ppocr.md @@ -59,7 +59,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/1.jpg" --det_model_di ### 2.1 超轻量中文识别模型推理 -**注意** `PP-OCRv3`的识别模型使用的输入shape为`3,48,320`, 需要添加参数`--rec_image_shape=3,48,320`,如果不使用`PP-OCRv3`的识别模型,则无需设置该参数。 +**注意** `PP-OCRv3`的识别模型使用的输入shape为`3,48,320`, 如果使用其他识别模型,则需根据模型设置参数`--rec_image_shape`。此外,`PP-OCRv3`的识别模型默认使用的`rec_algorithm`为`SVTR_LCNet`,注意和原始`SVTR`的区别。 超轻量中文识别模型推理,可以执行如下命令: @@ -67,7 +67,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/1.jpg" --det_model_di # 下载超轻量中文识别模型: wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar tar xf ch_PP-OCRv3_rec_infer.tar -python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/ch/word_4.jpg" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --rec_image_shape=3,48,320 +python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/ch/word_4.jpg" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" ``` ![](../imgs_words/ch/word_4.jpg) @@ -121,17 +121,17 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['0', 0.9999982] ## 4. 文本检测、方向分类和文字识别串联推理 -**注意** `PP-OCRv3`的识别模型使用的输入shape为`3,48,320`, 需要添加参数`--rec_image_shape=3,48,320`,如果不使用`PP-OCRv3`的识别模型,则无需设置该参数。 +**注意** `PP-OCRv3`的识别模型使用的输入shape为`3,48,320`, 如果使用其他识别模型,则需根据模型设置参数`--rec_image_shape`。此外,`PP-OCRv3`的识别模型默认使用的`rec_algorithm`为`SVTR_LCNet`,注意和原始`SVTR`的区别。 以超轻量中文OCR模型推理为例,在执行预测时,需要通过参数`image_dir`指定单张图像或者图像集合的路径、参数`det_model_dir`,`cls_model_dir`和`rec_model_dir`分别指定检测,方向分类和识别的inference模型路径。参数`use_angle_cls`用于控制是否启用方向分类模型。`use_mp`表示是否使用多进程。`total_process_num`表示在使用多进程时的进程数。可视化识别结果默认保存到 ./inference_results 文件夹里面。 ```shell # 使用方向分类器 -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=true --rec_image_shape=3,48,320 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=true # 不使用方向分类器 -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false --rec_image_shape=3,48,320 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false # 使用多进程 -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 --rec_image_shape=3,48,320 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 ``` 执行命令后,识别结果图像如下: diff --git a/doc/doc_en/inference_ppocr_en.md b/doc/doc_en/inference_ppocr_en.md index dcfb738e76..acf3b25b44 100755 --- a/doc/doc_en/inference_ppocr_en.md +++ b/doc/doc_en/inference_ppocr_en.md @@ -56,7 +56,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/1.jpg" --det_model_di ### 1. Lightweight Chinese Recognition Model Inference -**Note**: The input shape used by the recognition model of `PP-OCRv3` is `3,48,320`, and the parameter `--rec_image_shape=3,48,320` needs to be added. If the recognition model of `PP-OCRv3` is not used, this parameter does not need to be set. +**Note**: The input shape used by the recognition model of `PP-OCRv3` is `3, 48, 320`. If you use other recognition models, you need to set the parameter `--rec_image_shape` according to the model. In addition, the `rec_algorithm` used by the recognition model of `PP-OCRv3` is `SVTR_LCNet` by default. Note the difference from the original `SVTR`. For lightweight Chinese recognition model inference, you can execute the following commands: @@ -120,19 +120,18 @@ After executing the command, the prediction results (classification angle and sc ## Text Detection Angle Classification and Recognition Inference Concatenation -**Note**: The input shape used by the recognition model of `PP-OCRv3` is `3,48,320`, and the parameter `--rec_image_shape=3,48,320` needs to be added. If the recognition model of `PP-OCRv3` is not used, this parameter does not need to be set. +**Note**: The input shape used by the recognition model of `PP-OCRv3` is `3, 48, 320`. If you use other recognition models, you need to set the parameter `--rec_image_shape` according to the model. In addition, the `rec_algorithm` used by the recognition model of `PP-OCRv3` is `SVTR_LCNet` by default. Note the difference from the original `SVTR`. When performing prediction, you need to specify the path of a single image or a folder of images through the parameter `image_dir`, the parameter `det_model_dir` specifies the path to detect the inference model, the parameter `cls_model_dir` specifies the path to angle classification inference model and the parameter `rec_model_dir` specifies the path to identify the inference model. The parameter `use_angle_cls` is used to control whether to enable the angle classification model. The parameter `use_mp` specifies whether to use multi-process to infer `total_process_num` specifies process number when using multi-process. The parameter . The visualized recognition results are saved to the `./inference_results` folder by default. ```shell # use direction classifier -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=true --rec_image_shape=3,48,320 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=true # not use use direction classifier -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false --rec_image_shape=3,48,320 - +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false # use multi-process -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 --rec_image_shape=3,48,320 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 ``` From 5cc7b1334b93ff7eed39118010871cb10cc72bb9 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 11 May 2022 06:36:44 +0000 Subject: [PATCH 002/129] update doc for v3 infer --- doc/doc_en/inference_ppocr_en.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/doc_en/inference_ppocr_en.md b/doc/doc_en/inference_ppocr_en.md index acf3b25b44..935f92f514 100755 --- a/doc/doc_en/inference_ppocr_en.md +++ b/doc/doc_en/inference_ppocr_en.md @@ -126,12 +126,12 @@ When performing prediction, you need to specify the path of a single image or a ```shell # use direction classifier -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=true +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --cls_model_dir="./cls/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=true # not use use direction classifier -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false # use multi-process -python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv2_det_infer/" --rec_model_dir="./ch_PP-OCRv2_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 +python3 tools/infer/predict_system.py --image_dir="./doc/imgs/00018069.jpg" --det_model_dir="./ch_PP-OCRv3_det_infer/" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --use_angle_cls=false --use_mp=True --total_process_num=6 ``` From a6f5282973321b452c399b87895dbb29adf50a31 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 12 May 2022 16:14:18 +0800 Subject: [PATCH 003/129] fix --- ppocr/data/imaug/label_ops.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 02a5187dad..8b017b3219 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -438,10 +438,10 @@ class KieLabelEncode(object): texts.append(ann['transcription']) text_ind = [self.dict[c] for c in text if c in self.dict] text_inds.append(text_ind) - if 'label' in anno.keys(): + if 'label' in ann.keys(): labels.append(ann['label']) - elif 'key_cls' in anno.keys(): - labels.append(anno['key_cls']) + elif 'key_cls' in ann.keys(): + labels.append(ann['key_cls']) else: raise ValueError("Cannot found 'key_cls' in ann.keys(), please check your training annotation.") edges.append(ann.get('edge', 0)) From 01aeda4f6b52f36756f8ce82bfc739af856891e5 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 12 May 2022 11:59:02 +0000 Subject: [PATCH 004/129] add ppocrv3 tipc & test=document_fix --- deploy/cpp_infer/src/main.cpp | 16 +- deploy/cpp_infer/src/ocr_det.cpp | 56 ++--- deploy/cpp_infer/src/ocr_rec.cpp | 8 +- deploy/pdserving/pipeline_http_client.py | 26 ++- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++ ...rmal_normal_infer_python_linux_gpu_cpu.txt | 19 ++ ...nux_gpu_normal_normal_lite_cpp_arm_cpu.txt | 13 ++ ..._normal_normal_lite_cpp_arm_gpu_opencl.txt | 13 ++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++ ...nux_gpu_normal_normal_lite_cpp_arm_cpu.txt | 13 ++ ..._normal_normal_lite_cpp_arm_gpu_opencl.txt | 13 ++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 14 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 18 ++ .../ch_PP-OCRv3_det/train_infer_python.txt | 53 +++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 +++++ ...rmal_normal_infer_python_linux_gpu_cpu.txt | 21 ++ .../train_infer_python.txt | 53 +++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 +++++ .../ch_PP-OCRv3_rec_distillation.yml | 205 ++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 14 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 18 ++ .../ch_PP-OCRv3_rec/train_infer_python.txt | 53 +++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 +++++ ...rmal_normal_infer_python_linux_gpu_cpu.txt | 21 ++ .../train_infer_python.txt | 53 +++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 +++++ test_tipc/prepare.sh | 81 ++++++- test_tipc/prepare_lite_cpp.sh | 2 + test_tipc/test_inference_cpp.sh | 4 +- test_tipc/test_inference_python.sh | 4 +- test_tipc/test_paddle2onnx.sh | 41 +++- test_tipc/test_serving.sh | 32 ++- test_tipc/test_train_inference_python.sh | 2 +- 34 files changed, 1072 insertions(+), 66 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt diff --git a/deploy/cpp_infer/src/main.cpp b/deploy/cpp_infer/src/main.cpp index b6085257e7..c4b5b97ea8 100644 --- a/deploy/cpp_infer/src/main.cpp +++ b/deploy/cpp_infer/src/main.cpp @@ -77,13 +77,19 @@ int main(int argc, char **argv) { for (int i = 0; i < cv_all_img_names.size(); ++i) { if (FLAGS_benchmark) { cout << cv_all_img_names[i] << '\t'; - for (int n = 0; n < ocr_results[i].size(); n++) { - for (int m = 0; m < ocr_results[i][n].box.size(); m++) { - cout << ocr_results[i][n].box[m][0] << ' ' - << ocr_results[i][n].box[m][1] << ' '; + if (FLAGS_rec && FLAGS_det) { + Utility::print_result(ocr_results[i]); + } else if (FLAGS_det) { + for (int n = 0; n < ocr_results[i].size(); n++) { + for (int m = 0; m < ocr_results[i][n].box.size(); m++) { + cout << ocr_results[i][n].box[m][0] << ' ' + << ocr_results[i][n].box[m][1] << ' '; + } } + cout << endl; + } else { + Utility::print_result(ocr_results[i]); } - cout << endl; } else { cout << cv_all_img_names[i] << "\n"; Utility::print_result(ocr_results[i]); diff --git a/deploy/cpp_infer/src/ocr_det.cpp b/deploy/cpp_infer/src/ocr_det.cpp index c08f97b55a..550997e719 100644 --- a/deploy/cpp_infer/src/ocr_det.cpp +++ b/deploy/cpp_infer/src/ocr_det.cpp @@ -32,40 +32,46 @@ void DBDetector::LoadModel(const std::string &model_dir) { if (this->precision_ == "int8") { precision = paddle_infer::Config::Precision::kInt8; } - config.EnableTensorRtEngine(1 << 20, 10, 3, precision, false, false); + config.EnableTensorRtEngine(1 << 20, 1, 20, precision, false, false); std::map> min_input_shape = { {"x", {1, 3, 50, 50}}, - {"conv2d_92.tmp_0", {1, 96, 20, 20}}, - {"conv2d_91.tmp_0", {1, 96, 10, 10}}, - {"nearest_interp_v2_1.tmp_0", {1, 96, 10, 10}}, - {"nearest_interp_v2_2.tmp_0", {1, 96, 20, 20}}, - {"nearest_interp_v2_3.tmp_0", {1, 24, 20, 20}}, - {"nearest_interp_v2_4.tmp_0", {1, 24, 20, 20}}, - {"nearest_interp_v2_5.tmp_0", {1, 24, 20, 20}}, + {"conv2d_92.tmp_0", {1, 120, 20, 20}}, + {"conv2d_91.tmp_0", {1, 24, 10, 10}}, + {"conv2d_59.tmp_0", {1, 96, 20, 20}}, + {"nearest_interp_v2_1.tmp_0", {1, 256, 10, 10}}, + {"nearest_interp_v2_2.tmp_0", {1, 256, 20, 20}}, + {"conv2d_124.tmp_0", {1, 256, 20, 20}}, + {"nearest_interp_v2_3.tmp_0", {1, 64, 20, 20}}, + {"nearest_interp_v2_4.tmp_0", {1, 64, 20, 20}}, + {"nearest_interp_v2_5.tmp_0", {1, 64, 20, 20}}, {"elementwise_add_7", {1, 56, 2, 2}}, - {"nearest_interp_v2_0.tmp_0", {1, 96, 2, 2}}}; + {"nearest_interp_v2_0.tmp_0", {1, 256, 2, 2}}}; std::map> max_input_shape = { {"x", {1, 3, this->max_side_len_, this->max_side_len_}}, - {"conv2d_92.tmp_0", {1, 96, 400, 400}}, - {"conv2d_91.tmp_0", {1, 96, 200, 200}}, - {"nearest_interp_v2_1.tmp_0", {1, 96, 200, 200}}, - {"nearest_interp_v2_2.tmp_0", {1, 96, 400, 400}}, - {"nearest_interp_v2_3.tmp_0", {1, 24, 400, 400}}, - {"nearest_interp_v2_4.tmp_0", {1, 24, 400, 400}}, - {"nearest_interp_v2_5.tmp_0", {1, 24, 400, 400}}, + {"conv2d_92.tmp_0", {1, 120, 400, 400}}, + {"conv2d_91.tmp_0", {1, 24, 200, 200}}, + {"conv2d_59.tmp_0", {1, 96, 400, 400}}, + {"nearest_interp_v2_1.tmp_0", {1, 256, 200, 200}}, + {"nearest_interp_v2_2.tmp_0", {1, 256, 400, 400}}, + {"conv2d_124.tmp_0", {1, 256, 400, 400}}, + {"nearest_interp_v2_3.tmp_0", {1, 64, 400, 400}}, + {"nearest_interp_v2_4.tmp_0", {1, 64, 400, 400}}, + {"nearest_interp_v2_5.tmp_0", {1, 64, 400, 400}}, {"elementwise_add_7", {1, 56, 400, 400}}, - {"nearest_interp_v2_0.tmp_0", {1, 96, 400, 400}}}; + {"nearest_interp_v2_0.tmp_0", {1, 256, 400, 400}}}; std::map> opt_input_shape = { {"x", {1, 3, 640, 640}}, - {"conv2d_92.tmp_0", {1, 96, 160, 160}}, - {"conv2d_91.tmp_0", {1, 96, 80, 80}}, - {"nearest_interp_v2_1.tmp_0", {1, 96, 80, 80}}, - {"nearest_interp_v2_2.tmp_0", {1, 96, 160, 160}}, - {"nearest_interp_v2_3.tmp_0", {1, 24, 160, 160}}, - {"nearest_interp_v2_4.tmp_0", {1, 24, 160, 160}}, - {"nearest_interp_v2_5.tmp_0", {1, 24, 160, 160}}, + {"conv2d_92.tmp_0", {1, 120, 160, 160}}, + {"conv2d_91.tmp_0", {1, 24, 80, 80}}, + {"conv2d_59.tmp_0", {1, 96, 160, 160}}, + {"nearest_interp_v2_1.tmp_0", {1, 256, 80, 80}}, + {"nearest_interp_v2_2.tmp_0", {1, 256, 160, 160}}, + {"conv2d_124.tmp_0", {1, 256, 160, 160}}, + {"nearest_interp_v2_3.tmp_0", {1, 64, 160, 160}}, + {"nearest_interp_v2_4.tmp_0", {1, 64, 160, 160}}, + {"nearest_interp_v2_5.tmp_0", {1, 64, 160, 160}}, {"elementwise_add_7", {1, 56, 40, 40}}, - {"nearest_interp_v2_0.tmp_0", {1, 96, 40, 40}}}; + {"nearest_interp_v2_0.tmp_0", {1, 256, 40, 40}}}; config.SetTRTDynamicShapeInfo(min_input_shape, max_input_shape, opt_input_shape); diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp index f69f37b8f5..0a6fe693e2 100644 --- a/deploy/cpp_infer/src/ocr_rec.cpp +++ b/deploy/cpp_infer/src/ocr_rec.cpp @@ -143,15 +143,17 @@ void CRNNRecognizer::LoadModel(const std::string &model_dir) { if (this->precision_ == "int8") { precision = paddle_infer::Config::Precision::kInt8; } - config.EnableTensorRtEngine(1 << 20, 10, 3, precision, false, false); + config.EnableTensorRtEngine(1 << 20, 10, 15, precision, false, false); int imgH = this->rec_image_shape_[1]; int imgW = this->rec_image_shape_[2]; std::map> min_input_shape = { {"x", {1, 3, imgH, 10}}, {"lstm_0.tmp_0", {10, 1, 96}}}; std::map> max_input_shape = { - {"x", {1, 3, imgH, 2000}}, {"lstm_0.tmp_0", {1000, 1, 96}}}; + {"x", {this->rec_batch_num_, 3, imgH, 2500}}, + {"lstm_0.tmp_0", {1000, 1, 96}}}; std::map> opt_input_shape = { - {"x", {1, 3, imgH, imgW}}, {"lstm_0.tmp_0", {25, 1, 96}}}; + {"x", {this->rec_batch_num_, 3, imgH, imgW}}, + {"lstm_0.tmp_0", {25, 1, 96}}}; config.SetTRTDynamicShapeInfo(min_input_shape, max_input_shape, opt_input_shape); diff --git a/deploy/pdserving/pipeline_http_client.py b/deploy/pdserving/pipeline_http_client.py index 7bc4d882e5..a1226a9469 100644 --- a/deploy/pdserving/pipeline_http_client.py +++ b/deploy/pdserving/pipeline_http_client.py @@ -19,8 +19,16 @@ import base64 import os import argparse + + +def str2bool(v): + return v.lower() in ("true", "t", "1") + + parser = argparse.ArgumentParser(description="args for paddleserving") parser.add_argument("--image_dir", type=str, default="../../doc/imgs/") +parser.add_argument("--det", type=str2bool, default=True) +parser.add_argument("--rec", type=str2bool, default=True) args = parser.parse_args() @@ -46,13 +54,17 @@ for idx, img_file in enumerate(os.listdir(test_img_dir)): # check success if result["err_no"] == 0: ocr_result = result["value"][0] - try: - for item in eval(ocr_result): - # return transcription and points - print("{}, {}".format(item[0], item[1])) - except Exception as e: - print("No results") - continue + if not args.det: + print(ocr_result) + else: + try: + for item in eval(ocr_result): + # return transcription and points + print("{}, {}".format(item[0], item[1])) + except Exception as e: + print(ocr_result) + print("No results") + continue else: print( diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..63e7ff6556 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ocr_system_v3.0 +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--benchmark:True +--det:True +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..a044826501 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================ch_PP-OCRv2=========================== +model_name:ch_PP-OCRv3 +python:python3.7 +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_system.py --rec_image_shape="3,48,320" +--use_gpu:False|True +--enable_mkldnn:False|True +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--benchmark:True +null:null +null:null diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt new file mode 100644 index 0000000000..133a78c84f --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt @@ -0,0 +1,13 @@ +===========================lite_params=========================== +inference:./ocr_db_crnn system +runtime_device:ARM_CPU +det_infer_model:ch_PP-OCRv3_det_infer|ch_PP-OCRv3_det_slim_quant_infer +rec_infer_model:ch_PP-OCRv3_rec_infer|ch_PP-OCRv3_rec_slim_quant_infer +cls_infer_model:ch_ppocr_mobile_v2.0_cls_infer|ch_ppocr_mobile_v2.0_cls_slim_infer +--cpu_threads:1|4 +--det_batch_size:1 +--rec_batch_size:1 +--image_dir:./test_data/icdar2015_lite/text_localization/ch4_test_images/ +--config_dir:./config.txt +--rec_dict_dir:./ppocr_keys_v1.txt +--benchmark:True diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt new file mode 100644 index 0000000000..86e49fc100 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt @@ -0,0 +1,13 @@ +===========================lite_params=========================== +inference:./ocr_db_crnn system +runtime_device:ARM_GPU_OPENCL +det_infer_model:ch_PP-OCRv3_det_infer|ch_PP-OCRv3_det_slim_quant_infer +rec_infer_model:ch_PP-OCRv3_rec_infer|ch_PP-OCRv3_rec_slim_quant_infer +cls_infer_model:ch_ppocr_mobile_v2.0_cls_infer|ch_ppocr_mobile_v2.0_cls_slim_infer +--cpu_threads:1|4 +--det_batch_size:1 +--rec_batch_size:1 +--image_dir:./test_data/icdar2015_lite/text_localization/ch4_test_images/ +--config_dir:./config.txt +--rec_dict_dir:./ppocr_keys_v1.txt +--benchmark:True diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..80fee50f76 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ocr_det_v3.0 +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt new file mode 100644 index 0000000000..cbc101f93b --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_cpu.txt @@ -0,0 +1,13 @@ +===========================lite_params=========================== +inference:./ocr_db_crnn det +runtime_device:ARM_CPU +det_infer_model:ch_PP-OCRv3_det_infer|ch_PP-OCRv3_det_slim_quant_infer +null:null +null:null +--cpu_threads:1|4 +--det_batch_size:1 +null:null +--image_dir:./test_data/icdar2015_lite/text_localization/ch4_test_images/ +--config_dir:./config.txt +null:null +--benchmark:True \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt new file mode 100644 index 0000000000..ba3f5b71e5 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_lite_cpp_arm_gpu_opencl.txt @@ -0,0 +1,13 @@ +===========================lite_params=========================== +inference:./ocr_db_crnn det +runtime_device:ARM_GPU_OPENCL +det_infer_model:ch_PP-OCRv3_det_infer|ch_PP-OCRv3_det_slim_quant_infer +null:null +null:null +--cpu_threads:1|4 +--det_batch_size:1 +null:null +--image_dir:./test_data/icdar2015_lite/text_localization/ch4_test_images/ +--config_dir:./config.txt +null:null +--benchmark:True diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..b4c681c0aa --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,14 @@ +===========================paddle2onnx_params=========================== +model_name:ocr_det_v3 +python:python3.7 +2onnx: paddle2onnx +--model_dir:./inference/ch_PP-OCRv3_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--save_file:./inference/det_v3_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_det.py +--use_gpu:True|False +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..624b13e0d5 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,18 @@ +===========================serving_params=========================== +model_name:ocr_det_v3 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--dirname:./inference/ch_PP-OCRv3_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--serving_server:./deploy/pdserving/ppocr_det_v3_serving/ +--serving_client:./deploy/pdserving/ppocr_det_v3_client/ +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:True|False +op.det.local_service_conf.thread_num:1|6 +op.det.local_service_conf.use_trt:False|True +op.det.local_service_conf.precision:fp32|fp16|int8 +pipline:pipeline_rpc_client.py|pipeline_http_client.py +--image_dir:../../doc/imgs diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt new file mode 100644 index 0000000000..93f673289a --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_det +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +quant_export:null +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..98bc36a80d --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_det +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +quant_export:null +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..e4a3aa6c61 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,21 @@ +===========================kl_quant_params=========================== +model_name:PPOCRv3_ocr_det_kl +python:python3.7 +Global.pretrained_model:null +Global.save_inference_dir:null +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:deploy/slim/quantization/quant_kl.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +infer_quant:True +inference:tools/infer/predict_det.py +--use_gpu:False|True +--enable_mkldnn:True +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt new file mode 100644 index 0000000000..f1ea7de5e5 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_det_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=1|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..6d6862607a --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_det_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml new file mode 100644 index 0000000000..4c8ba0a6fa --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml @@ -0,0 +1,205 @@ +Global: + debug: false + use_gpu: true + epoch_num: 800 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec_ppocr_v3_distillation + save_epoch_step: 3 + eval_batch_step: [0, 2000] + cal_metric_during_train: true + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: false + infer_img: doc/imgs_words/ch/word_1.jpg + character_dict_path: ppocr/utils/ppocr_keys_v1.txt + max_text_length: &max_text_length 25 + infer_mode: false + use_space_char: true + distributed: true + save_res_path: ./output/rec/predicts_ppocrv3_distillation.txt + + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.999 + lr: + name: Piecewise + decay_epochs : [700, 800] + values : [0.0005, 0.00005] + warmup_epoch: 5 + regularizer: + name: L2 + factor: 3.0e-05 + + +Architecture: + model_type: &model_type "rec" + name: DistillationModel + algorithm: Distillation + Models: + Teacher: + pretrained: + freeze_params: false + return_all_feats: true + model_type: *model_type + algorithm: SVTR + Transform: + Backbone: + name: MobileNetV1Enhance + scale: 0.5 + last_conv_stride: [1, 2] + last_pool_type: avg + Head: + name: MultiHead + head_list: + - CTCHead: + Neck: + name: svtr + dims: 64 + depth: 2 + hidden_dims: 120 + use_guide: True + Head: + fc_decay: 0.00001 + - SARHead: + enc_dim: 512 + max_text_length: *max_text_length + Student: + pretrained: + freeze_params: false + return_all_feats: true + model_type: *model_type + algorithm: SVTR + Transform: + Backbone: + name: MobileNetV1Enhance + scale: 0.5 + last_conv_stride: [1, 2] + last_pool_type: avg + Head: + name: MultiHead + head_list: + - CTCHead: + Neck: + name: svtr + dims: 64 + depth: 2 + hidden_dims: 120 + use_guide: True + Head: + fc_decay: 0.00001 + - SARHead: + enc_dim: 512 + max_text_length: *max_text_length +Loss: + name: CombinedLoss + loss_config_list: + - DistillationDMLLoss: + weight: 1.0 + act: "softmax" + use_log: true + model_name_pairs: + - ["Student", "Teacher"] + key: head_out + multi_head: True + dis_head: ctc + name: dml_ctc + - DistillationDMLLoss: + weight: 0.5 + act: "softmax" + use_log: true + model_name_pairs: + - ["Student", "Teacher"] + key: head_out + multi_head: True + dis_head: sar + name: dml_sar + - DistillationDistanceLoss: + weight: 1.0 + mode: "l2" + model_name_pairs: + - ["Student", "Teacher"] + key: backbone_out + - DistillationCTCLoss: + weight: 1.0 + model_name_list: ["Student", "Teacher"] + key: head_out + multi_head: True + - DistillationSARLoss: + weight: 1.0 + model_name_list: ["Student", "Teacher"] + key: head_out + multi_head: True + +PostProcess: + name: DistillationCTCLabelDecode + model_name: ["Student", "Teacher"] + key: head_out + multi_head: True + +Metric: + name: DistillationMetric + base_metric_name: RecMetric + main_indicator: acc + key: "Student" + ignore_space: True + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data/ + ext_op_transform_idx: 1 + label_file_list: + - ./train_data/ic15_data/rec_gt_train.txt + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - RecConAug: + prob: 0.5 + ext_data_num: 2 + image_shape: [48, 320, 3] + - RecAug: + - MultiLabelEncode: + - RecResizeImg: + image_shape: [3, 48, 320] + - KeepKeys: + keep_keys: + - image + - label_ctc + - label_sar + - length + - valid_ratio + loader: + shuffle: true + batch_size_per_card: 128 + drop_last: true + num_workers: 4 +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data + label_file_list: + - ./train_data/ic15_data/rec_gt_test.txt + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - MultiLabelEncode: + - RecResizeImg: + image_shape: [3, 48, 320] + - KeepKeys: + keep_keys: + - image + - label_ctc + - label_sar + - length + - valid_ratio + loader: + shuffle: false + drop_last: false + batch_size_per_card: 128 + num_workers: 4 diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..d338a1f222 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ocr_rec_v3.0 +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:6 +--use_tensorrt:False|True +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..eb1cbb9044 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,14 @@ +===========================paddle2onnx_params=========================== +model_name:ocr_rec_v3 +python:python3.7 +2onnx: paddle2onnx +--model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--save_file:./inference/rec_v3_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--rec_model_dir: +--image_dir:./inference/rec_inference \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..89bde9c8ce --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,18 @@ +===========================serving_params=========================== +model_name:ocr_rec_v3 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--dirname:./inference/ch_PP-OCRv3_rec_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--serving_server:./deploy/pdserving/ppocr_rec_v3_serving/ +--serving_client:./deploy/pdserving/ppocr_rec_v3_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.rec.local_service_conf.devices:gpu|null +op.rec.local_service_conf.use_mkldnn:False +op.rec.local_service_conf.thread_num:1|6 +op.rec.local_service_conf.use_trt:False|True +op.rec.local_service_conf.precision:fp32|fp16|int8 +pipline:pipeline_rpc_client.py|pipeline_http_client.py +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt new file mode 100644 index 0000000000..c333c08330 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:PPOCRv3_ocr_rec +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_infer +infer_export:null +infer_quant:False +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:False|True +--precision:fp32|int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..47cc3e2f53 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:PPOCRv3_ocr_rec +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_infer +infer_export:null +infer_quant:False +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:False|True +--precision:fp32|int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..51ad29a4ed --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,21 @@ +===========================kl_quant_params=========================== +model_name:PPOCRv3_ocr_rec_kl +python:python3.7 +Global.pretrained_model:null +Global.save_inference_dir:null +infer_model:./inference/ch_PP-OCRv3_rec_infer/ +infer_export:deploy/slim/quantization/quant_kl.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +infer_quant:True +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:False|True +--enable_mkldnn:False|True +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:True +--precision:int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt new file mode 100644 index 0000000000..fd7d61c372 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_rec_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +fpgm_export: null +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_slim_quant_infer +infer_export:null +infer_quant:True +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:False|True +--precision:fp32|int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..6049a377a6 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PPOCRv3_rec_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +fpgm_export: null +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_slim_quant_infer +infer_export:null +infer_quant:True +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:False|True +--precision:fp32|int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 6a8983009e..d5c9c4f84f 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -48,6 +48,11 @@ if [ ${MODE} = "lite_train_lite_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi + if [[ ${model_name} =~ "PPOCRv3_det" ]];then + # TODO check model link + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ + fi cd ./pretrain_models/ && tar xf det_mv3_db_v2.0_train.tar && cd ../ rm -rf ./train_data/icdar2015 rm -rf ./train_data/ic15_data @@ -68,6 +73,11 @@ if [ ${MODE} = "lite_train_lite_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_rec_train.tar && cd ../ fi + if [ ${model_name} == "ch_PPOCRv3_rec" ] || [ ${model_name} == "ch_PPOCRv3_rec_PACT" ]; then + # TODO check model link + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf ch_PP-OCRv3_rec_train.tar && cd ../ + fi if [ ${model_name} == "det_r18_db_v2_0" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/ResNet18_vd_pretrained.pdparams --no-check-certificate fi @@ -111,6 +121,11 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi + if [ ${model_name} == "ch_PPOCRv3_det" ]; then + # TODO check model link + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ + fi if [ ${model_name} == "en_server_pgnetA" ]; then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/total_text_lite.tar --no-check-certificate wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/pgnet/en_server_pgnetA.tar --no-check-certificate @@ -135,6 +150,11 @@ elif [ ${MODE} = "lite_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi + if [ ${model_name} == "ch_PPOCRv3_det" ]; then + # TODO check model link + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ + fi elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate @@ -169,17 +189,42 @@ elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && cd ../ fi + if [[ ${model_name} =~ "ch_PP-OCRv2" ]]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_PP-OCRv2_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + fi + if [[ ${model_name} =~ "ch_PP-OCRv3" ]]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + fi if [[ ${model_name} =~ "ch_PPOCRv2_det" ]]; then eval_model_name="ch_PP-OCRv2_det_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ fi + if [[ ${model_name} =~ "ch_PPOCRv3_det" ]]; then + # TODO check model link + eval_model_name="ch_PP-OCRv3_det_infer" + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ + fi if [[ ${model_name} =~ "PPOCRv2_ocr_rec" ]]; then eval_model_name="ch_PP-OCRv2_rec_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv2_rec_slim_quant_infer.tar && cd ../ fi + if [[ ${model_name} =~ "PPOCRv3_ocr_rec" ]]; then + # TODO check model link + eval_model_name="ch_PP-OCRv3_rec_infer" + echo $(pwd) + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + # wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_quant_infer.tar --no-check-certificate + cd ./inference && tar xf ${eval_model_name}.tar && cd ../ + # cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv3_rec_slim_quant_infer.tar && cd ../ + fi if [ ${model_name} == "en_server_pgnetA" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/pgnet/en_server_pgnetA.tar --no-check-certificate cd ./inference && tar xf en_server_pgnetA.tar && tar xf ch_det_data_50.tar && cd ../ @@ -286,11 +331,25 @@ if [ ${MODE} = "klquant_whole_infer" ]; then cd ./train_data/ && tar xf ic15_data.tar && cd ../ cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv2_rec_infer.tar && cd ../ fi + if [ ${model_name} = "PPOCRv3_ocr_rec_kl" ]; then + # TODO check model link + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate + cd ./train_data/ && tar xf ic15_data.tar && cd ../ + cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ + fi if [ ${model_name} = "PPOCRv2_ocr_det_kl" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi + if [ ${model_name} = "PPOCRv3_ocr_det_kl" ]; then + # TODO check model link + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + fi if [ ${model_name} = "ch_ppocr_mobile_v2.0_rec_KL" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate @@ -305,6 +364,14 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ocr_det_v3.0" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ocr_rec_v3.0" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ elif [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate @@ -314,6 +381,11 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ocr_system_v3.0" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi fi @@ -330,19 +402,26 @@ if [ ${MODE} = "serving_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_det_infer.tar && cd ../ fi if [ ${MODE} = "paddle2onnx_infer" ];then # prepare serving env python_name=$(func_parser_value "${lines[2]}") - ${python_name} -m pip install install paddle2onnx + ${python_name} -m pip install paddle2onnx ${python_name} -m pip install onnxruntime==1.4.0 # wget model wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ # wget data wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar diff --git a/test_tipc/prepare_lite_cpp.sh b/test_tipc/prepare_lite_cpp.sh index 94af43c88d..9148cb5dd7 100644 --- a/test_tipc/prepare_lite_cpp.sh +++ b/test_tipc/prepare_lite_cpp.sh @@ -51,6 +51,8 @@ for model in ${lite_model_list[*]}; do inference_model_url=https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/${model}.tar elif [[ $model =~ "v2.0" ]]; then inference_model_url=https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/${model}.tar + elif [[ $model =~ "PP-OCRv3" ]]; then + inference_model_url=https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/${model}.tar else echo "Model is wrong, please check." exit 3 diff --git a/test_tipc/test_inference_cpp.sh b/test_tipc/test_inference_cpp.sh index 9885e39372..2bef621d98 100644 --- a/test_tipc/test_inference_cpp.sh +++ b/test_tipc/test_inference_cpp.sh @@ -43,7 +43,7 @@ cpp_cls_value=$(func_parser_value "${lines[18]}") cpp_use_angle_cls_key=$(func_parser_key "${lines[19]}") cpp_use_angle_cls_value=$(func_parser_value "${lines[19]}") -LOG_PATH="./test_tipc/output" +LOG_PATH="./test_tipc/output/cpp_infer/${model_name}" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_cpp.log" @@ -178,7 +178,7 @@ if [ ${use_opencv} = "True" ]; then else OPENCV_DIR='' fi -LIB_DIR=$(pwd)/Paddle/build/paddle_inference_install_dir/ +LIB_DIR=$(pwd)/paddle_inference/ CUDA_LIB_DIR=$(dirname `find /usr -name libcudart.so`) CUDNN_LIB_DIR=$(dirname `find /usr -name libcudnn.so`) diff --git a/test_tipc/test_inference_python.sh b/test_tipc/test_inference_python.sh index 27276d55b9..a416d623d8 100644 --- a/test_tipc/test_inference_python.sh +++ b/test_tipc/test_inference_python.sh @@ -44,7 +44,7 @@ infer_value1=$(func_parser_value "${lines[17]}") -LOG_PATH="./test_tipc/output" +LOG_PATH="./test_tipc/output/${model_name}/${MODE}" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_python.log" @@ -113,7 +113,7 @@ function func_inference(){ set_tensorrt=$(func_set_params "${use_trt_key}" "${use_trt}") set_precision=$(func_set_params "${precision_key}" "${precision}") set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}") - set_infer_params0=$(func_set_params "${save_log_key}" "${save_log_value}") + set_infer_params0=$(func_set_params "${rec_model_key}" "${rec_model_value}") set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}") command="${_python} ${_script} ${use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} ${set_infer_params0} > ${_save_log_path} 2>&1 " eval $command diff --git a/test_tipc/test_paddle2onnx.sh b/test_tipc/test_paddle2onnx.sh index 300c61770d..4d1712cfda 100644 --- a/test_tipc/test_paddle2onnx.sh +++ b/test_tipc/test_paddle2onnx.sh @@ -11,7 +11,7 @@ python=$(func_parser_value "${lines[2]}") # parser params -dataline=$(awk 'NR==1, NR==12{print}' $FILENAME) +dataline=$(awk 'NR==1, NR==14{print}' $FILENAME) IFS=$'\n' lines=(${dataline}) @@ -34,14 +34,13 @@ enable_onnx_checker_value=$(func_parser_value "${lines[9]}") # parser onnx inference inference_py=$(func_parser_value "${lines[10]}") use_gpu_key=$(func_parser_key "${lines[11]}") -use_gpu_value=$(func_parser_value "${lines[11]}") +use_gpu_list=$(func_parser_value "${lines[11]}") det_model_key=$(func_parser_key "${lines[12]}") image_dir_key=$(func_parser_key "${lines[13]}") image_dir_value=$(func_parser_value "${lines[13]}") - -LOG_PATH="./test_tipc/output" -mkdir -p ./test_tipc/output +LOG_PATH="./test_tipc/output/paddle2onnx/${model_name}" +mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_paddle2onnx.log" @@ -50,7 +49,6 @@ function func_paddle2onnx(){ _script=$1 # paddle2onnx - _save_log_path="${LOG_PATH}/paddle2onnx_infer_cpu.log" set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") @@ -62,12 +60,31 @@ function func_paddle2onnx(){ last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" # python inference - set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu_value}") - set_model_dir=$(func_set_params "${det_model_key}" "${save_file_value}") - set_img_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") - infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " - eval $infer_model_cmd - status_check $last_status "${infer_model_cmd}" "${status_log}" + for use_gpu in ${use_gpu_list[*]}; do + if [ ${use_gpu} = "False" ] || [ ${use_gpu} = "cpu" ]; then + _save_log_path="${LOG_PATH}/paddle2onnx_infer_cpu.log" + set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu}") + set_model_dir=$(func_set_params "${det_model_key}" "${save_file_value}") + set_img_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + eval $infer_model_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${infer_model_cmd}" "${status_log}" + elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then + _save_log_path="${LOG_PATH}/paddle2onnx_infer_gpu.log" + set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu}") + set_model_dir=$(func_set_params "${det_model_key}" "${save_file_value}") + set_img_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + eval $infer_model_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${infer_model_cmd}" "${status_log}" + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done } diff --git a/test_tipc/test_serving.sh b/test_tipc/test_serving.sh index 260b252f41..3a6c88f313 100644 --- a/test_tipc/test_serving.sh +++ b/test_tipc/test_serving.sh @@ -38,8 +38,8 @@ pipeline_py=$(func_parser_value "${lines[16]}") image_dir_key=$(func_parser_key "${lines[17]}") image_dir_value=$(func_parser_value "${lines[17]}") -LOG_PATH="../../test_tipc/output" -mkdir -p ./test_tipc/output +LOG_PATH="$(pwd)/test_tipc/output/pdserving/${model_name}" +mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_serving.log" function func_serving(){ @@ -64,24 +64,40 @@ function func_serving(){ if [ ${python} = "cpp" ]; then for use_gpu in ${web_use_gpu_list[*]}; do if [ ${use_gpu} = "null" ]; then - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --port 9293" + if [ ${model_name} = "ocr_det_mobile" ]; then + web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293" + elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then + web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_v3_serving/ ppocr_rec_v3_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293" + fi eval $web_service_cpp_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cpp_cmd}" "${status_log}" sleep 2s _save_log_path="${LOG_PATH}/server_infer_cpp_cpu_pipeline_usemkldnn_False_threads_4_batchsize_1.log" - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" + if [ ${model_name} = "ocr_det_mobile" ]; then + pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" + elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then + pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_v3_client/ ppocr_rec_v3_client/" + fi eval $pipeline_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${pipeline_cmd}" "${status_log}" sleep 2s ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 else - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --port 9293 --gpu_id=0" + if [ ${model_name} = "ocr_det_mobile" ]; then + web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293 --gpu_id=0" + elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then + web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_v3_serving/ ppocr_rec_v3_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293 --gpu_id=0" + fi eval $web_service_cpp_cmd sleep 2s _save_log_path="${LOG_PATH}/server_infer_cpp_cpu_pipeline_usemkldnn_False_threads_4_batchsize_1.log" - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" + if [ ${model_name} = "ocr_det_mobile" ]; then + pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" + elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then + pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_v3_client/ ppocr_rec_v3_client/" + fi eval $pipeline_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${pipeline_cmd}" "${status_log}" @@ -113,7 +129,7 @@ function func_serving(){ ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 done done - elif [ ${use_gpu} = "0" ]; then + elif [ ${use_gpu} = "gpu" ]; then for use_trt in ${web_use_trt_list[*]}; do for precision in ${web_precision_list[*]}; do if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then @@ -130,7 +146,7 @@ function func_serving(){ device_type=2 fi set_precision=$(func_set_params "${web_precision_key}" "${precision}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} & " + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} & " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" diff --git a/test_tipc/test_train_inference_python.sh b/test_tipc/test_train_inference_python.sh index fe98cb00f6..81d1bf8eef 100644 --- a/test_tipc/test_train_inference_python.sh +++ b/test_tipc/test_train_inference_python.sh @@ -125,7 +125,7 @@ if [ ${MODE} = "klquant_whole_infer" ]; then infer_value1=$(func_parser_value "${lines[19]}") fi -LOG_PATH="./test_tipc/output/${model_name}" +LOG_PATH="./test_tipc/output/${model_name}/${MODE}" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_python.log" From 1382c17a106e568d8b2a88a14c6339d97e335004 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Fri, 13 May 2022 03:09:19 +0000 Subject: [PATCH 005/129] update model name --- ...odel_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...odel_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...odel_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt | 2 +- test_tipc/prepare.sh | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 63e7ff6556..da17069a96 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,5 +1,5 @@ ===========================cpp_infer_params=========================== -model_name:ocr_system_v3.0 +model_name:ocr_system_v3 use_opencv:True infer_model:./inference/ch_PP-OCRv3_det_infer/ infer_quant:False diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 80fee50f76..c7a37ddd59 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,5 +1,5 @@ ===========================cpp_infer_params=========================== -model_name:ocr_det_v3.0 +model_name:ocr_det_v3 use_opencv:True infer_model:./inference/ch_PP-OCRv3_det_infer/ infer_quant:False diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index d338a1f222..46b1c96c92 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,5 +1,5 @@ ===========================cpp_infer_params=========================== -model_name:ocr_rec_v3.0 +model_name:ocr_rec_v3 use_opencv:True infer_model:./inference/ch_PP-OCRv3_rec_infer/ infer_quant:False diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index 2326c9d2a7..ed72889970 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ trans_model:-m paddle_serving_client.convert --serving_client:./deploy/pdserving/ppocr_det_mobile_2.0_client/ serving_dir:./deploy/pdserving web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" -op.det.local_service_conf.devices:"0"|null +op.det.local_service_conf.devices:gpu|null op.det.local_service_conf.use_mkldnn:True|False op.det.local_service_conf.thread_num:1|6 op.det.local_service_conf.use_trt:False|True diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index d5c9c4f84f..a5c5bd2d06 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -364,11 +364,11 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_det_v3.0" ]; then + elif [ ${model_name} = "ocr_det_v3" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_rec_v3.0" ]; then + elif [ ${model_name} = "ocr_rec_v3" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ @@ -381,7 +381,7 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_system_v3.0" ]; then + elif [ ${model_name} = "ocr_system_v3" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate From a3753aae50f890b1bae296d50ca3b3adc5ebb4ba Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Fri, 13 May 2022 14:28:35 +0000 Subject: [PATCH 006/129] fix rec prediction for trt7 --- tools/infer/utility.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 74ec42ec84..67a0317734 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -272,9 +272,10 @@ def create_predictor(args, mode, logger): if args.rec_algorithm not in ["CRNN", "SVTR_LCNet"]: use_dynamic_shape = False imgH = int(args.rec_image_shape.split(',')[-2]) - min_input_shape = {"x": [1, 3, imgH, 10]} - max_input_shape = {"x": [args.rec_batch_num, 3, imgH, 2304]} - opt_input_shape = {"x": [args.rec_batch_num, 3, imgH, 320]} + min_input_shape = {"x": [1, 3, imgH, 10], } + max_input_shape = {"x": [args.rec_batch_num, 3, imgH, 2304], } + opt_input_shape = {"x": [args.rec_batch_num, 3, imgH, 320], } + config.exp_disable_tensorrt_ops(["elementwise_add"]) elif mode == "cls": min_input_shape = {"x": [1, 3, 48, 10]} max_input_shape = {"x": [args.rec_batch_num, 3, 48, 1024]} From c425ba9b852fe9100abeeb295ffb6b4fe146f1e6 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Fri, 13 May 2022 14:45:06 +0000 Subject: [PATCH 007/129] fix --- tools/infer/utility.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 67a0317734..db28af5f43 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -272,10 +272,10 @@ def create_predictor(args, mode, logger): if args.rec_algorithm not in ["CRNN", "SVTR_LCNet"]: use_dynamic_shape = False imgH = int(args.rec_image_shape.split(',')[-2]) - min_input_shape = {"x": [1, 3, imgH, 10], } - max_input_shape = {"x": [args.rec_batch_num, 3, imgH, 2304], } - opt_input_shape = {"x": [args.rec_batch_num, 3, imgH, 320], } - config.exp_disable_tensorrt_ops(["elementwise_add"]) + min_input_shape = {"x": [1, 3, imgH, 10]} + max_input_shape = {"x": [args.rec_batch_num, 3, imgH, 2304]} + opt_input_shape = {"x": [args.rec_batch_num, 3, imgH, 320]} + config.exp_disable_tensorrt_ops(["transpose2"]) elif mode == "cls": min_input_shape = {"x": [1, 3, 48, 10]} max_input_shape = {"x": [args.rec_batch_num, 3, 48, 1024]} @@ -283,6 +283,9 @@ def create_predictor(args, mode, logger): else: use_dynamic_shape = False if use_dynamic_shape: + print("min_input_shape: ", min_input_shape) + print("max_input_shape: ", max_input_shape) + print("opt_input_shape: ", opt_input_shape) config.set_trt_dynamic_shape_info( min_input_shape, max_input_shape, opt_input_shape) @@ -301,7 +304,7 @@ def create_predictor(args, mode, logger): config.enable_mkldnn_bfloat16() # enable memory optim config.enable_memory_optim() - config.disable_glog_info() + # config.disable_glog_info() config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("matmul_transpose_reshape_fuse_pass") if mode == 'table': From 85cfc51ece35abcc0886323c2f9978fa4b741c96 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Fri, 13 May 2022 14:45:40 +0000 Subject: [PATCH 008/129] fix --- tools/infer/utility.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index db28af5f43..57fdc1e28c 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -283,9 +283,6 @@ def create_predictor(args, mode, logger): else: use_dynamic_shape = False if use_dynamic_shape: - print("min_input_shape: ", min_input_shape) - print("max_input_shape: ", max_input_shape) - print("opt_input_shape: ", opt_input_shape) config.set_trt_dynamic_shape_info( min_input_shape, max_input_shape, opt_input_shape) From 265cd32bd5b9f76ce3a1ed03bc6eb835e56d16af Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Fri, 13 May 2022 14:46:02 +0000 Subject: [PATCH 009/129] fix --- tools/infer/utility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 57fdc1e28c..48b16db4a0 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -301,7 +301,7 @@ def create_predictor(args, mode, logger): config.enable_mkldnn_bfloat16() # enable memory optim config.enable_memory_optim() - # config.disable_glog_info() + config.disable_glog_info() config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("matmul_transpose_reshape_fuse_pass") if mode == 'table': From 0b6290eaf2c00bbca9fe318fb494e739ca60eec0 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Mon, 16 May 2022 16:57:13 +0800 Subject: [PATCH 010/129] add support for static training (#6297) * add support for static training * fix assert info --- ppocr/modeling/architectures/__init__.py | 20 +++++++++++++++++++- tools/train.py | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/ppocr/modeling/architectures/__init__.py b/ppocr/modeling/architectures/__init__.py index e9a01cf028..3f47f64a0f 100755 --- a/ppocr/modeling/architectures/__init__.py +++ b/ppocr/modeling/architectures/__init__.py @@ -15,10 +15,13 @@ import copy import importlib +from paddle.jit import to_static +from paddle.static import InputSpec + from .base_model import BaseModel from .distillation_model import DistillationModel -__all__ = ['build_model'] +__all__ = ["build_model", "apply_to_static"] def build_model(config): @@ -30,3 +33,18 @@ def build_model(config): mod = importlib.import_module(__name__) arch = getattr(mod, name)(config) return arch + + +def apply_to_static(model, config, logger): + if config["Global"].get("to_static", False) is not True: + return model + assert "image_shape" in config[ + "Global"], "image_shape must be assigned for static training mode..." + supported_list = ["DB"] + assert config["Architecture"][ + "algorithm"] in supported_list, f"algorithms that supports static training must in in {supported_list} but got {config['Architecture']['algorithm']}" + + specs = [InputSpec([None] + config["Global"]["image_shape"])] + model = to_static(model, input_spec=specs) + logger.info("Successfully to apply @to_static with specs: {}".format(specs)) + return model diff --git a/tools/train.py b/tools/train.py index 42aba548d6..b7c25e3423 100755 --- a/tools/train.py +++ b/tools/train.py @@ -35,6 +35,7 @@ from ppocr.postprocess import build_post_process from ppocr.metrics import build_metric from ppocr.utils.save_load import load_model from ppocr.utils.utility import set_seed +from ppocr.modeling.architectures import apply_to_static import tools.program as program dist.get_world_size() @@ -121,6 +122,8 @@ def main(config, device, logger, vdl_writer): if config['Global']['distributed']: model = paddle.DataParallel(model) + model = apply_to_static(model, config, logger) + # build loss loss_class = build_loss(config['Loss']) From 45eb69794514136a1c0513469287e27b8bb02e3a Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 16 May 2022 17:36:26 +0800 Subject: [PATCH 011/129] add lp recognize doc, test=document --- applications/车牌识别.md | 612 ++++++++++++++++++++++++++++ doc/doc_en/algorithm_overview_en.md | 6 + 2 files changed, 618 insertions(+) create mode 100644 applications/车牌识别.md diff --git a/applications/车牌识别.md b/applications/车牌识别.md new file mode 100644 index 0000000000..8b6b9833f9 --- /dev/null +++ b/applications/车牌识别.md @@ -0,0 +1,612 @@ +- [1. 项目介绍](#1-项目介绍) +- [2. 环境搭建](#2-环境搭建) +- [3. 数据集准备](#3-数据集准备) + - [3.1 数据集标注规则](#31-数据集标注规则) + - [3.2 制作符合PP-OCR训练格式的标注文件](#32-制作符合pp-ocr训练格式的标注文件) +- [4. 实验](#4-实验) + - [4.1 检测](#41-检测) + - [4.1.1 方案1:预训练模型](#411-方案1预训练模型) + - [4.1.2 方案2:CCPD车牌数据集fine-tune](#412-方案2ccpd车牌数据集fine-tune) + - [4.1.3 量化训练](#413-量化训练) + - [4.1.4 模型导出](#414-模型导出) + - [4.2 识别](#42-识别) + - [4.2.1 方案1:预训练模型](#421-方案1预训练模型) + - [4.2.2 改动后处理](#422-改动后处理) + - [4.2.3 方案2:CCPD车牌数据集fine-tune](#423-方案2ccpd车牌数据集fine-tune) + - [4.2.4 量化训练](#424-量化训练) + - [4.2.5 模型导出](#425-模型导出) + - [4.3 串联推理](#43-串联推理) + - [4.4 实验总结](#44-实验总结) + +# 一种基于PaddleOCR的轻量级车牌识别模型 + +## 1. 项目介绍 + +车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 + +由于使用场景的限制,表单识别通常要求高精度和实时。 + +在本例中,使用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。项目链接: [PaddleOCR车牌](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) + +## 2. 环境搭建 + +本任务基于Aistudio完成, 具体环境如下: + +- 操作系统: Linux +- PaddlePaddle: 2.3 +- paddleslim: 2.2.2 +- PaddleOCR: Release/2.5 + +下载 PaddleOCR代码 + +```bash +git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR +``` + +安装依赖库 + +```bash +pip install -r PaddleOCR/requirements.txt +``` + +## 3. 数据集准备 + + +所使用的数据集为 CCPD新能源车牌数据集,该数据集分布如下: + +|数据集类型|数量| +|---|---| +|训练集| 5769| +|验证集| 1001| +|测试集| 5006| + +数据集图片示例如下: +![](https://ai-studio-static-online.cdn.bcebos.com/3bce057a8e0c40a0acbd26b2e29e4e2590a31bc412764be7b9e49799c69cb91c) + +数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595 + +下载好数据集后对数据集进行解压 + +```bash +unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip +``` + +### 3.1 数据集标注规则 +CPPD的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD + +具体规则如下: + +例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg + +由分隔符'-'分为几个部分: + +- 025:车牌区域与整个图片区域的面积比。 + +- 95_113: 车牌水平倾斜度和垂直倾斜度, 水平95°, 竖直113° + +- 154&383_386&473: 车牌边界框坐标:左上(154, 383), 右下(386, 473) + +- 386&473_177&454_154&383_363&402: 车牌四个角点坐标, 坐标顺序为[右下,左下,左上,右上] + +- 0_0_22_27_27_33_16: 车牌号码,CCPD中的每个图像只有一个LP。每个LP编号由一个汉字、一个字母和五个字母或数字组成。有效的中国车牌由七个字符组成:省(1个字符)、字母(1个字符)、字母+数字(5个字符)。“0_0_22_27_27_33_16”是每个字符的索引。这三个数组的定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们使用O作为“无字符”的标志,因为中国车牌字符中没有O。 + +```python +provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"] +alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'O'] +ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O'] + +``` + +### 3.2 制作符合PP-OCR训练格式的标注文件 + +在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。 + + +```python +import cv2 +import os +import json +from tqdm import tqdm +import numpy as np + +provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"] +alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O'] +ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O'] + +def make_label(img_dir, save_gt_folder, phase): + crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs') + os.makedirs(crop_img_save_dir, exist_ok=True) + + f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8') + f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8') + + i = 0 + for filename in tqdm(os.listdir(os.path.join(img_dir, phase))): + str_list = filename.split('-') + if len(str_list) < 5: + continue + coord_list = str_list[3].split('_') + txt_list = str_list[4].split('_') + boxes = [] + for coord in coord_list: + boxes.append([int(x) for x in coord.split("&")]) + boxes = [boxes[2], boxes[3], boxes[0], boxes[1]] + lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]]) + + # det + det_info = [{'points':boxes, 'transcription':lp_number}] + f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False))) + + # rec + boxes = np.float32(boxes) + img = cv2.imread(os.path.join(img_dir, phase, filename)) + # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())] + crop_img = get_rotate_crop_image(img, boxes) + crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list)) + crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename) + cv2.imwrite(crop_img_save_path, crop_img) + f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number)) + i+=1 + f_det.close() + f_rec.close() + +def get_rotate_crop_image(img, points): + ''' + img_height, img_width = img.shape[0:2] + left = int(np.min(points[:, 0])) + right = int(np.max(points[:, 0])) + top = int(np.min(points[:, 1])) + bottom = int(np.max(points[:, 1])) + img_crop = img[top:bottom, left:right, :].copy() + points[:, 0] = points[:, 0] - left + points[:, 1] = points[:, 1] - top + ''' + assert len(points) == 4, "shape of points must be 4*2" + img_crop_width = int( + max( + np.linalg.norm(points[0] - points[1]), + np.linalg.norm(points[2] - points[3]))) + img_crop_height = int( + max( + np.linalg.norm(points[0] - points[3]), + np.linalg.norm(points[1] - points[2]))) + pts_std = np.float32([[0, 0], [img_crop_width, 0], + [img_crop_width, img_crop_height], + [0, img_crop_height]]) + M = cv2.getPerspectiveTransform(points, pts_std) + dst_img = cv2.warpPerspective( + img, + M, (img_crop_width, img_crop_height), + borderMode=cv2.BORDER_REPLICATE, + flags=cv2.INTER_CUBIC) + dst_img_height, dst_img_width = dst_img.shape[0:2] + if dst_img_height * 1.0 / dst_img_width >= 1.5: + dst_img = np.rot90(dst_img) + return dst_img + +img_dir = '/home/aistudio/data/CCPD2020/ccpd_green' +save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR' +# phase = 'train' # change to val and test to make val dataset and test dataset +for phase in ['train','val','test']: + make_label(img_dir, save_gt_folder, phase) +``` + +通过上述命令可以完成了`训练集`,`验证集`和`测试集`的制作,制作完成的数据集信息如下: + +| 类型 | 数据集 | 图片地址 | 标签地址 | 图片数量 | +| --- | --- | --- | --- | --- | +| 检测 | 训练集 | /home/aistudio/data/CCPD2020/ccpd_green/train | /home/aistudio/data/CCPD2020/PPOCR/train/det.txt | 5769 | +| 检测 | 验证集 | /home/aistudio/data/CCPD2020/ccpd_green/val | /home/aistudio/data/CCPD2020/PPOCR/val/det.txt | 1001 | +| 检测 | 测试集 | /home/aistudio/data/CCPD2020/ccpd_green/test | /home/aistudio/data/CCPD2020/PPOCR/test/det.txt | 5006 | +| 识别 | 训练集 | /home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/train/rec.txt | 5769 | +| 识别 | 验证集 | /home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/val/rec.txt | 1001 | +| 识别 | 测试集 | /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/test/rec.txt | 5006 | + +在本例中,我们只使用训练集和测试集。 + +## 4. 实验 + +选用飞桨OCR开发套件PaddleOCR中的PP-OCRv3模型进行文本检测和识别。PP-OCRv3在PP-OC2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。 + +对于车牌检测和识别均使用下面3种方案: + +1. PP-OCRv3中英文超轻量预训练模型 +2. CCPD车牌数据集在PP-OCRv3模型上fine-tune +3. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化 + +### 4.1 检测 +#### 4.1.1 方案1:预训练模型 + +从下表中下载PP-OCRv3文本检测预训练模型 + +|模型名称|模型简介|配置文件|推理模型大小|下载地址| +| --- | --- | --- | --- | --- | +|ch_PP-OCRv3_det| 【最新】原始超轻量模型,支持中英文、多语种文本检测 |[ch_PP-OCRv3_det_cml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)| 3.8M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar)| + +使用如下命令下载预训练模型 + +```bash +mkdir models +cd models +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar -xf ch_PP-OCRv3_det_distill_train.tar +cd /home/aistudio/PaddleOCR +``` + +预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student](../configs/chepai/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: + +1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 +2. Eval.dataset.data_dir:指向验证集图片存放目录 +3. Eval.dataset.label_file_list:指向验证集标注文件 + +使用如下命令进行PP-OCRv3文本检测预训练模型的评估 + + +```bash +python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] +``` + +使用预训练模型进行评估,指标如下所示: + +|方案|hmeans| +|---|---| +|PP-OCRv3中英文超轻量检测预训练模型|76.12%| + +#### 4.1.2 方案2:CCPD车牌数据集fine-tune + +**训练** + +和评估相同,进行训练也需要对部分字段进行设置,具体如下: + +在使用预训练模型进行fine-tune时,需要设置如下11个字段 +1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 +2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。 +3. Optimizer.lr.name: 学习率衰减器设为常量 Const +4. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍3. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍 +5. Optimizer.lr.warmup_epoch: warmup_epoch设为0 +6. Train.dataset.data_dir:指向训练集图片存放目录 +7. Train.dataset.label_file_list:指向训练集标注文件 +9. Eval.dataset.data_dir:指向验证集图片存放目录 +10. Eval.dataset.label_file_list:指向验证集标注文件 + +使用如下代码即可启动在CCPD车牌数据集上的fine-tune。 + +```bash +python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \ + Global.save_model_dir=output/CCPD/det \ + Global.eval_batch_step="[0, 772]" \ + Optimizer.lr.name=Const \ + Optimizer.lr.learning_rate=0.0005 \ + Optimizer.lr.warmup_epoch=0 \ + Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] +``` + +**评估** + +训练完成后使用如下命令进行评估 + + +```bash +python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] +``` + +使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下: + +|方案|hmeans| +|---|---| +|PP-OCRv3中英文超轻量检测预训练模型|76.12%| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| + +可以看到进行fine-tune能显著提升车牌检测的效果。 + +#### 4.1.3 量化训练 + +为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 + +量化训练课通过如下命令启动: + +```bash +python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \ + Global.save_model_dir=output/CCPD/det_quant \ + Global.eval_batch_step="[0, 772]" \ + Optimizer.lr.name=Const \ + Optimizer.lr.learning_rate=0.0005 \ + Optimizer.lr.warmup_epoch=0 \ + Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] +``` + +量化后指标对比如下 + +|方案|hmeans|模型大小|预测速度(lite)| +|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%|2.5m|| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%|1m|| + +可以看到量化后能显著降低模型体积 + +#### 4.1.4 模型导出 + +使用如下命令可以将训练好的模型进行导出 + +* 非量化模型 +```bash +python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \ + Global.save_inference_dir=output/det/infer +``` +* 量化模型 +```bash +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \ + Global.save_inference_dir=output/det/infer +``` + +### 4.2 识别 +#### 4.2.1 方案1:预训练模型 + +从下表中下载PP-OCRv3文本识别预训练模型 + +|模型名称|模型简介|配置文件|推理模型大小|下载地址| +| --- | --- | --- | --- | --- | +|ch_PP-OCRv3_rec|【最新】原始超轻量模型,支持中英文、数字识别|[ch_PP-OCRv3_rec_distillation.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml)| 12.4M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar) | + +使用如下命令下载预训练模型 + +```bash +mkdir models +cd models +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar +tar -xf ch_PP-OCRv3_rec_train.tar +cd /home/aistudio/PaddleOCR +``` + +PaddleOCR提供的PP-OCRv3识别蒸馏预训练模型中包含了多个模型的参数,需要使用如下代码提取Student模型的参数: + +```python +import paddle +# 加载预训练模型 +all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 学生模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看学生模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams") +``` + +预训练模型下载完成后,我们使用[ch_PP-OCRv3_rec.yml](../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: + +1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 +2. Eval.dataset.data_dir:指向验证集图片存放目录 +3. Eval.dataset.label_file_list:指向验证集标注文件 + +使用如下命令进行PP-OCRv3文本识别预训练模型的评估 + +```bash +python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] +``` + +评估部分日志如下: +```bash +[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy +eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00, 2.57it/s] +[2022/05/12 19:52:17] ppocr INFO: metric eval *************** +[2022/05/12 19:52:17] ppocr INFO: acc:0.0 +[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452 +[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545 +[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548 +[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905 + +``` +使用预训练模型进行评估,指标如下所示: + +|方案|acc| +|---|---| +|PP-OCRv3中英文超轻量识别预训练模型|0%| + +从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证: + + +```python +! python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \ + Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg +``` + +输出部分日志如下: +```bash +[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0) +W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1 +W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6. +[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student +[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg +[2022/05/01 08:52:00] ppocr INFO: result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}} +[2022/05/01 08:52:00] ppocr INFO: success! +``` + +从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个`·`。针对这种情况,有如下两种方案: +1. 直接通过后处理去掉多识别的`·`。 +2. 进行finetune。 + +#### 4.2.2 改动后处理 + +直接通过后处理去掉多识别的`·`,在后处理的改动比较简单,只需在 `ppocr/postprocess/rec_postprocess.py` 文件的76行添加如下代码: +```python +text = text.replace('·','') +``` + +改动前后指标对比: + +|方案|acc| +|---|---| +|PP-OCRv3中英文超轻量识别预训练模型|0.2%| +|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%| + +可以看到,去掉多余的`·`能大幅提高精度。 + +#### 4.2.3 方案2:CCPD车牌数据集fine-tune + +**训练** + +和评估相同,进行训练也需要对部分字段进行设置,具体如下: + +1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址 +2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。 +3. Optimizer.lr.name: 学习率衰减器设为常量 Const +4. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍 +5. Optimizer.lr.warmup_epoch: warmup_epoch设为0 +6. Train.dataset.data_dir:指向训练集图片存放目录 +7. Train.dataset.label_file_list:指向训练集标注文件 +9. Train.loader.batch_size_per_card: 训练时每张卡的图片数,这里设为64 +10. Eval.dataset.data_dir:指向验证集图片存放目录 +11. Eval.dataset.label_file_list:指向验证集标注文件 +13. Eval.loader.batch_size_per_card: 验证时每张卡的图片数,这里设为64 + +使用如下命令启动finetune + +```bash +python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \ + Global.save_model_dir=output/CCPD/rec/ \ + Global.eval_batch_step="[0, 90]" \ + Optimizer.lr.name=Const \ + Optimizer.lr.learning_rate=0.0005 \ + Optimizer.lr.warmup_epoch=0 \ + Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \ + Train.loader.batch_size_per_card=64 \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ + Eval.loader.batch_size_per_card=64 +``` + +**评估** + +训练完成后使用如下命令进行评估 + +```bash +python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] +``` + +使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下: + +|方案|acc| +|---|---| +|PP-OCRv3中英文超轻量识别预训练模型|0%| +|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%| + +可以看到进行fine-tune能显著提升车牌识别的效果。 + +#### 4.2.4 量化训练 + +为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 + +量化训练课通过如下命令启动 + + +```python +! python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ + Global.save_model_dir=output/CCPD/rec_quant/ \ + Global.eval_batch_step="[0, 90]" \ + Optimizer.lr.name=Const \ + Optimizer.lr.learning_rate=0.0005 \ + Optimizer.lr.warmup_epoch=0 \ + Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \ + Train.loader.batch_size_per_card=64 \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ + Eval.loader.batch_size_per_card=64 +``` + +量化后指标对比如下 + +|方案|acc|模型大小|预测速度(lite)| +|---|---|---|---| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%|10.3m| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化|94.36%|4.8m| + +可以看到量化后能显著降低模型体积 + +#### 4.2.5 模型导出 + +使用如下命令可以将训练好的模型进行导出。 + +* 非量化模型 +```python +! python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/rec/infer +``` +* 量化模型 +```python +! python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/rec_quant/infer +``` + +### 4.3 串联推理 + +检测模型和识别模型分别fine-tune并导出为inference模型之后,可以使用如下命令进行端到端推理并对结果进行可视化。 + + +```python +! python tools/infer/predict_system.py \ + --det_model_dir=output/CCPD/det/infer/ \ + --rec_model_dir=output/CCPD/rec/infer/ \ + --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ + --rec_image_shape=3,48,320 +``` +推理结果如下 + +![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) + + + + +### 4.4 实验总结 + +我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和finetune 和finetune+量化3种方案的实验,指标对比如下: + +- 检测 + +|方案|hmeans|模型大小|预测速度(lite)| +|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型|76.12%| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%|2.5m|| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%|1m|| + +- 识别 + +|方案|acc|模型大小|预测速度(lite)| +|---|---|---|---| +|PP-OCRv3中英文超轻量识别预训练模型|0%|x|x|x| +|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%|x|x| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%|10.3m|| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化|94.36%|4.8m|| diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md index 18c9cd7d51..383cbe39bb 100755 --- a/doc/doc_en/algorithm_overview_en.md +++ b/doc/doc_en/algorithm_overview_en.md @@ -41,6 +41,12 @@ On Total-Text dataset, the text detection result is as follows: | --- | --- | --- | --- | --- | --- | |SAST|ResNet50_vd|89.63%|78.44%|83.66%|[trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_totaltext_v2.0_train.tar)| +On CTW1500 dataset, the text detection result is as follows: + +|Model|Backbone|Precision|Recall|Hmean| Download link| +| --- | --- | --- | --- | --- |---| +|FCE|ResNet50_dcn|88.39%|82.18%|85.27%| [trained model](https://paddleocr.bj.bcebos.com/contribution/det_r50_dcn_fce_ctw_v2.0_train.tar) | + **Note:** Additional data, like icdar2013, icdar2017, COCO-Text, ArT, was added to the model training of SAST. Download English public dataset in organized format used by PaddleOCR from: * [Baidu Drive](https://pan.baidu.com/s/12cPnZcVuV1zn5DOd4mqjVw) (download code: 2bpi). * [Google Drive](https://drive.google.com/drive/folders/1ll2-XEVyCQLpJjawLDiRlvo_i4BqHCJe?usp=sharing) From e3c66dccd7989ebdc7019b712cc8b37a8a49e860 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 16 May 2022 18:17:50 +0800 Subject: [PATCH 012/129] add model link, test=document --- applications/车牌识别.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 8b6b9833f9..a6feec1320 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -235,7 +235,7 @@ tar -xf ch_PP-OCRv3_det_distill_train.tar cd /home/aistudio/PaddleOCR ``` -预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student](../configs/chepai/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: +预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student.yml](../configs/chepai/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: 1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 2. Eval.dataset.data_dir:指向验证集图片存放目录 @@ -289,6 +289,7 @@ python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] ``` +训练好的模型地址为: [det_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_finetune.tar) **评估** @@ -331,6 +332,8 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] ``` +训练好的模型地址为: [det_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_quant.tar) + 量化后指标对比如下 |方案|hmeans|模型大小|预测速度(lite)| @@ -500,6 +503,7 @@ python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ Eval.loader.batch_size_per_card=64 ``` +训练好的模型地址为: [rec_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_finetune.tar) **评估** @@ -544,6 +548,7 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ Eval.loader.batch_size_per_card=64 ``` +训练好的模型地址为: [rec_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_quant.tar) 量化后指标对比如下 From a153b58f0b85ea2df1aa607f2b0452cf59802a50 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 16 May 2022 18:22:04 +0800 Subject: [PATCH 013/129] update toc, test=document --- applications/车牌识别.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index a6feec1320..556f938241 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -5,15 +5,15 @@ - [3.2 制作符合PP-OCR训练格式的标注文件](#32-制作符合pp-ocr训练格式的标注文件) - [4. 实验](#4-实验) - [4.1 检测](#41-检测) - - [4.1.1 方案1:预训练模型](#411-方案1预训练模型) - - [4.1.2 方案2:CCPD车牌数据集fine-tune](#412-方案2ccpd车牌数据集fine-tune) - - [4.1.3 量化训练](#413-量化训练) + - [4.1.1 预训练模型](#411-预训练模型) + - [4.1.2 CCPD车牌数据集fine-tune](#412-ccpd车牌数据集fine-tune) + - [4.1.3 CCPD车牌数据集fine-tune+量化训练](#413-ccpd车牌数据集fine-tune量化训练) - [4.1.4 模型导出](#414-模型导出) - [4.2 识别](#42-识别) - - [4.2.1 方案1:预训练模型](#421-方案1预训练模型) - - [4.2.2 改动后处理](#422-改动后处理) - - [4.2.3 方案2:CCPD车牌数据集fine-tune](#423-方案2ccpd车牌数据集fine-tune) - - [4.2.4 量化训练](#424-量化训练) + - [4.2.1 预训练模型](#421-预训练模型) + - [4.2.2 预训练模型+改动后处理](#422-预训练模型改动后处理) + - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) + - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) - [4.2.5 模型导出](#425-模型导出) - [4.3 串联推理](#43-串联推理) - [4.4 实验总结](#44-实验总结) @@ -217,7 +217,7 @@ for phase in ['train','val','test']: 3. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化 ### 4.1 检测 -#### 4.1.1 方案1:预训练模型 +#### 4.1.1 预训练模型 从下表中下载PP-OCRv3文本检测预训练模型 @@ -257,7 +257,7 @@ python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ |---|---| |PP-OCRv3中英文超轻量检测预训练模型|76.12%| -#### 4.1.2 方案2:CCPD车牌数据集fine-tune +#### 4.1.2 CCPD车牌数据集fine-tune **训练** @@ -312,7 +312,7 @@ python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ 可以看到进行fine-tune能显著提升车牌检测的效果。 -#### 4.1.3 量化训练 +#### 4.1.3 CCPD车牌数据集fine-tune+量化训练 为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 @@ -361,7 +361,7 @@ python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP ``` ### 4.2 识别 -#### 4.2.1 方案1:预训练模型 +#### 4.2.1 预训练模型 从下表中下载PP-OCRv3文本识别预训练模型 @@ -452,7 +452,7 @@ W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6 1. 直接通过后处理去掉多识别的`·`。 2. 进行finetune。 -#### 4.2.2 改动后处理 +#### 4.2.2 预训练模型+改动后处理 直接通过后处理去掉多识别的`·`,在后处理的改动比较简单,只需在 `ppocr/postprocess/rec_postprocess.py` 文件的76行添加如下代码: ```python @@ -468,7 +468,7 @@ text = text.replace('·','') 可以看到,去掉多余的`·`能大幅提高精度。 -#### 4.2.3 方案2:CCPD车牌数据集fine-tune +#### 4.2.3 CCPD车牌数据集fine-tune **训练** @@ -526,7 +526,7 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ 可以看到进行fine-tune能显著提升车牌识别的效果。 -#### 4.2.4 量化训练 +#### 4.2.4 CCPD车牌数据集fine-tune+量化训练 为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 From 8060b374be7afc0aad932d053cb958d51cbe255a Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 16 May 2022 18:27:11 +0800 Subject: [PATCH 014/129] update metirc, test=document --- applications/车牌识别.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 556f938241..b4a73abbdd 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -518,11 +518,11 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ 使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下: -|方案|acc| -|---|---| -|PP-OCRv3中英文超轻量识别预训练模型|0%| -|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%| +|方案| acc | +|---|--------| +|PP-OCRv3中英文超轻量识别预训练模型| 0% | +|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`| 90.97% | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 可以看到进行fine-tune能显著提升车牌识别的效果。 @@ -552,10 +552,10 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ 量化后指标对比如下 -|方案|acc|模型大小|预测速度(lite)| -|---|---|---|---| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%|10.3m| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化|94.36%|4.8m| +|方案| acc |模型大小|预测速度(lite)| +|---|--------|---|---| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% |10.3m| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% |4.8m| 可以看到量化后能显著降低模型体积 @@ -609,9 +609,9 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ - 识别 -|方案|acc|模型大小|预测速度(lite)| -|---|---|---|---| -|PP-OCRv3中英文超轻量识别预训练模型|0%|x|x|x| -|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%|x|x| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune|94.36%|10.3m|| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化|94.36%|4.8m|| +|方案| acc |模型大小|预测速度(lite)| +|---|--------|---|---| +|PP-OCRv3中英文超轻量识别预训练模型| 0% ||| +|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`| 90.97% ||| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% |10.3m|| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% |4.8m|| From 62ba9336f97a3de464b21e2038c744ea5da6f7f8 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 16 May 2022 18:28:12 +0800 Subject: [PATCH 015/129] update metirc, test=document --- applications/车牌识别.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index b4a73abbdd..541de6d610 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -557,7 +557,7 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ |PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% |10.3m| |PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% |4.8m| -可以看到量化后能显著降低模型体积 +可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 #### 4.2.5 模型导出 @@ -593,8 +593,6 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ ![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) - - ### 4.4 实验总结 我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和finetune 和finetune+量化3种方案的实验,指标对比如下: From 4a17698f708fa36e901a2903a8b7229118022209 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Tue, 17 May 2022 12:22:56 +0800 Subject: [PATCH 016/129] update doc, test=document --- applications/车牌识别.md | 215 +++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 98 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 541de6d610..beac04412e 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -1,3 +1,5 @@ +# 一种基于PaddleOCR的轻量级车牌识别模型 + - [1. 项目介绍](#1-项目介绍) - [2. 环境搭建](#2-环境搭建) - [3. 数据集准备](#3-数据集准备) @@ -5,28 +7,28 @@ - [3.2 制作符合PP-OCR训练格式的标注文件](#32-制作符合pp-ocr训练格式的标注文件) - [4. 实验](#4-实验) - [4.1 检测](#41-检测) - - [4.1.1 预训练模型](#411-预训练模型) + - [4.1.1 预训练模型直接预测](#411-预训练模型直接预测) - [4.1.2 CCPD车牌数据集fine-tune](#412-ccpd车牌数据集fine-tune) - [4.1.3 CCPD车牌数据集fine-tune+量化训练](#413-ccpd车牌数据集fine-tune量化训练) - [4.1.4 模型导出](#414-模型导出) - [4.2 识别](#42-识别) - - [4.2.1 预训练模型](#421-预训练模型) - - [4.2.2 预训练模型+改动后处理](#422-预训练模型改动后处理) + - [4.2.1 预训练模型直接预测](#421-预训练模型直接预测) + - [4.2.2 预训练模型直接预测+改动后处理](#422-预训练模型直接预测改动后处理) - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) - [4.2.5 模型导出](#425-模型导出) - [4.3 串联推理](#43-串联推理) - [4.4 实验总结](#44-实验总结) -# 一种基于PaddleOCR的轻量级车牌识别模型 - ## 1. 项目介绍 车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 -由于使用场景的限制,表单识别通常要求高精度和实时。 +由于使用场景的限制,车牌识别通常要求高精度和实时。 -在本例中,使用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。项目链接: [PaddleOCR车牌](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) +在本例中,使用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。 + +aistudio项目链接: [PaddleOCR车牌](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) ## 2. 环境搭建 @@ -51,8 +53,9 @@ pip install -r PaddleOCR/requirements.txt ## 3. 数据集准备 +所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为 -所使用的数据集为 CCPD新能源车牌数据集,该数据集分布如下: +该数据集分布如下: |数据集类型|数量| |---|---| @@ -72,7 +75,8 @@ unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip ``` ### 3.1 数据集标注规则 -CPPD的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD + +CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD 具体规则如下: @@ -204,20 +208,22 @@ for phase in ['train','val','test']: | 识别 | 验证集 | /home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/val/rec.txt | 1001 | | 识别 | 测试集 | /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/test/rec.txt | 5006 | -在本例中,我们只使用训练集和测试集。 +在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。 ## 4. 实验 -选用飞桨OCR开发套件PaddleOCR中的PP-OCRv3模型进行文本检测和识别。PP-OCRv3在PP-OC2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。 +由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OC2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。 -对于车牌检测和识别均使用下面3种方案: +由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。 -1. PP-OCRv3中英文超轻量预训练模型 +因此,本实验中对于车牌检测和识别有如下3种方案: + +1. PP-OCRv3中英文超轻量预训练模型直接预测 2. CCPD车牌数据集在PP-OCRv3模型上fine-tune 3. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化 ### 4.1 检测 -#### 4.1.1 预训练模型 +#### 4.1.1 预训练模型直接预测 从下表中下载PP-OCRv3文本检测预训练模型 @@ -237,11 +243,13 @@ cd /home/aistudio/PaddleOCR 预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student.yml](../configs/chepai/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: -1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 -2. Eval.dataset.data_dir:指向验证集图片存放目录 -3. Eval.dataset.label_file_list:指向验证集标注文件 +1. 模型存储和训练相关: + 1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 +2. 数据集相关 + 1. Eval.dataset.data_dir:指向测试集图片存放目录 + 2. Eval.dataset.label_file_list:指向测试集标注文件 -使用如下命令进行PP-OCRv3文本检测预训练模型的评估 +上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估 ```bash @@ -250,29 +258,32 @@ python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] ``` +上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。 使用预训练模型进行评估,指标如下所示: -|方案|hmeans| -|---|---| -|PP-OCRv3中英文超轻量检测预训练模型|76.12%| +| 方案 |hmeans| +|---------------------------|---| +| PP-OCRv3中英文超轻量检测预训练模型直接预测 |76.12%| #### 4.1.2 CCPD车牌数据集fine-tune **训练** -和评估相同,进行训练也需要对部分字段进行设置,具体如下: +为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下: -在使用预训练模型进行fine-tune时,需要设置如下11个字段 -1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 -2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。 -3. Optimizer.lr.name: 学习率衰减器设为常量 Const -4. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍3. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍 -5. Optimizer.lr.warmup_epoch: warmup_epoch设为0 -6. Train.dataset.data_dir:指向训练集图片存放目录 -7. Train.dataset.label_file_list:指向训练集标注文件 -9. Eval.dataset.data_dir:指向验证集图片存放目录 -10. Eval.dataset.label_file_list:指向验证集标注文件 +1. 模型存储和训练相关: + 1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 + 2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。 +2. 优化器相关: + 1. Optimizer.lr.name: 学习率衰减器设为常量 Const + 2. Optimizer.lr.learning_rate: 做finetune实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 + 3. Optimizer.lr.warmup_epoch: warmup_epoch设为0 +3. 数据集相关: + 1. Train.dataset.data_dir:指向训练集图片存放目录 + 2. Train.dataset.label_file_list:指向训练集标注文件 + 3. Eval.dataset.data_dir:指向测试集图片存放目录 + 4. Eval.dataset.label_file_list:指向测试集标注文件 使用如下代码即可启动在CCPD车牌数据集上的fine-tune。 @@ -289,6 +300,9 @@ python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] ``` + +在上述命令中,通过`-o`的方式修改了配置文件中的参数。 + 训练好的模型地址为: [det_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_finetune.tar) **评估** @@ -307,16 +321,16 @@ python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ |方案|hmeans| |---|---| -|PP-OCRv3中英文超轻量检测预训练模型|76.12%| +|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%| |PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 可以看到进行fine-tune能显著提升车牌检测的效果。 #### 4.1.3 CCPD车牌数据集fine-tune+量化训练 -为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 +此处采用 PaddleOCR 中提供好的[量化教程](../deploy/slim/quantization/README.md)对模型进行量化训练。 -量化训练课通过如下命令启动: +量化训练可通过如下命令启动: ```bash python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ @@ -336,12 +350,12 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR 量化后指标对比如下 -|方案|hmeans|模型大小|预测速度(lite)| -|---|---|---|---| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%|2.5m|| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%|1m|| +|方案|hmeans| 模型大小 |预测速度(lite)| +|---|---|------|---| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || -可以看到量化后能显著降低模型体积 +可以看到量化后能显著降低模型体积并且精度几乎无损。 #### 4.1.4 模型导出 @@ -361,7 +375,7 @@ python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP ``` ### 4.2 识别 -#### 4.2.1 预训练模型 +#### 4.2.1 预训练模型直接预测 从下表中下载PP-OCRv3文本识别预训练模型 @@ -379,7 +393,7 @@ tar -xf ch_PP-OCRv3_rec_train.tar cd /home/aistudio/PaddleOCR ``` -PaddleOCR提供的PP-OCRv3识别蒸馏预训练模型中包含了多个模型的参数,需要使用如下代码提取Student模型的参数: +PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含`Teacher`和`Student`模型的参数,详细信息可参考[knowledge_distillation.md](../doc/doc_ch/knowledge_distillation.md)。 因此,模型下载完成后需要使用如下代码提取`Student`模型的参数: ```python import paddle @@ -397,9 +411,11 @@ paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams") 预训练模型下载完成后,我们使用[ch_PP-OCRv3_rec.yml](../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: -1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 -2. Eval.dataset.data_dir:指向验证集图片存放目录 -3. Eval.dataset.label_file_list:指向验证集标注文件 +1. 模型存储和训练相关: + 1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址 +2. 数据集相关 + 1. Eval.dataset.data_dir:指向测试集图片存放目录 + 2. Eval.dataset.label_file_list:指向测试集标注文件 使用如下命令进行PP-OCRv3文本识别预训练模型的评估 @@ -426,13 +442,13 @@ eval model:: 100%|████████████████████ |方案|acc| |---|---| -|PP-OCRv3中英文超轻量识别预训练模型|0%| +|PP-OCRv3中英文超轻量识别预训练模型直接预测|0%| 从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证: -```python -! python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ +```bash +python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \ Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg ``` @@ -452,9 +468,9 @@ W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6 1. 直接通过后处理去掉多识别的`·`。 2. 进行finetune。 -#### 4.2.2 预训练模型+改动后处理 +#### 4.2.2 预训练模型直接预测+改动后处理 -直接通过后处理去掉多识别的`·`,在后处理的改动比较简单,只需在 `ppocr/postprocess/rec_postprocess.py` 文件的76行添加如下代码: +直接通过后处理去掉多识别的`·`,在后处理的改动比较简单,只需在 [ppocr/postprocess/rec_postprocess.py](../ppocr/postprocess/rec_postprocess.py) 文件的76行添加如下代码: ```python text = text.replace('·','') ``` @@ -463,8 +479,8 @@ text = text.replace('·','') |方案|acc| |---|---| -|PP-OCRv3中英文超轻量识别预训练模型|0.2%| -|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|90.97%| +|PP-OCRv3中英文超轻量识别预训练模型直接预测|0.2%| +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`|90.97%| 可以看到,去掉多余的`·`能大幅提高精度。 @@ -472,19 +488,20 @@ text = text.replace('·','') **训练** -和评估相同,进行训练也需要对部分字段进行设置,具体如下: +为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下: -1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址 -2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。 -3. Optimizer.lr.name: 学习率衰减器设为常量 Const -4. Optimizer.lr.learning_rate: 学习率设为之前的0.05倍 -5. Optimizer.lr.warmup_epoch: warmup_epoch设为0 -6. Train.dataset.data_dir:指向训练集图片存放目录 -7. Train.dataset.label_file_list:指向训练集标注文件 -9. Train.loader.batch_size_per_card: 训练时每张卡的图片数,这里设为64 -10. Eval.dataset.data_dir:指向验证集图片存放目录 -11. Eval.dataset.label_file_list:指向验证集标注文件 -13. Eval.loader.batch_size_per_card: 验证时每张卡的图片数,这里设为64 +1. 模型存储和训练相关: + 1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址 + 2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。 +2. 优化器相关 + 1. Optimizer.lr.name: 学习率衰减器设为常量 Const + 2. Optimizer.lr.learning_rate: 做finetune实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 + 3. Optimizer.lr.warmup_epoch: warmup_epoch设为0 +3. 数据集相关 + 1. Train.dataset.data_dir:指向训练集图片存放目录 + 2. Train.dataset.label_file_list:指向训练集标注文件 + 3. Eval.dataset.data_dir:指向测试集图片存放目录 + 4. Eval.dataset.label_file_list:指向测试集标注文件 使用如下命令启动finetune @@ -498,10 +515,8 @@ python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Optimizer.lr.warmup_epoch=0 \ Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \ - Train.loader.batch_size_per_card=64 \ Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ - Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ - Eval.loader.batch_size_per_card=64 + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] ``` 训练好的模型地址为: [rec_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_finetune.tar) @@ -520,21 +535,20 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ |方案| acc | |---|--------| -|PP-OCRv3中英文超轻量识别预训练模型| 0% | -|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`| 90.97% | +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% | |PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 可以看到进行fine-tune能显著提升车牌识别的效果。 #### 4.2.4 CCPD车牌数据集fine-tune+量化训练 -为了在端侧设备上进行部署,我们还需要对模型进行量化以提升模型的运行速度并降低模型体积。 +此处采用 PaddleOCR 中提供好的[量化教程](../deploy/slim/quantization/README.md)对模型进行量化训练。 -量化训练课通过如下命令启动 +量化训练可通过如下命令启动: - -```python -! python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ +```bash +python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ Global.save_model_dir=output/CCPD/rec_quant/ \ Global.eval_batch_step="[0, 90]" \ @@ -543,19 +557,17 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Optimizer.lr.warmup_epoch=0 \ Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \ - Train.loader.batch_size_per_card=64 \ Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ - Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] \ - Eval.loader.batch_size_per_card=64 + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] ``` 训练好的模型地址为: [rec_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_quant.tar) 量化后指标对比如下 -|方案| acc |模型大小|预测速度(lite)| -|---|--------|---|---| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% |10.3m| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% |4.8m| +|方案| acc | 模型大小 |预测速度(lite)| +|---|--------|-------|---| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 @@ -564,14 +576,14 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ 使用如下命令可以将训练好的模型进行导出。 * 非量化模型 -```python -! python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ +```bash +python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ Global.save_inference_dir=output/CCPD/rec/infer ``` * 量化模型 -```python -! python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ +```bash +python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \ Global.save_inference_dir=output/CCPD/rec_quant/infer ``` @@ -581,8 +593,8 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ 检测模型和识别模型分别fine-tune并导出为inference模型之后,可以使用如下命令进行端到端推理并对结果进行可视化。 -```python -! python tools/infer/predict_system.py \ +```bash +python tools/infer/predict_system.py \ --det_model_dir=output/CCPD/det/infer/ \ --rec_model_dir=output/CCPD/rec/infer/ \ --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ @@ -599,17 +611,24 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ - 检测 -|方案|hmeans|模型大小|预测速度(lite)| -|---|---|---|---| -|PP-OCRv3中英文超轻量检测预训练模型|76.12%| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%|2.5m|| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%|1m|| +|方案|hmeans| 模型大小 |预测速度(lite)| +|---|---|------|---| +|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || - 识别 -|方案| acc |模型大小|预测速度(lite)| -|---|--------|---|---| -|PP-OCRv3中英文超轻量识别预训练模型| 0% ||| -|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`| 90.97% ||| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% |10.3m|| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% |4.8m|| +|方案| acc | 模型大小 |预测速度(lite)| +|---|--------|-------|---| +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M|| +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M|| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M || +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M || + + +- 结论 + +PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过finetune后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 + +PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过finetune后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 From 57c6813cce70a8fb2fc1b8fdc7889f18be718685 Mon Sep 17 00:00:00 2001 From: HinGwenWoong Date: Tue, 10 May 2022 19:30:52 +0800 Subject: [PATCH 017/129] Fix re-reco will clear all key message --- PPOCRLabel/PPOCRLabel.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/PPOCRLabel/PPOCRLabel.py b/PPOCRLabel/PPOCRLabel.py index f6e6abe365..ce3d66f07f 100644 --- a/PPOCRLabel/PPOCRLabel.py +++ b/PPOCRLabel/PPOCRLabel.py @@ -1149,7 +1149,10 @@ class MainWindow(QMainWindow): for box in self.result_dic: trans_dic = {"label": box[1][0], "points": box[0], "difficult": False} if self.kie_mode: - trans_dic.update({"key_cls": "None"}) + if len(box) == 3: + trans_dic.update({"key_cls": box[2]}) + else: + trans_dic.update({"key_cls": "None"}) if trans_dic["label"] == "" and mode == 'Auto': continue shapes.append(trans_dic) @@ -2047,6 +2050,7 @@ class MainWindow(QMainWindow): rec_flag = 0 for shape in self.canvas.shapes: box = [[int(p.x()), int(p.y())] for p in shape.points] + kie_cls = shape.key_cls if len(box) > 4: box = self.gen_quad_from_poly(np.array(box)) @@ -2062,17 +2066,27 @@ class MainWindow(QMainWindow): if shape.line_color == DEFAULT_LOCK_COLOR: shape.label = result[0][0] result.insert(0, box) + if self.kie_mode: + result.append(kie_cls) self.result_dic_locked.append(result) else: result.insert(0, box) + if self.kie_mode: + result.append(kie_cls) self.result_dic.append(result) else: print('Can not recognise the box') if shape.line_color == DEFAULT_LOCK_COLOR: shape.label = result[0][0] - self.result_dic_locked.append([box, (self.noLabelText, 0)]) + if self.kie_mode: + self.result_dic_locked.append([box, (self.noLabelText, 0), kie_cls]) + else: + self.result_dic_locked.append([box, (self.noLabelText, 0)]) else: - self.result_dic.append([box, (self.noLabelText, 0)]) + if self.kie_mode: + self.result_dic.append([box, (self.noLabelText, 0), kie_cls]) + else: + self.result_dic.append([box, (self.noLabelText, 0)]) try: if self.noLabelText == shape.label or result[1][0] == shape.label: print('label no change') From a3e513b037b91397e198c72d9d51cf81a0cba52d Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Tue, 17 May 2022 14:49:18 +0800 Subject: [PATCH 018/129] update doc, test=document --- applications/车牌识别.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index beac04412e..8ca03a2c3a 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -28,7 +28,7 @@ 在本例中,使用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。 -aistudio项目链接: [PaddleOCR车牌](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) +aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) ## 2. 环境搭建 @@ -212,7 +212,7 @@ for phase in ['train','val','test']: ## 4. 实验 -由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OC2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。 +由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。 由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。 From 7036ec1b5f33edf431bbf414190322631c9a2d0b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 17 May 2022 15:55:55 +0800 Subject: [PATCH 019/129] add doc --- doc/doc_ch/PPOCRv3_det_train.md | 252 ++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 doc/doc_ch/PPOCRv3_det_train.md diff --git a/doc/doc_ch/PPOCRv3_det_train.md b/doc/doc_ch/PPOCRv3_det_train.md new file mode 100644 index 0000000000..601acddee1 --- /dev/null +++ b/doc/doc_ch/PPOCRv3_det_train.md @@ -0,0 +1,252 @@ + +# PP-OCRv3 文本检测模型训练 + +- [1. 简介](#1) +- [2. PPOCRv3检测训练](#2) +- [3. 基于PPOCRv3检测的finetune训练](#3) + + +## 1. 简介 + +PP-OCRv3在PP-OCRv2的基础上进一步升级。本节介绍PP-OCRv3检测模型的训练步骤。有关PPOCRv3策略介绍参考[文档](./PP-OCRv3_introduction.md)。 + + + +## 2. 检测训练 + +PP-OCRv3检测模型是对PP-OCRv2中的[CML](https://arxiv.org/pdf/2109.03144.pdf)(Collaborative Mutual Learning) 协同互学习文本检测蒸馏策略进行了升级。PP-OCRv3分别针对检测教师模型和学生模型进行进一步效果优化。其中,在对教师模型优化时,提出了大感受野的PAN结构LK-PAN和引入了DML(Deep Mutual Learning)蒸馏策略;在对学生模型优化时,提出了残差注意力机制的FPN结构RSE-FPN。 + +PP-OCRv3检测训练包括两个步骤: +- 步骤1:采用DML蒸馏方法训练检测教师模型 +- 步骤2:使用步骤1得到的教师模型采用CML方法训练出轻量学生模型 + + +### 2.1 准备数据和运行环境 + +训练数据采用icdar2015数据,准备训练集步骤参考[ocr_dataset](./dataset/ocr_datasets.md). + +运行环境准备参考[文档](./installation.md)。 + + +### 2.2 训练教师模型 + +教师模型训练的配置文件是[ch_PP-OCRv3_det_dml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml)。教师模型模型结构的Backbone、Neck、Head分别为Resnet50, LKPAN, DBHead,采用DML的蒸馏方法训练。有关配置文件的详细介绍参考[文档](./knowledge_distillation)。 + + +下载ImageNet预训练模型: +``` +# 下载ResNet50_vd的预训练模型 +wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/ResNet50_vd_ssld_pretrained.pdparams +``` + +**启动训练** +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Global.save_model_dir=./output/ +``` + +训练过程中保存的模型在output目录下,包含以下文件: +``` +best_accuracy.states +best_accuracy.pdparams # 默认保存最优精度的模型参数 +best_accuracy.pdopt # 默认保存最优精度的优化器相关参数 +latest.states +latest.pdparams # 默认保存的最新模型参数 +latest.pdopt # 默认保存的最新模型的优化器相关参数 +``` +其中,best_accuracy是保存的精度最高的模型参数,可以直接使用该模型评估。 + +模型评估命令如下: +``` +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./output/best_accuracy +``` + +训练的教师模型结构更大,精度更高,用于提升学生模型的精度。 + +**提取教师模型参数** +best_accuracy包含两个模型的参数,分别对应配置文件中的Student,Student2。提取Student的参数方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./pretrain_models/dml_teacher.pdparams") +``` + +提取出来的模型参数可以用于模型进一步的finetune训练或者蒸馏训练。 + +### 2.3 训练学生模型 + +训练学生模型的配置文件是[ch_PP-OCRv3_det_cml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml) +上一节训练得到的教师模型作为监督,采用CML方式训练得到轻量的学生模型。 + +下载学生模型的ImageNet预训练模型: +``` +# 下载MobileNetV3的预训练模型 +wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/MobileNetV3_large_x0_5_pretrained.pdparams +``` + +**启动训练** + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ + Global.save_model_dir=./output/ +``` + +训练过程中保存的模型在output目录下, +模型评估命令如下: +``` +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +``` + +best_accuracy包含三个模型的参数,分别对应配置文件中的Student,Student2,Teacher。提取Student参数的方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./pretrain_models/cml_student.pdparams") +``` + +提取出来的Student的参数可用于模型部署或者做进一步的finetune训练。 + + + + +## 3. 基于PPOCRv3检测finetune训练 + +本节介绍如何使用PPOCRv3检测模型在其他场景上的finetune训练。 + +finetune训练适用于三种场景: +- 基于CML蒸馏方法的finetune训练,适用于教师模型在使用场景上精度高于PPOCRv3检测模型,且希望得到一个轻量检测模型。 +- 基于PPOCRv3轻量检测模型的finetune训练,无需训练教师模型,希望在PPOCRv3检测模型基础上提升使用场景上的精度。 +- 基于DML蒸馏方法的finetune训练,适用于采用DML方法进一步提升精度的场景。 + + +**基于CML蒸馏方法的finetune训练** + +下载PPOCRv3训练模型: +``` +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar +``` +ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams包含CML配置文件中Student、Student2、Teacher模型的参数。 + +启动训练: + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ + Global.save_model_dir=./output/ +``` + +**基于PPOCRv3轻量检测模型的finetune训练** + + +下载PPOCRv3训练模型,并提取Student结构的模型参数: +``` +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar +``` + +提取Student参数的方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./student.pdparams") +``` + +使用配置文件[ch_PP-OCRv3_det_student.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml)训练。 + +**启动训练** + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.pretrained_model=./student \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.pretrained_model=./student \ + Global.save_model_dir=./output/ +``` + + +**基于DML蒸馏方法的finetune训练** + +以ch_PP-OCRv3_det_distill_train中的Teacher模型为例,首先提取Teacher结构的参数,方法如下: +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Teacher."):]: all_params[key] for key in all_params if "Teacher." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./teacher.pdparams") +``` + +**启动训练** +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./teacher \ + Architecture.Models.Student2.pretrained=./teacher \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./teacher \ + Architecture.Models.Student2.pretrained=./teacher \ + Global.save_model_dir=./output/ +``` + + From b339204dfc306ba11e213a464f6da7cff5e407b9 Mon Sep 17 00:00:00 2001 From: lubin10 Date: Tue, 17 May 2022 08:29:44 +0000 Subject: [PATCH 020/129] update tools/export_model.py tools/infer_rec.py --- tools/export_model.py | 2 +- tools/infer_rec.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/export_model.py b/tools/export_model.py index e971f6cb20..c0cbcd361c 100755 --- a/tools/export_model.py +++ b/tools/export_model.py @@ -17,7 +17,7 @@ import sys __dir__ = os.path.dirname(os.path.abspath(__file__)) sys.path.append(__dir__) -sys.path.append(os.path.abspath(os.path.join(__dir__, ".."))) +sys.path.insert(0, os.path.abspath(os.path.join(__dir__, ".."))) import argparse diff --git a/tools/infer_rec.py b/tools/infer_rec.py index 193e24a4de..a08fa25b46 100755 --- a/tools/infer_rec.py +++ b/tools/infer_rec.py @@ -157,7 +157,7 @@ def main(): if info is not None: logger.info("\t result: {}".format(info)) - fout.write(file + "\t" + info) + fout.write(file + "\t" + info + "\n") logger.info("success!") From 2d89b2cef6853a722956861fdca4d80f359b61b2 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 18 May 2022 09:03:09 +0800 Subject: [PATCH 021/129] update doc, test=document --- applications/车牌识别.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 8ca03a2c3a..5cfb1c1e0c 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -24,9 +24,18 @@ 车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 -由于使用场景的限制,车牌识别通常要求高精度和实时。 +结合我国国情,目前车牌识别技术的难点有: -在本例中,使用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。 +1. 汽车牌照组成比较复杂,汉字+字母+数据混合,不只有英文字母和阿拉伯数字,还有汉字,识别难度比较大; +2. 颜色种类多,车牌格式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 +3. 文件分辨率低,通常由于车牌较远,有时是由于低端相机导致的; +4. 车牌悬挂位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; +5. 图像模糊,尤其是运动模糊; +6. 由于强光,反射或阴影造成的光照和对比度较差; +7. 车牌(部分)遮挡,通常是拖车杆或车牌上的污渍; +8. 在车辆管理等场景场景对于模型速度有着一定限制。 + +针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。 aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) From eaeea01cffa0ff3754548ce3b8794b82311c3dcf Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 18 May 2022 13:49:12 +0800 Subject: [PATCH 022/129] update doc, test=document --- applications/车牌识别.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 5cfb1c1e0c..bcfe4fb65e 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -26,16 +26,14 @@ 结合我国国情,目前车牌识别技术的难点有: -1. 汽车牌照组成比较复杂,汉字+字母+数据混合,不只有英文字母和阿拉伯数字,还有汉字,识别难度比较大; -2. 颜色种类多,车牌格式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 -3. 文件分辨率低,通常由于车牌较远,有时是由于低端相机导致的; -4. 车牌悬挂位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; -5. 图像模糊,尤其是运动模糊; -6. 由于强光,反射或阴影造成的光照和对比度较差; -7. 车牌(部分)遮挡,通常是拖车杆或车牌上的污渍; -8. 在车辆管理等场景场景对于模型速度有着一定限制。 +1. 车牌样式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 +2. 车牌位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; +3. 图像质量差: 运动模糊,由于强光,反射或阴影造成的光照和对比度较差, 车牌(部分)遮挡; +4. 在车辆管理等场景场景对于模型速度有着一定限制。 -针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发并使用量化进行模型体积的压缩和模型推理速度的加速。 +针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升x%。 + +并使用量化进行模型体积的压缩和模型推理速度的加速 aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) From e55835be8d3bb4239bfe840451484315b83649bd Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 18 May 2022 15:33:11 +0800 Subject: [PATCH 023/129] Update ppocr_introduction_en.md --- doc/doc_en/ppocr_introduction_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doc_en/ppocr_introduction_en.md b/doc/doc_en/ppocr_introduction_en.md index 8fe6bc683a..b13d7f9bf1 100644 --- a/doc/doc_en/ppocr_introduction_en.md +++ b/doc/doc_en/ppocr_introduction_en.md @@ -38,7 +38,7 @@ On the basis of PP-OCR, PP-OCRv2 is further optimized in five aspects. The detec PP-OCRv3 upgraded the detection model and recognition model in 9 aspects based on PP-OCRv2: - PP-OCRv3 detector upgrades the CML(Collaborative Mutual Learning) text detection strategy proposed in PP-OCRv2, and further optimizes the effect of teacher model and student model respectively. In the optimization of teacher model, a pan module with large receptive field named LK-PAN is proposed and the DML distillation strategy is adopted; In the optimization of student model, a FPN module with residual attention mechanism named RSE-FPN is proposed. -- PP-OCRv3 recognizer is optimized based on text recognition algorithm [SVTR](https://arxiv.org/abs/2205.00159). SVTR no longer adopts RNN by introducing transformers structure, which can mine the context information of text line image more effectively, so as to improve the ability of text recognition. PP-OCRv3 adopts lightweight text recognition network SVTR_LCNet, guided training of CTC loss by attention loss, data augmentation strategy TextConAug, better pre-trained model by self-supervised TextRotNet, UDML(Unified Deep Mutual Learning), and UIM (Unlabeled Images Mining) to accelerate the model and improve the effect. +- PP-OCRv3 recognizer is optimized based on text recognition algorithm [SVTR](https://arxiv.org/abs/2205.00159). SVTR no longer adopts RNN by introducing transformers structure, which can mine the context information of text line image more effectively, so as to improve the ability of text recognition. PP-OCRv3 adopts lightweight text recognition network SVTR_LCNet, guided training of CTC by attention, data augmentation strategy TextConAug, better pre-trained model by self-supervised TextRotNet, UDML(Unified Deep Mutual Learning), and UIM (Unlabeled Images Mining) to accelerate the model and improve the effect. PP-OCRv3 pipeline is as follows: From 43403c46b0fe67f27f8733b6b3e888e7d76277f4 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 18 May 2022 16:08:38 +0800 Subject: [PATCH 024/129] update doc, test=document --- applications/车牌识别.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index bcfe4fb65e..2abb9c6f7a 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -33,8 +33,6 @@ 针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升x%。 -并使用量化进行模型体积的压缩和模型推理速度的加速 - aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) ## 2. 环境搭建 From b9668e275ec26a510652e0e366ebd660d2a99425 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 18 May 2022 10:31:09 +0000 Subject: [PATCH 025/129] fix dead links --- doc/doc_ch/knowledge_distillation.md | 6 +- doc/doc_ch/multi_languages.md | 6 +- doc/doc_ch/serving_inference.md | 238 ------------------ doc/doc_ch/update.md | 6 +- doc/doc_en/algorithm_det_east_en.md | 2 +- doc/doc_en/algorithm_det_fcenet_en.md | 2 +- doc/doc_en/algorithm_det_psenet_en.md | 2 +- doc/doc_en/algorithm_e2e_pgnet_en.md | 2 +- doc/doc_en/algorithm_rec_aster_en.md | 4 +- doc/doc_en/algorithm_rec_crnn_en.md | 4 +- doc/doc_en/algorithm_rec_nrtr_en.md | 4 +- doc/doc_en/algorithm_rec_sar_en.md | 4 +- doc/doc_en/algorithm_rec_seed_en.md | 4 +- doc/doc_en/algorithm_rec_srn_en.md | 4 +- doc/doc_en/algorithm_rec_svtr_en.md | 4 +- doc/doc_en/knowledge_distillation_en.md | 4 +- doc/doc_en/multi_languages_en.md | 6 +- doc/doc_en/update_en.md | 6 +- ppstructure/vqa/README_ch.md | 4 +- .../jeston_test_train_inference_python.md | 2 +- .../docs/mac_test_train_inference_python.md | 2 +- test_tipc/docs/test_train_inference_python.md | 2 +- .../docs/win_test_train_inference_python.md | 2 +- 23 files changed, 41 insertions(+), 279 deletions(-) delete mode 100644 doc/doc_ch/serving_inference.md diff --git a/doc/doc_ch/knowledge_distillation.md b/doc/doc_ch/knowledge_distillation.md index 76ab5e62e0..79c4418d53 100644 --- a/doc/doc_ch/knowledge_distillation.md +++ b/doc/doc_ch/knowledge_distillation.md @@ -424,9 +424,9 @@ Architecture: ``` -如果是采用DML,即两个小模型互相学习的方法,上述配置文件里的Teacher网络结构需要设置为Student模型一样的配置,具体参考配置文件[ch_PP-OCRv3_det_dml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml)。 - -下面介绍[ch_PP-OCRv3_det_cml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)的配置文件参数: +如果是采用DML,即两个小模型互相学习的方法,上述配置文件里的Teacher网络结构需要设置为Student模型一样的配置,具体参考配置文件[ch_PP-OCRv3_det_dml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml)。 + +下面介绍[ch_PP-OCRv3_det_cml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)的配置文件参数: ``` Architecture: diff --git a/doc/doc_ch/multi_languages.md b/doc/doc_ch/multi_languages.md index 499fdd9881..1f337bdf49 100644 --- a/doc/doc_ch/multi_languages.md +++ b/doc/doc_ch/multi_languages.md @@ -238,10 +238,10 @@ python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs ## 4 预测部署 除了安装whl包进行快速预测,ppocr 也提供了多种预测部署方式,如有需求可阅读相关文档: -- [基于Python脚本预测引擎推理](./inference.md) -- [基于C++预测引擎推理](../../deploy/cpp_infer/readme.md) +- [基于Python脚本预测引擎推理](./inference_ppocr.md) +- [基于C++预测引擎推理](../../deploy/cpp_infer/readme_ch.md) - [服务化部署](../../deploy/hubserving/readme.md) -- [端侧部署](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/deploy/lite/readme.md) +- [端侧部署](../../deploy/lite/readme_ch.md) - [Benchmark](./benchmark.md) diff --git a/doc/doc_ch/serving_inference.md b/doc/doc_ch/serving_inference.md deleted file mode 100644 index 30ea7ee7c1..0000000000 --- a/doc/doc_ch/serving_inference.md +++ /dev/null @@ -1,238 +0,0 @@ -# 使用Paddle Serving预测推理 - -阅读本文档之前,请先阅读文档 [基于Python预测引擎推理](./inference.md) - -同本地执行预测一样,我们需要保存一份可以用于Paddle Serving的模型。 - -接下来首先介绍如何将训练的模型转换成Paddle Serving模型,然后将依次介绍文本检测、文本识别以及两者串联基于预测引擎推理。 - -### 一、 准备环境 -我们先安装Paddle Serving相关组件 -我们推荐用户使用GPU来做Paddle Serving的OCR服务部署 - -**CUDA版本:9.X/10.X** - -**CUDNN版本:7.X** - -**操作系统版本:Linux/Windows** - -**Python版本: 2.7/3.5/3.6/3.7** - -**Python操作指南:** - -目前Serving用于OCR的部分功能还在测试当中,因此在这里我们给出[Servnig latest package](https://github.com/PaddlePaddle/Serving/blob/develop/doc/Latest_Packages_CN.md) -大家根据自己的环境选择需要安装的whl包即可,例如以Python 3.5为例,执行下列命令 -``` -#CPU/GPU版本选择一个 -#GPU版本服务端 -#CUDA 9 -python -m pip install -U https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server_gpu-0.0.0.post9-py3-none-any.whl -#CUDA 10 -python -m pip install -U https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server_gpu-0.0.0.post10-py3-none-any.whl -#CPU版本服务端 -python -m pip install -U https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server-0.0.0-py3-none-any.whl -#客户端和App包使用以下链接(CPU,GPU通用) -python -m pip install -U https://paddle-serving.bj.bcebos.com/whl/paddle_serving_client-0.0.0-cp36-none-any.whl https://paddle-serving.bj.bcebos.com/whl/paddle_serving_app-0.0.0-py3-none-any.whl -``` - -## 二、训练模型转Serving模型 - -在前序文档 [基于Python预测引擎推理](./inference.md) 中,我们提供了如何把训练的checkpoint转换成Paddle模型。Paddle模型通常由一个文件夹构成,内含模型结构描述文件`model`和模型参数文件`params`。Serving模型由两个文件夹构成,用于存放客户端和服务端的配置。 - -我们以`ch_rec_r34_vd_crnn`模型作为例子,下载链接在: - -``` -wget --no-check-certificate https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_infer.tar -tar xf ch_rec_r34_vd_crnn_infer.tar -``` -因此我们按照Serving模型转换教程,运行下列python文件。 -``` -python tools/inference_to_serving.py --model_dir ch_rec_r34_vd_crnn -``` -最终会在`serving_client_dir`和`serving_server_dir`生成客户端和服务端的模型配置。其中`serving_server_dir`和`serving_client_dir`的名字可以自定义。最终文件结构如下 - -``` -/ch_rec_r34_vd_crnn/ -├── serving_client_dir # 客户端配置文件夹 -└── serving_server_dir # 服务端配置文件夹 -``` - -## 三、文本检测模型Serving推理 - -启动服务可以根据实际需求选择启动`标准版`或者`快速版`,两种方式的对比如下表: - -|版本|特点|适用场景| -|-|-|-| -|标准版|稳定性高,分布式部署|适用于吞吐量大,需要跨机房部署的情况| -|快速版|部署方便,预测速度快|适用于对预测速度要求高,迭代速度快的场景,Windows用户只能选择快速版| - -接下来的命令中,我们会指定快速版和标准版的命令。需要说明的是,标准版只能用Linux平台,快速版可以支持Linux/Windows。 -文本检测模型推理,默认使用DB模型的配置参数,识别默认为CRNN。 - -配置文件在`params.py`中,我们贴出配置部分,如果需要做改动,也在这个文件内部进行修改。 - -``` -def read_params(): - cfg = Config() - #use gpu - cfg.use_gpu = False # 是否使用GPU - cfg.use_pdserving = True # 是否使用paddleserving,必须为True - - #params for text detector - cfg.det_algorithm = "DB" # 检测算法, DB/EAST等 - cfg.det_model_dir = "./det_mv_server/" # 检测算法模型路径 - cfg.det_max_side_len = 960 - - #DB params - cfg.det_db_thresh =0.3 - cfg.det_db_box_thresh =0.5 - cfg.det_db_unclip_ratio =2.0 - - #EAST params - cfg.det_east_score_thresh = 0.8 - cfg.det_east_cover_thresh = 0.1 - cfg.det_east_nms_thresh = 0.2 - - #params for text recognizer - cfg.rec_algorithm = "CRNN" # 识别算法, CRNN/RARE等 - cfg.rec_model_dir = "./ocr_rec_server/" # 识别算法模型路径 - - cfg.rec_image_shape = "3, 32, 320" - cfg.rec_batch_num = 30 - cfg.max_text_length = 25 - - cfg.rec_char_dict_path = "./ppocr_keys_v1.txt" # 识别算法字典文件 - cfg.use_space_char = True - - #params for text classifier - cfg.use_angle_cls = True # 是否启用分类算法 - cfg.cls_model_dir = "./ocr_clas_server/" # 分类算法模型路径 - cfg.cls_image_shape = "3, 48, 192" - cfg.label_list = ['0', '180'] - cfg.cls_batch_num = 30 - cfg.cls_thresh = 0.9 - - return cfg -``` -与本地预测不同的是,Serving预测需要一个客户端和一个服务端,因此接下来的教程都是两行代码。 - -在正式执行服务端启动命令之前,先export PYTHONPATH到工程主目录下。 -``` -export PYTHONPATH=$PWD:$PYTHONPATH -cd deploy/pdserving -``` -为了方便用户复现Demo程序,我们提供了Chinese and English ultra-lightweight OCR model (8.1M)版本的Serving模型 -``` -wget --no-check-certificate https://paddleocr.bj.bcebos.com/deploy/pdserving/ocr_pdserving_suite.tar.gz -tar xf ocr_pdserving_suite.tar.gz -``` - -### 1. 超轻量中文检测模型推理 - -超轻量中文检测模型推理,可以执行如下命令启动服务端: - -``` -#根据环境只需要启动其中一个就可以 -python det_rpc_server.py #标准版,Linux用户 -python det_local_server.py #快速版,Windows/Linux用户 -``` - -客户端 - -``` -python det_web_client.py -``` - - -Serving的推测和本地预测不同点在于,客户端发送请求到服务端,服务端需要检测到文字框之后返回框的坐标,此处没有后处理的图片,只能看到坐标值。 - -## 四、文本识别模型Serving推理 - -下面将介绍超轻量中文识别模型推理、基于CTC损失的识别模型推理和基于Attention损失的识别模型推理。对于中文文本识别,建议优先选择基于CTC损失的识别模型,实践中也发现基于Attention损失的效果不如基于CTC损失的识别模型。此外,如果训练时修改了文本的字典,请参考下面的自定义文本识别字典的推理。 - -### 1. 超轻量中文识别模型推理 - -超轻量中文识别模型推理,可以执行如下命令启动服务端: -需要注意params.py中的`--use_gpu`的值 -``` -#根据环境只需要启动其中一个就可以 -python rec_rpc_server.py #标准版,Linux用户 -python rec_local_server.py #快速版,Windows/Linux用户 -``` -如果需要使用CPU版本,还需增加 `--use_gpu False`。 - -客户端 - -``` -python rec_web_client.py -``` - -![](../imgs_words/ch/word_4.jpg) - -执行命令后,上面图像的预测结果(识别的文本和得分)会打印到屏幕上,示例如下: - -``` -{u'result': {u'score': [u'0.89547354'], u'pred_text': ['实力活力']}} -``` - - - -## 五、方向分类模型推理 - -下面将介绍方向分类模型推理。 - - - -### 1. 方向分类模型推理 - -方向分类模型推理, 可以执行如下命令启动服务端: -需要注意params.py中的`--use_gpu`的值 -``` -#根据环境只需要启动其中一个就可以 -python clas_rpc_server.py #标准版,Linux用户 -python clas_local_server.py #快速版,Windows/Linux用户 -``` - -客户端 - -``` -python rec_web_client.py -``` - -![](../imgs_words/ch/word_4.jpg) - -执行命令后,上面图像的预测结果(分类的方向和得分)会打印到屏幕上,示例如下: - -``` -{u'result': {u'direction': [u'0'], u'score': [u'0.9999963']}} -``` - - -## 六、文本检测、方向分类和文字识别串联Serving推理 - -### 1. 超轻量中文OCR模型推理 - -在执行预测时,需要通过参数`image_dir`指定单张图像或者图像集合的路径、参数`det_model_dir`,`cls_model_dir`和`rec_model_dir`分别指定检测,方向分类和识别的inference模型路径。参数`use_angle_cls`用于控制是否启用方向分类模型。与本地预测不同的是,为了减少网络传输耗时,可视化识别结果目前不做处理,用户收到的是推理得到的文字字段。 - -执行如下命令启动服务端: -需要注意params.py中的`--use_gpu`的值 -``` -#标准版,Linux用户 -#GPU用户 -python -m paddle_serving_server_gpu.serve --model det_infer_server --port 9293 --gpu_id 0 -python -m paddle_serving_server_gpu.serve --model cls_infer_server --port 9294 --gpu_id 0 -python ocr_rpc_server.py -#CPU用户 -python -m paddle_serving_server.serve --model det_infer_server --port 9293 -python -m paddle_serving_server.serve --model cls_infer_server --port 9294 -python ocr_rpc_server.py - -#快速版,Windows/Linux用户 -python ocr_local_server.py -``` - -客户端 - -``` -python rec_web_client.py -``` diff --git a/doc/doc_ch/update.md b/doc/doc_ch/update.md index 9927a228d2..07591ea126 100644 --- a/doc/doc_ch/update.md +++ b/doc/doc_ch/update.md @@ -1,9 +1,9 @@ # 更新 - 2022.5.9 发布PaddleOCR v2.5。发布内容包括: - - [PP-OCRv3](./doc/doc_ch/ppocr_introduction.md#pp-ocrv3),速度可比情况下,中文场景效果相比于PP-OCRv2再提升5%,英文场景提升11%,80语种多语言模型平均识别准确率提升5%以上; - - 半自动标注工具[PPOCRLabelv2](./PPOCRLabel):新增表格文字图像、图像关键信息抽取任务和不规则文字图像的标注功能; + - [PP-OCRv3](./ppocr_introduction.md#pp-ocrv3),速度可比情况下,中文场景效果相比于PP-OCRv2再提升5%,英文场景提升11%,80语种多语言模型平均识别准确率提升5%以上; + - 半自动标注工具[PPOCRLabelv2](../../PPOCRLabel):新增表格文字图像、图像关键信息抽取任务和不规则文字图像的标注功能; - OCR产业落地工具集:打通22种训练部署软硬件环境与方式,覆盖企业90%的训练部署环境需求 - - 交互式OCR开源电子书[《动手学OCR》](./doc/doc_ch/ocr_book.md),覆盖OCR全栈技术的前沿理论与代码实践,并配套教学视频。 + - 交互式OCR开源电子书[《动手学OCR》](./ocr_book.md),覆盖OCR全栈技术的前沿理论与代码实践,并配套教学视频。 - 2022.5.7 添加对[Weights & Biases](https://docs.wandb.ai/)训练日志记录工具的支持。 - 2021.12.21 《OCR十讲》课程开讲,12月21日起每晚八点半线上授课! 【免费】报名地址:https://aistudio.baidu.com/aistudio/course/introduce/25207 - 2021.12.21 发布PaddleOCR v2.4。OCR算法新增1种文本检测算法(PSENet),3种文本识别算法(NRTR、SEED、SAR);文档结构化算法新增1种关键信息提取算法(SDMGR),3种DocVQA算法(LayoutLM、LayoutLMv2,LayoutXLM)。 diff --git a/doc/doc_en/algorithm_det_east_en.md b/doc/doc_en/algorithm_det_east_en.md index 3955809a49..07c434a9b1 100644 --- a/doc/doc_en/algorithm_det_east_en.md +++ b/doc/doc_en/algorithm_det_east_en.md @@ -40,7 +40,7 @@ Please prepare your environment referring to [prepare the environment](./environ The above EAST model is trained using the ICDAR2015 text detection public dataset. For the download of the dataset, please refer to [ocr_datasets](./dataset/ocr_datasets_en.md). -After the data download is complete, please refer to [Text Detection Training Tutorial](./detection.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. +After the data download is complete, please refer to [Text Detection Training Tutorial](./detection_en.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. diff --git a/doc/doc_en/algorithm_det_fcenet_en.md b/doc/doc_en/algorithm_det_fcenet_en.md index e15fb9a07e..f3c51a91a4 100644 --- a/doc/doc_en/algorithm_det_fcenet_en.md +++ b/doc/doc_en/algorithm_det_fcenet_en.md @@ -37,7 +37,7 @@ Please prepare your environment referring to [prepare the environment](./environ The above FCE model is trained using the CTW1500 text detection public dataset. For the download of the dataset, please refer to [ocr_datasets](./dataset/ocr_datasets_en.md). -After the data download is complete, please refer to [Text Detection Training Tutorial](./detection.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. +After the data download is complete, please refer to [Text Detection Training Tutorial](./detection_en.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. ## 4. Inference and Deployment diff --git a/doc/doc_en/algorithm_det_psenet_en.md b/doc/doc_en/algorithm_det_psenet_en.md index d4cb3ea7d1..3977a156ac 100644 --- a/doc/doc_en/algorithm_det_psenet_en.md +++ b/doc/doc_en/algorithm_det_psenet_en.md @@ -39,7 +39,7 @@ Please prepare your environment referring to [prepare the environment](./environ The above PSE model is trained using the ICDAR2015 text detection public dataset. For the download of the dataset, please refer to [ocr_datasets](./dataset/ocr_datasets_en.md). -After the data download is complete, please refer to [Text Detection Training Tutorial](./detection.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. +After the data download is complete, please refer to [Text Detection Training Tutorial](./detection_en.md) for training. PaddleOCR has modularized the code structure, so that you only need to **replace the configuration file** to train different detection models. ## 4. Inference and Deployment diff --git a/doc/doc_en/algorithm_e2e_pgnet_en.md b/doc/doc_en/algorithm_e2e_pgnet_en.md index c7cb3221cc..ab74c57bc3 100644 --- a/doc/doc_en/algorithm_e2e_pgnet_en.md +++ b/doc/doc_en/algorithm_e2e_pgnet_en.md @@ -36,7 +36,7 @@ The results of detection and recognition are as follows: ## 2. Environment Configuration -Please refer to [Operation Environment Preparation](./environment_en.md) to configure PaddleOCR operating environment first, refer to [PaddleOCR Overview and Project Clone](./paddleOCR_overview_en.md) to clone the project +Please refer to [Operation Environment Preparation](./environment_en.md) to configure PaddleOCR operating environment first, refer to [Project Clone](./clone_en.md) to clone the project ## 3. Quick Use diff --git a/doc/doc_en/algorithm_rec_aster_en.md b/doc/doc_en/algorithm_rec_aster_en.md index 1540681a19..b949cb5b37 100644 --- a/doc/doc_en/algorithm_rec_aster_en.md +++ b/doc/doc_en/algorithm_rec_aster_en.md @@ -33,13 +33,13 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_crnn_en.md b/doc/doc_en/algorithm_rec_crnn_en.md index 571569ee44..8548c2fa62 100644 --- a/doc/doc_en/algorithm_rec_crnn_en.md +++ b/doc/doc_en/algorithm_rec_crnn_en.md @@ -33,13 +33,13 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_nrtr_en.md b/doc/doc_en/algorithm_rec_nrtr_en.md index 3f8fd0adee..40c9b91629 100644 --- a/doc/doc_en/algorithm_rec_nrtr_en.md +++ b/doc/doc_en/algorithm_rec_nrtr_en.md @@ -29,13 +29,13 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_sar_en.md b/doc/doc_en/algorithm_rec_sar_en.md index 8c1e6dbbfa..24b87c10c3 100644 --- a/doc/doc_en/algorithm_rec_sar_en.md +++ b/doc/doc_en/algorithm_rec_sar_en.md @@ -31,13 +31,13 @@ Note:In addition to using the two text recognition datasets MJSynth and SynthTex ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_seed_en.md b/doc/doc_en/algorithm_rec_seed_en.md index 21679f42fd..f8d7ae6d3f 100644 --- a/doc/doc_en/algorithm_rec_seed_en.md +++ b/doc/doc_en/algorithm_rec_seed_en.md @@ -31,13 +31,13 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_srn_en.md b/doc/doc_en/algorithm_rec_srn_en.md index c022a81f9e..1d7fc07dc2 100644 --- a/doc/doc_en/algorithm_rec_srn_en.md +++ b/doc/doc_en/algorithm_rec_srn_en.md @@ -30,13 +30,13 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/algorithm_rec_svtr_en.md b/doc/doc_en/algorithm_rec_svtr_en.md index 2e7deb4c07..d402a6b491 100644 --- a/doc/doc_en/algorithm_rec_svtr_en.md +++ b/doc/doc_en/algorithm_rec_svtr_en.md @@ -34,7 +34,7 @@ The accuracy (%) and model files of SVTR on the public dataset of scene text rec ## 2. Environment -Please refer to ["Environment Preparation"](./environment.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone.md) to clone the project code. +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. #### Dataset Preparation @@ -44,7 +44,7 @@ Please refer to ["Environment Preparation"](./environment.md) to configure the P ## 3. Model Training / Evaluation / Prediction -Please refer to [Text Recognition Tutorial](./recognition.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Training: diff --git a/doc/doc_en/knowledge_distillation_en.md b/doc/doc_en/knowledge_distillation_en.md index bd36907c98..52725e5c05 100755 --- a/doc/doc_en/knowledge_distillation_en.md +++ b/doc/doc_en/knowledge_distillation_en.md @@ -438,10 +438,10 @@ Architecture: ``` If DML is used, that is, the method of two small models learning from each other, the Teacher network structure in the above configuration file needs to be set to the same configuration as the Student model. -Refer to the configuration file for details. [ch_PP-OCRv3_det_dml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml) +Refer to the configuration file for details. [ch_PP-OCRv3_det_dml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml) -The following describes the configuration file parameters [ch_PP-OCRv3_det_cml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml): +The following describes the configuration file parameters [ch_PP-OCRv3_det_cml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml): ``` Architecture: diff --git a/doc/doc_en/multi_languages_en.md b/doc/doc_en/multi_languages_en.md index 4696a3e842..d9cb180f70 100644 --- a/doc/doc_en/multi_languages_en.md +++ b/doc/doc_en/multi_languages_en.md @@ -187,10 +187,10 @@ In addition to installing the whl package for quick forecasting, PPOCR also provides a variety of forecasting deployment methods. If necessary, you can read related documents: -- [Python Inference](./inference_en.md) -- [C++ Inference](../../deploy/cpp_infer/readme_en.md) +- [Python Inference](./inference_ppocr_en.md) +- [C++ Inference](../../deploy/cpp_infer/readme.md) - [Serving](../../deploy/hubserving/readme_en.md) -- [Mobile](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/deploy/lite/readme_en.md) +- [Mobile](../../deploy/lite/readme.md) - [Benchmark](./benchmark_en.md) diff --git a/doc/doc_en/update_en.md b/doc/doc_en/update_en.md index a900219b24..a44dd0d70c 100644 --- a/doc/doc_en/update_en.md +++ b/doc/doc_en/update_en.md @@ -1,8 +1,8 @@ # RECENT UPDATES - 2022.5.9 release PaddleOCR v2.5, including: - - [PP-OCRv3](./doc/doc_en/ppocr_introduction_en.md#pp-ocrv3): With comparable speed, the effect of Chinese scene is further improved by 5% compared with PP-OCRv2, the effect of English scene is improved by 11%, and the average recognition accuracy of 80 language multilingual models is improved by more than 5%. - - [PPOCRLabelv2](./PPOCRLabel): Add the annotation function for table recognition task, key information extraction task and irregular text image. - - Interactive e-book [*"Dive into OCR"*](./doc/doc_en/ocr_book_en.md), covers the cutting-edge theory and code practice of OCR full stack technology. + - [PP-OCRv3](./ppocr_introduction_en.md#pp-ocrv3): With comparable speed, the effect of Chinese scene is further improved by 5% compared with PP-OCRv2, the effect of English scene is improved by 11%, and the average recognition accuracy of 80 language multilingual models is improved by more than 5%. + - [PPOCRLabelv2](../../PPOCRLabel): Add the annotation function for table recognition task, key information extraction task and irregular text image. + - Interactive e-book [*"Dive into OCR"*](./ocr_book_en.md), covers the cutting-edge theory and code practice of OCR full stack technology. - 2022.5.7 Add support for metric and model logging during training to [Weights & Biases](https://docs.wandb.ai/). - 2021.12.21 OCR open source online course starts. The lesson starts at 8:30 every night and lasts for ten days. Free registration: https://aistudio.baidu.com/aistudio/course/introduce/25207 - 2021.12.21 release PaddleOCR v2.4, release 1 text detection algorithm (PSENet), 3 text recognition algorithms (NRTR、SEED、SAR), 1 key information extraction algorithm (SDMGR) and 3 DocVQA algorithms (LayoutLM、LayoutLMv2,LayoutXLM). diff --git a/ppstructure/vqa/README_ch.md b/ppstructure/vqa/README_ch.md index ff513f8f7d..b677dc07bc 100644 --- a/ppstructure/vqa/README_ch.md +++ b/ppstructure/vqa/README_ch.md @@ -52,7 +52,7 @@ PP-Structure 里的 DOC-VQA算法基于PaddleNLP自然语言处理算法库进 ### 3.1 SER -![](../../doc/vqa/result_ser/zh_val_0_ser.jpg) | ![](../../doc/vqa/result_ser/zh_val_42_ser.jpg) +![](../docs/vqa/result_ser/zh_val_0_ser.jpg) | ![](../docs/vqa/result_ser/zh_val_42_ser.jpg) ---|--- 图中不同颜色的框表示不同的类别,对于XFUND数据集,有`QUESTION`, `ANSWER`, `HEADER` 3种类别 @@ -65,7 +65,7 @@ PP-Structure 里的 DOC-VQA算法基于PaddleNLP自然语言处理算法库进 ### 3.2 RE -![](../../doc/vqa/result_re/zh_val_21_re.jpg) | ![](../../doc/vqa/result_re/zh_val_40_re.jpg) +![](../docs/vqa/result_re/zh_val_21_re.jpg) | ![](../docs/vqa/result_re/zh_val_40_re.jpg) ---|--- diff --git a/test_tipc/docs/jeston_test_train_inference_python.md b/test_tipc/docs/jeston_test_train_inference_python.md index 9e9d15fb67..b25175ed00 100644 --- a/test_tipc/docs/jeston_test_train_inference_python.md +++ b/test_tipc/docs/jeston_test_train_inference_python.md @@ -115,4 +115,4 @@ ValueError: The results of python_infer_gpu_usetrt_True_precision_fp32_batchsize ## 3. 更多教程 本文档为功能测试用,更丰富的训练预测使用教程请参考: [模型训练](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/training.md) -[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference.md) +[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference_ppocr.md) diff --git a/test_tipc/docs/mac_test_train_inference_python.md b/test_tipc/docs/mac_test_train_inference_python.md index ea6e0218b1..c37291a8fc 100644 --- a/test_tipc/docs/mac_test_train_inference_python.md +++ b/test_tipc/docs/mac_test_train_inference_python.md @@ -152,4 +152,4 @@ ValueError: The results of python_infer_cpu_usemkldnn_False_threads_1_batchsize_ ## 3. 更多教程 本文档为功能测试用,更丰富的训练预测使用教程请参考: [模型训练](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/training.md) -[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference.md) +[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference_ppocr.md) diff --git a/test_tipc/docs/test_train_inference_python.md b/test_tipc/docs/test_train_inference_python.md index fa969cbe1b..99de940079 100644 --- a/test_tipc/docs/test_train_inference_python.md +++ b/test_tipc/docs/test_train_inference_python.md @@ -153,4 +153,4 @@ python3.7 test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.tx ## 3. 更多教程 本文档为功能测试用,更丰富的训练预测使用教程请参考: [模型训练](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/training.md) -[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference.md) +[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference_ppocr.md) diff --git a/test_tipc/docs/win_test_train_inference_python.md b/test_tipc/docs/win_test_train_inference_python.md index 95585af038..6e3ce93bb3 100644 --- a/test_tipc/docs/win_test_train_inference_python.md +++ b/test_tipc/docs/win_test_train_inference_python.md @@ -156,4 +156,4 @@ ValueError: The results of python_infer_cpu_usemkldnn_False_threads_1_batchsize_ ## 3. 更多教程 本文档为功能测试用,更丰富的训练预测使用教程请参考: [模型训练](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/training.md) -[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference.md) +[基于Python预测引擎推理](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/inference_ppocr.md) From 2e80aab477be38425620a2116a54efc741d7335c Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Wed, 18 May 2022 19:03:18 +0800 Subject: [PATCH 026/129] add support for svtr static training (#6328) --- ppocr/modeling/architectures/__init__.py | 26 ++++++++++++++++++++---- ppocr/modeling/heads/rec_sar_head.py | 20 +++++++++--------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/ppocr/modeling/architectures/__init__.py b/ppocr/modeling/architectures/__init__.py index 3f47f64a0f..1c955ef3ab 100755 --- a/ppocr/modeling/architectures/__init__.py +++ b/ppocr/modeling/architectures/__init__.py @@ -40,11 +40,29 @@ def apply_to_static(model, config, logger): return model assert "image_shape" in config[ "Global"], "image_shape must be assigned for static training mode..." - supported_list = ["DB"] - assert config["Architecture"][ - "algorithm"] in supported_list, f"algorithms that supports static training must in in {supported_list} but got {config['Architecture']['algorithm']}" + supported_list = ["DB", "SVTR"] + if config["Architecture"]["algorithm"] in ["Distillation"]: + algo = list(config["Architecture"]["Models"].values())[0]["algorithm"] + else: + algo = config["Architecture"]["algorithm"] + assert algo in supported_list, f"algorithms that supports static training must in in {supported_list} but got {algo}" + + specs = [ + InputSpec( + [None] + config["Global"]["image_shape"], dtype='float32') + ] + + if algo == "SVTR": + specs.append([ + InputSpec( + [None, config["Global"]["max_text_length"]], + dtype='int64'), InputSpec( + [None, config["Global"]["max_text_length"]], dtype='int64'), + InputSpec( + [None], dtype='int64'), InputSpec( + [None], dtype='float64') + ]) - specs = [InputSpec([None] + config["Global"]["image_shape"])] model = to_static(model, input_spec=specs) logger.info("Successfully to apply @to_static with specs: {}".format(specs)) return model diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py index 0e6b34404b..5e64cae85a 100644 --- a/ppocr/modeling/heads/rec_sar_head.py +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -83,7 +83,7 @@ class SAREncoder(nn.Layer): def forward(self, feat, img_metas=None): if img_metas is not None: - assert len(img_metas[0]) == feat.shape[0] + assert len(img_metas[0]) == paddle.shape(feat)[0] valid_ratios = None if img_metas is not None and self.mask: @@ -98,9 +98,10 @@ class SAREncoder(nn.Layer): if valid_ratios is not None: valid_hf = [] - T = holistic_feat.shape[1] - for i in range(len(valid_ratios)): - valid_step = min(T, math.ceil(T * valid_ratios[i])) - 1 + T = paddle.shape(holistic_feat)[1] + for i in range(paddle.shape(valid_ratios)[0]): + valid_step = paddle.minimum( + T, paddle.ceil(valid_ratios[i] * T).astype('int32')) - 1 valid_hf.append(holistic_feat[i, valid_step, :]) valid_hf = paddle.stack(valid_hf, axis=0) else: @@ -247,13 +248,14 @@ class ParallelSARDecoder(BaseDecoder): # bsz * (seq_len + 1) * h * w * attn_size attn_weight = self.conv1x1_2(attn_weight) # bsz * (seq_len + 1) * h * w * 1 - bsz, T, h, w, c = attn_weight.shape + bsz, T, h, w, c = paddle.shape(attn_weight) assert c == 1 if valid_ratios is not None: # cal mask of attention weight - for i in range(len(valid_ratios)): - valid_width = min(w, math.ceil(w * valid_ratios[i])) + for i in range(paddle.shape(valid_ratios)[0]): + valid_width = paddle.minimum( + w, paddle.ceil(valid_ratios[i] * w).astype("int32")) if valid_width < w: attn_weight[i, :, :, valid_width:, :] = float('-inf') @@ -288,7 +290,7 @@ class ParallelSARDecoder(BaseDecoder): img_metas: [label, valid_ratio] ''' if img_metas is not None: - assert len(img_metas[0]) == feat.shape[0] + assert paddle.shape(img_metas[0])[0] == paddle.shape(feat)[0] valid_ratios = None if img_metas is not None and self.mask: @@ -302,7 +304,6 @@ class ParallelSARDecoder(BaseDecoder): # bsz * (seq_len + 1) * C out_dec = self._2d_attention( in_dec, feat, out_enc, valid_ratios=valid_ratios) - # bsz * (seq_len + 1) * num_classes return out_dec[:, 1:, :] # bsz * seq_len * num_classes @@ -395,7 +396,6 @@ class SARHead(nn.Layer): if self.training: label = targets[0] # label - label = paddle.to_tensor(label, dtype='int64') final_out = self.decoder( feat, holistic_feat, label, img_metas=targets) else: From 27739ec79ad31389cfb551108a32c6dc05274d85 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Wed, 18 May 2022 11:33:15 +0000 Subject: [PATCH 027/129] fix doc link --- doc/doc_ch/models_list.md | 4 ++-- doc/doc_en/models_list_en.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/doc_ch/models_list.md b/doc/doc_ch/models_list.md index 318d5874f5..c36cac037e 100644 --- a/doc/doc_ch/models_list.md +++ b/doc/doc_ch/models_list.md @@ -22,7 +22,7 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型类型|模型格式|简介| |--- | --- | --- | -|推理模型|inference.pdmodel、inference.pdiparams|用于预测引擎推理,[详情](./inference.md)| +|推理模型|inference.pdmodel、inference.pdiparams|用于预测引擎推理,[详情](./inference_ppocr.md)| |训练模型、预训练模型|\*.pdparams、\*.pdopt、\*.states |训练过程中保存的模型的参数、优化器状态和训练中间信息,多用于模型指标评估和恢复训练| |nb模型|\*.nb|经过飞桨Paddle-Lite工具优化后的模型,适用于移动端/IoT端等端侧部署场景(需使用飞桨Paddle Lite部署)。| @@ -114,7 +114,7 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 | ka_PP-OCRv3_rec | ppocr/utils/dict/ka_dict.txt |卡纳达文识别|[ka_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml)|9.9M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ka_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ka_PP-OCRv3_rec_train.tar) | | ta_PP-OCRv3_rec | ppocr/utils/dict/ta_dict.txt |泰米尔文识别|[ta_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml)|9.6M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ta_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ta_PP-OCRv3_rec_train.tar) | | latin_PP-OCRv3_rec | ppocr/utils/dict/latin_dict.txt | 拉丁文识别 | [latin_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml) |9.7M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/latin_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/latin_PP-OCRv3_rec_train.tar) | -| arabic_PP-OCRv3_rec | ppocr/utils/dict/arabic_dict.txt | 阿拉伯字母 | [arabic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/rec_arabic_lite_train.yml) |9.6M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_train.tar) | +| arabic_PP-OCRv3_rec | ppocr/utils/dict/arabic_dict.txt | 阿拉伯字母 | [arabic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml) |9.6M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_train.tar) | | cyrillic_PP-OCRv3_rec | ppocr/utils/dict/cyrillic_dict.txt | 斯拉夫字母 | [cyrillic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml) |9.6M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/cyrillic_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/cyrillic_PP-OCRv3_rec_train.tar) | | devanagari_PP-OCRv3_rec | ppocr/utils/dict/devanagari_dict.txt |梵文字母 | [devanagari_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml) |9.9M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/devanagari_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/devanagari_PP-OCRv3_rec_train.tar) | diff --git a/doc/doc_en/models_list_en.md b/doc/doc_en/models_list_en.md index 8e8c1f2fe1..c52f71dfe4 100644 --- a/doc/doc_en/models_list_en.md +++ b/doc/doc_en/models_list_en.md @@ -20,7 +20,7 @@ The downloadable models provided by PaddleOCR include `inference model`, `traine |model type|model format|description| |--- | --- | --- | -|inference model|inference.pdmodel、inference.pdiparams|Used for inference based on Paddle inference engine,[detail](./inference_en.md)| +|inference model|inference.pdmodel、inference.pdiparams|Used for inference based on Paddle inference engine,[detail](./inference_ppocr_en.md)| |trained model, pre-trained model|\*.pdparams、\*.pdopt、\*.states |The checkpoints model saved in the training process, which stores the parameters of the model, mostly used for model evaluation and continuous training.| |nb model|\*.nb| Model optimized by Paddle-Lite, which is suitable for mobile-side deployment scenarios (Paddle-Lite is needed for nb model deployment). | @@ -37,7 +37,7 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv3_det_slim| [New] slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection |[ch_PP-OCRv3_det_cml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)| 1.1M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/ch/ch_PP-OCRv3_det_slim_distill_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_slim_infer.nb)| +|ch_PP-OCRv3_det_slim| [New] slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection |[ch_PP-OCRv3_det_cml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)| 1.1M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_slim_distill_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_slim_infer.nb)| |ch_PP-OCRv3_det| [New] Original lightweight model, supporting Chinese, English, multilingual text detection |[ch_PP-OCRv3_det_cml.yml](../../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml)| 3.8M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar)| |ch_PP-OCRv2_det_slim| [New] slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| |ch_PP-OCRv2_det| [New] Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| @@ -75,7 +75,7 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv3_rec_slim | [New] Slim qunatization with distillation lightweight model, supporting Chinese, English text recognition |[ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml)| 4.9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/ch/ch_PP-OCRv3_rec_slim_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.nb) | +|ch_PP-OCRv3_rec_slim | [New] Slim qunatization with distillation lightweight model, supporting Chinese, English text recognition |[ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml)| 4.9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.nb) | |ch_PP-OCRv3_rec| [New] Original lightweight model, supporting Chinese, English, multilingual text recognition |[ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml)| 12.4M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar) | |ch_PP-OCRv2_rec_slim| Slim qunatization with distillation lightweight model, supporting Chinese, English text recognition|[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | |ch_PP-OCRv2_rec| Original lightweight model, supporting Chinese, English, multilingual text recognition |[ch_PP-OCRv2_rec_distillation.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | @@ -91,7 +91,7 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|en_PP-OCRv3_rec_slim | [New] Slim qunatization with distillation lightweight model, supporting english, English text recognition |[en_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml)| 3.2M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/PP-OCRv3_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_slim_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_slim_infer.nb) | +|en_PP-OCRv3_rec_slim | [New] Slim qunatization with distillation lightweight model, supporting english, English text recognition |[en_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml)| 3.2M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_slim_train.tar) / [nb model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_slim_infer.nb) | |en_PP-OCRv3_rec| [New] Original lightweight model, supporting english, English, multilingual text recognition |[en_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml)| 9.6M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_train.tar) | |en_number_mobile_slim_v2.0_rec|Slim pruned and quantized lightweight model, supporting English and number recognition|[rec_en_number_lite_train.yml](../../configs/rec/multi_language/rec_en_number_lite_train.yml)| 2.7M | [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/en_number_mobile_v2.0_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/en_number_mobile_v2.0_rec_slim_train.tar) | |en_number_mobile_v2.0_rec|Original lightweight model, supporting English and number recognition|[rec_en_number_lite_train.yml](../../configs/rec/multi_language/rec_en_number_lite_train.yml)|2.6M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/multilingual/en_number_mobile_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/multilingual/en_number_mobile_v2.0_rec_train.tar) | @@ -108,7 +108,7 @@ Relationship of the above models is as follows. | ka_PP-OCRv3_rec | ppocr/utils/dict/ka_dict.txt | Lightweight model for Kannada recognition |[ka_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml)|9.9M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ka_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ka_PP-OCRv3_rec_train.tar) | | ta_PP-OCRv3_rec | ppocr/utils/dict/ta_dict.txt |Lightweight model for Tamil recognition|[ta_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml)|9.6M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ta_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/ta_PP-OCRv3_rec_train.tar) | | latin_PP-OCRv3_rec | ppocr/utils/dict/latin_dict.txt | Lightweight model for latin recognition | [latin_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml) |9.7M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/latin_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/latin_PP-OCRv3_rec_train.tar) | -| arabic_PP-OCRv3_rec | ppocr/utils/dict/arabic_dict.txt | Lightweight model for arabic recognition | [arabic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/rec_arabic_lite_train.yml) |9.6M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_train.tar) | +| arabic_PP-OCRv3_rec | ppocr/utils/dict/arabic_dict.txt | Lightweight model for arabic recognition | [arabic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml) |9.6M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/arabic_PP-OCRv3_rec_train.tar) | | cyrillic_PP-OCRv3_rec | ppocr/utils/dict/cyrillic_dict.txt | Lightweight model for cyrillic recognition | [cyrillic_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml) |9.6M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/cyrillic_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/cyrillic_PP-OCRv3_rec_train.tar) | | devanagari_PP-OCRv3_rec | ppocr/utils/dict/devanagari_dict.txt | Lightweight model for devanagari recognition | [devanagari_PP-OCRv3_rec.yml](../../configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml) |9.9M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/devanagari_PP-OCRv3_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/multilingual/devanagari_PP-OCRv3_rec_train.tar) | From bb0c95965682fb08195b02808ebcce5efd58fc6b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 19 May 2022 19:46:40 +0800 Subject: [PATCH 028/129] add benchmark --- applications/车牌识别.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 2abb9c6f7a..afa8d57107 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -357,11 +357,13 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR |方案|hmeans| 模型大小 |预测速度(lite)| |---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms/image | 可以看到量化后能显著降低模型体积并且精度几乎无损。 +预测速度是在android骁龙855上预测275张图像的平均耗时。 + #### 4.1.4 模型导出 使用如下命令可以将训练好的模型进行导出 @@ -571,11 +573,13 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ |方案| acc | 模型大小 |预测速度(lite)| |---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms/image; | 可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 + #### 4.2.5 模型导出 使用如下命令可以将训练好的模型进行导出。 @@ -618,19 +622,22 @@ python tools/infer/predict_system.py \ |方案|hmeans| 模型大小 |预测速度(lite)| |---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms/image | + +预测速度是在android骁龙855上预测275张图像的平均耗时。 - 识别 |方案| acc | 模型大小 |预测速度(lite)| |---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M || -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M || +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M | 1.8ms/image | +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 - 结论 From 16bafedeba9cdae18290717278dc9079f32411b4 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 19 May 2022 19:48:11 +0800 Subject: [PATCH 029/129] add benchmark --- applications/车牌识别.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index afa8d57107..7510f3c5a8 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -362,7 +362,7 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR 可以看到量化后能显著降低模型体积并且精度几乎无损。 -预测速度是在android骁龙855上预测275张图像的平均耗时。 +预测速度是在android骁龙855上预测275张图像的平均耗时。模型在移动端的部署步骤参考[文档](../deploy/lite/readme_ch.md) #### 4.1.4 模型导出 @@ -578,7 +578,7 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ 可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 -预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。模型在移动端的部署步骤参考[文档](../deploy/lite/readme_ch.md) #### 4.2.5 模型导出 From bb66f0cb58496b81002223c12ed4901adcc07603 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Thu, 19 May 2022 20:33:08 +0800 Subject: [PATCH 030/129] add e2e metric and lite speed --- applications/车牌识别.md | 177 +++++++++++++++++++++++++-- tools/end2end/convert_ppocr_label.py | 18 ++- tools/end2end/readme.md | 14 +-- 3 files changed, 181 insertions(+), 28 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 2abb9c6f7a..91a48d2641 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -609,6 +609,148 @@ python tools/infer/predict_system.py \ ![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) +### 4.4 计算End2End指标 + +端到端指标可通过 [PaddleOCR内置脚本](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/tools/end2end/readme.md) 进行计算,具体步骤如下: + +1. 导出模型 + +通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集 + +```bash +# 检测模型 + +# 预训练模型 +python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \ + Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer + +# 非量化模型 +python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/det/infer + +# 量化模型 +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ + Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/det_quant/infer \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \ + Eval.loader.num_workers=0 + +# 识别模型 + +# 预训练模型 +python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \ + Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer + +# 非量化模型 +python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/rec/infer + +# 量化模型 +python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ + Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \ + Global.save_inference_dir=output/CCPD/rec_quant/infer \ + Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ + Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] +``` + +2. 用导出的模型对测试集进行预测 + +此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下: + +```bash +# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 +python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=output/ch_PP-OCRv3_rec_train/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain + +# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` +python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=output/ch_PP-OCRv3_rec_train/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/post + +# PP-OCRv3中英文超轻量检测预训练模型+finetune,PP-OCRv3中英文超轻量识别预训练模型+finetune +python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/finetune + +# PP-OCRv3中英文超轻量检测预训练模型finetune+量化,PP-OCRv3中英文超轻量识别预训练模型finetune+量化 结果转换和评估 +python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant +``` + +3. 转换label并计算指标 + +将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算 + +```bash +python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt + +# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估 +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain +python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain + +# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估 +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post +python3 tools/end2end/eval_end2end.py end2end/gt end2end/post + +# PP-OCRv3中英文超轻量检测预训练模型finetune,PP-OCRv3中英文超轻量识别预训练模型finetune 结果转换和评估 +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/finetune/system_results.txt --save_folder=end2end/finetune +python3 tools/end2end/eval_end2end.py end2end/gt end2end/finetune + +# PP-OCRv3中英文超轻量检测预训练模型finetune+量化,PP-OCRv3中英文超轻量识别预训练模型finetune+量化 结果转换和评估 +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant +python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant +``` + +日志如下: +```bash +The convert label saved in end2end/gt +The convert label saved in end2end/pretrain +start testing... +hit, dt_count, gt_count 2 5988 5006 +character_acc: 70.42% +avg_edit_dist_field: 2.37 +avg_edit_dist_img: 2.37 +precision: 0.03% +recall: 0.04% +fmeasure: 0.04% +The convert label saved in end2end/post +start testing... +hit, dt_count, gt_count 4224 5988 5006 +character_acc: 81.59% +avg_edit_dist_field: 1.47 +avg_edit_dist_img: 1.47 +precision: 70.54% +recall: 84.38% +fmeasure: 76.84% +The convert label saved in end2end/finetune +start testing... +hit, dt_count, gt_count 4286 4898 5006 +character_acc: 94.16% +avg_edit_dist_field: 0.47 +avg_edit_dist_img: 0.47 +precision: 87.51% +recall: 85.62% +fmeasure: 86.55% +The convert label saved in end2end/quant +start testing... +hit, dt_count, gt_count 4349 4951 5006 +character_acc: 94.13% +avg_edit_dist_field: 0.47 +avg_edit_dist_img: 0.47 +precision: 87.84% +recall: 86.88% +fmeasure: 87.36% +``` + +各个方案端到端指标如下: + +|det|rec|fmeasure| +|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型|0.04%| +|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|76.84%| +|PP-OCRv3中英文超轻量检测预训练模型+finetune|PP-OCRv3中英文超轻量识别预训练模型+finetune|86.55%| +|PP-OCRv3中英文超轻量检测预训练模型+finetune+量化|PP-OCRv3中英文超轻量识别预训练模型+finetune+量化|87.36%| + +从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行finetune后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 ### 4.4 实验总结 @@ -616,24 +758,35 @@ python tools/infer/predict_system.py \ - 检测 -|方案|hmeans| 模型大小 |预测速度(lite)| -|---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|方案|hmeans| 模型大小 | 预测速度(lite) | +|---|---|------|------------| +|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| 233ms | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 233ms | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms | - 识别 -|方案| acc | 模型大小 |预测速度(lite)| -|---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M || -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M || +|方案| acc | 模型大小 | 预测速度(lite) | +|---|--------|-------|------------| +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4,2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M | 1.8ms | -- 结论 +- 端到端指标如下: + +|det|rec|fmeasure|模型大小|预测速度(lite) | +|---|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型|0.04%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|76.84%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+finetune|PP-OCRv3中英文超轻量识别预训练模型+finetune|86.55%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+finetune+量化|PP-OCRv3中英文超轻量识别预训练模型+finetune+量化|87.36%|5.8M|224ms| + +*结论* PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过finetune后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过finetune后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 + +从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行finetune后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%并且模型大小降低54%。 diff --git a/tools/end2end/convert_ppocr_label.py b/tools/end2end/convert_ppocr_label.py index 8084cac785..c64b9ed168 100644 --- a/tools/end2end/convert_ppocr_label.py +++ b/tools/end2end/convert_ppocr_label.py @@ -85,10 +85,16 @@ def convert_label(label_dir, mode="gt", save_dir="./save_results/"): print("The convert label saved in {}".format(save_dir)) +def parse_args(): + import argparse + parser = argparse.ArgumentParser(description="args") + parser.add_argument("--label_path", type=str, required=True) + parser.add_argument("--save_folder", type=str, required=True) + parser.add_argument("--mode", type=str, default=False) + args = parser.parse_args() + return args + + if __name__ == "__main__": - - ppocr_label_gt = "/paddle/Datasets/chinese/test_set/Label_refine_310_V2.txt" - convert_label(ppocr_label_gt, "gt", "./save_gt_310_V2/") - - ppocr_label_gt = "./infer_results/ch_PPOCRV2_infer.txt" - convert_label(ppocr_label_gt_en, "pred", "./save_PPOCRV2_infer/") + args = parse_args() + convert_label(args.label_path, args.mode, args.save_folder) diff --git a/tools/end2end/readme.md b/tools/end2end/readme.md index 69da06dcda..636ee764ae 100644 --- a/tools/end2end/readme.md +++ b/tools/end2end/readme.md @@ -23,19 +23,13 @@ all-sum-510/00224225.jpg [{"transcription": "超赞", "points": [[8.0, 48 **步骤二:** 将步骤一保存的数据转换为端对端评测需要的数据格式: -修改 `tools/convert_ppocr_label.py`中的代码,convert_label函数中设置输入标签路径,Mode,保存标签路径等,对预测数据的GTlabel和预测结果的label格式进行转换。 + +修改 `tools/end2end/convert_ppocr_label.py`中的代码,convert_label函数中设置输入标签路径,Mode,保存标签路径等,对预测数据的GTlabel和预测结果的label格式进行转换。 ``` -ppocr_label_gt = "gt_label.txt" -convert_label(ppocr_label_gt, "gt", "./save_gt_label/") +python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=path/to/label_txt --save_folder=save_gt_label -ppocr_label_gt = "./ch_PP-OCRv2_results/system_results.txt" -convert_label(ppocr_label_gt_en, "pred", "./save_PPOCRV2_infer/") -``` - -运行`convert_ppocr_label.py`: -``` -python3 tools/convert_ppocr_label.py +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=path/to/pred_txt --save_folder=save_PPOCRV2_infer ``` 得到如下结果: From f05f5b3d0b70a1a675dc49ab5a8375e8d4612161 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Thu, 19 May 2022 20:56:00 +0800 Subject: [PATCH 031/129] add speed up in doc --- applications/车牌识别.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 91a48d2641..18390ddef2 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -31,7 +31,7 @@ 3. 图像质量差: 运动模糊,由于强光,反射或阴影造成的光照和对比度较差, 车牌(部分)遮挡; 4. 在车辆管理等场景场景对于模型速度有着一定限制。 -针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升x%。 +针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) @@ -355,12 +355,12 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR 量化后指标对比如下 -|方案|hmeans| 模型大小 |预测速度(lite)| -|---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|方案|hmeans| 模型大小 | 预测速度(lite) | +|---|---|------|------------| +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms | -可以看到量化后能显著降低模型体积并且精度几乎无损。 +可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。 #### 4.1.4 模型导出 @@ -569,12 +569,12 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ 量化后指标对比如下 -|方案| acc | 模型大小 |预测速度(lite)| -|---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | +|方案| acc | 模型大小 | 预测速度(lite) | +|---|--------|-------|------------| +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms | -可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 +可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。 #### 4.2.5 模型导出 From 815be0b939a355e0f6faf1aaf6ce89bed1bac36d Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Thu, 19 May 2022 20:58:17 +0800 Subject: [PATCH 032/129] update toc --- applications/车牌识别.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 18390ddef2..bc368a6a35 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -18,7 +18,8 @@ - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) - [4.2.5 模型导出](#425-模型导出) - [4.3 串联推理](#43-串联推理) - - [4.4 实验总结](#44-实验总结) + - [4.4 计算End2End指标](#44-计算End2End指标) + - [4.5 实验总结](#45-实验总结) ## 1. 项目介绍 @@ -752,7 +753,7 @@ fmeasure: 87.36% 从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行finetune后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 -### 4.4 实验总结 +### 4.5 实验总结 我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和finetune 和finetune+量化3种方案的实验,指标对比如下: From ab8e8ce564c76a23e04fcf13b6837e43c2031688 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Thu, 19 May 2022 21:08:32 +0800 Subject: [PATCH 033/129] replace finetune with fine-tune --- applications/车牌识别.md | 54 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index bc368a6a35..24115f6714 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -283,7 +283,7 @@ python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \ 2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。 2. 优化器相关: 1. Optimizer.lr.name: 学习率衰减器设为常量 Const - 2. Optimizer.lr.learning_rate: 做finetune实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 + 2. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 3. Optimizer.lr.warmup_epoch: warmup_epoch设为0 3. 数据集相关: 1. Train.dataset.data_dir:指向训练集图片存放目录 @@ -363,6 +363,8 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR 可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。 +速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。 + #### 4.1.4 模型导出 使用如下命令可以将训练好的模型进行导出 @@ -472,7 +474,7 @@ W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6 从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个`·`。针对这种情况,有如下两种方案: 1. 直接通过后处理去掉多识别的`·`。 -2. 进行finetune。 +2. 进行 fine-tune。 #### 4.2.2 预训练模型直接预测+改动后处理 @@ -501,7 +503,7 @@ text = text.replace('·','') 2. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。 2. 优化器相关 1. Optimizer.lr.name: 学习率衰减器设为常量 Const - 2. Optimizer.lr.learning_rate: 做finetune实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 + 2. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍 3. Optimizer.lr.warmup_epoch: warmup_epoch设为0 3. 数据集相关 1. Train.dataset.data_dir:指向训练集图片存放目录 @@ -509,7 +511,7 @@ text = text.replace('·','') 3. Eval.dataset.data_dir:指向测试集图片存放目录 4. Eval.dataset.label_file_list:指向测试集标注文件 -使用如下命令启动finetune +使用如下命令启动 fine-tune ```bash python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ @@ -577,6 +579,8 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ 可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。 +速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。 + #### 4.2.5 模型导出 使用如下命令可以将训练好的模型进行导出。 @@ -670,10 +674,10 @@ python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_dis # PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=output/ch_PP-OCRv3_rec_train/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/post -# PP-OCRv3中英文超轻量检测预训练模型+finetune,PP-OCRv3中英文超轻量识别预训练模型+finetune -python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/finetune +# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune +python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune -# PP-OCRv3中英文超轻量检测预训练模型finetune+量化,PP-OCRv3中英文超轻量识别预训练模型finetune+量化 结果转换和评估 +# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估 python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant ``` @@ -692,11 +696,11 @@ python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post python3 tools/end2end/eval_end2end.py end2end/gt end2end/post -# PP-OCRv3中英文超轻量检测预训练模型finetune,PP-OCRv3中英文超轻量识别预训练模型finetune 结果转换和评估 -python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/finetune/system_results.txt --save_folder=end2end/finetune -python3 tools/end2end/eval_end2end.py end2end/gt end2end/finetune +# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估 +python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune +python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune -# PP-OCRv3中英文超轻量检测预训练模型finetune+量化,PP-OCRv3中英文超轻量识别预训练模型finetune+量化 结果转换和评估 +# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估 python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant ``` @@ -722,7 +726,7 @@ avg_edit_dist_img: 1.47 precision: 70.54% recall: 84.38% fmeasure: 76.84% -The convert label saved in end2end/finetune +The convert label saved in end2end/fine-tune start testing... hit, dt_count, gt_count 4286 4898 5006 character_acc: 94.16% @@ -748,14 +752,14 @@ fmeasure: 87.36% |---|---|---| |PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型|0.04%| |PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|76.84%| -|PP-OCRv3中英文超轻量检测预训练模型+finetune|PP-OCRv3中英文超轻量识别预训练模型+finetune|86.55%| -|PP-OCRv3中英文超轻量检测预训练模型+finetune+量化|PP-OCRv3中英文超轻量识别预训练模型+finetune+量化|87.36%| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune|PP-OCRv3中英文超轻量识别预训练模型+fine-tune|86.55%| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化|PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|87.36%| -从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行finetune后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 +从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行 fine-tune 后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 ### 4.5 实验总结 -我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和finetune 和finetune+量化3种方案的实验,指标对比如下: +我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune+量化3种方案的实验,并基于[PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: - 检测 @@ -777,17 +781,17 @@ fmeasure: 87.36% - 端到端指标如下: -|det|rec|fmeasure|模型大小|预测速度(lite) | -|---|---|---|---|---| -|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型|0.04%|12.8M|298ms| -|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|76.84%|12.8M|298ms| -|PP-OCRv3中英文超轻量检测预训练模型+finetune|PP-OCRv3中英文超轻量识别预训练模型+finetune|86.55%|12.8M|298ms| -|PP-OCRv3中英文超轻量检测预训练模型+finetune+量化|PP-OCRv3中英文超轻量识别预训练模型+finetune+量化|87.36%|5.8M|224ms| +| det | rec |fmeasure|模型大小|预测速度(lite) | +|-----------------------------------|------------------------------------|---|---|---| +| PP-OCRv3中英文超轻量检测预训练模型 | PP-OCRv3中英文超轻量识别预训练模型 |0.04%|12.8M|298ms| +| PP-OCRv3中英文超轻量检测预训练模型 | PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` |76.84%|12.8M|298ms| +| PP-OCRv3中英文超轻量检测预训练模型+fine-tune | PP-OCRv3中英文超轻量识别预训练模型+fine-tune |86.55%|12.8M|298ms| +| PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化 | PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化 |87.36%|5.8M|224ms| *结论* -PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过finetune后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 +PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 -PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过finetune后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 +PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 -从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行finetune后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%并且模型大小降低54%。 +从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行 fine-tune 后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%并且模型大小降低54%。 From 8e4f8f6912dc5e541b7adad940e465c5207e8fd7 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Fri, 20 May 2022 11:46:08 +0800 Subject: [PATCH 034/129] update doc --- applications/车牌识别.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 24115f6714..6959bfae05 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -17,20 +17,20 @@ - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) - [4.2.5 模型导出](#425-模型导出) - - [4.3 串联推理](#43-串联推理) + - [4.3 部署](#43-部署) - [4.4 计算End2End指标](#44-计算End2End指标) - [4.5 实验总结](#45-实验总结) ## 1. 项目介绍 -车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 +车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。 -结合我国国情,目前车牌识别技术的难点有: +本项目难点如下: + +1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 +2. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 +3. 边缘和端测场景应用对模型大小有限制,推理速度有要求 -1. 车牌样式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 -2. 车牌位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; -3. 图像质量差: 运动模糊,由于强光,反射或阴影造成的光照和对比度较差, 车牌(部分)遮挡; -4. 在车辆管理等场景场景对于模型速度有着一定限制。 针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 @@ -598,10 +598,11 @@ python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OC Global.save_inference_dir=output/CCPD/rec_quant/infer ``` -### 4.3 串联推理 +### 4.3 部署 -检测模型和识别模型分别fine-tune并导出为inference模型之后,可以使用如下命令进行端到端推理并对结果进行可视化。 +- 基于 Paddle Inference 的python推理 +检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。 ```bash python tools/infer/predict_system.py \ @@ -614,9 +615,13 @@ python tools/infer/predict_system.py \ ![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) +- 端侧部署 + +端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md) + ### 4.4 计算End2End指标 -端到端指标可通过 [PaddleOCR内置脚本](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/tools/end2end/readme.md) 进行计算,具体步骤如下: +端到端指标可通过 [PaddleOCR内置脚本](../tools/end2end/readme.md) 进行计算,具体步骤如下: 1. 导出模型 From 8a6d61cb710f99d3254ee78f86c30478f479d965 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Fri, 20 May 2022 07:03:21 +0000 Subject: [PATCH 035/129] fix tipc v3 rec pact model path --- .../ch_PP-OCRv3_rec_PACT/train_infer_python.txt | 2 +- test_tipc/prepare.sh | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt index fd7d61c372..8d99024da4 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt @@ -34,7 +34,7 @@ distill_export:null export1:null export2:null inference_dir:Student -infer_model:./inference/ch_PP-OCRv3_rec_slim_quant_infer +infer_model:./inference/ch_PP-OCRv3_rec_slim_infer infer_export:null infer_quant:True inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index a5c5bd2d06..7bf71ecd70 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -49,7 +49,6 @@ if [ ${MODE} = "lite_train_lite_infer" ];then cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi if [[ ${model_name} =~ "PPOCRv3_det" ]];then - # TODO check model link wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -74,7 +73,6 @@ if [ ${MODE} = "lite_train_lite_infer" ];then cd ./pretrain_models/ && tar xf ch_PP-OCRv2_rec_train.tar && cd ../ fi if [ ${model_name} == "ch_PPOCRv3_rec" ] || [ ${model_name} == "ch_PPOCRv3_rec_PACT" ]; then - # TODO check model link wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_rec_train.tar && cd ../ fi @@ -122,7 +120,6 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi if [ ${model_name} == "ch_PPOCRv3_det" ]; then - # TODO check model link wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -151,7 +148,6 @@ elif [ ${MODE} = "lite_train_whole_infer" ];then cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi if [ ${model_name} == "ch_PPOCRv3_det" ]; then - # TODO check model link wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -205,7 +201,6 @@ elif [ ${MODE} = "whole_infer" ];then cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ fi if [[ ${model_name} =~ "ch_PPOCRv3_det" ]]; then - # TODO check model link eval_model_name="ch_PP-OCRv3_det_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ @@ -217,13 +212,14 @@ elif [ ${MODE} = "whole_infer" ];then cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv2_rec_slim_quant_infer.tar && cd ../ fi if [[ ${model_name} =~ "PPOCRv3_ocr_rec" ]]; then - # TODO check model link eval_model_name="ch_PP-OCRv3_rec_infer" - echo $(pwd) wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate - # wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_quant_infer.tar --no-check-certificate - cd ./inference && tar xf ${eval_model_name}.tar && cd ../ - # cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv3_rec_slim_quant_infer.tar && cd ../ + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar --no-check-certificate + cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv3_rec_slim_infer.tar && cd ../ + fi + if [[ ${model_name} == "ch_PPOCRv3_rec_PACT" ]]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_rec_slim_infer.tar && cd ../ fi if [ ${model_name} == "en_server_pgnetA" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/pgnet/en_server_pgnetA.tar --no-check-certificate From 885ec436c198a88ed9df2794c0f8da72f090fecf Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Fri, 20 May 2022 16:04:31 +0800 Subject: [PATCH 036/129] update doc --- applications/车牌识别.md | 49 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 6959bfae05..270d7cef76 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -17,8 +17,8 @@ - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) - [4.2.5 模型导出](#425-模型导出) - - [4.3 部署](#43-部署) - - [4.4 计算End2End指标](#44-计算End2End指标) + - [4.3 计算End2End指标](#43-计算End2End指标) + - [4.4 部署](#44-部署) - [4.5 实验总结](#45-实验总结) ## 1. 项目介绍 @@ -598,28 +598,7 @@ python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OC Global.save_inference_dir=output/CCPD/rec_quant/infer ``` -### 4.3 部署 - -- 基于 Paddle Inference 的python推理 - -检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。 - -```bash -python tools/infer/predict_system.py \ - --det_model_dir=output/CCPD/det/infer/ \ - --rec_model_dir=output/CCPD/rec/infer/ \ - --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ - --rec_image_shape=3,48,320 -``` -推理结果如下 - -![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) - -- 端侧部署 - -端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md) - -### 4.4 计算End2End指标 +### 4.3 计算End2End指标 端到端指标可通过 [PaddleOCR内置脚本](../tools/end2end/readme.md) 进行计算,具体步骤如下: @@ -762,6 +741,28 @@ fmeasure: 87.36% 从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行 fine-tune 后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 +### 4.4 部署 + +- 基于 Paddle Inference 的python推理 + +检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。 + +```bash +python tools/infer/predict_system.py \ + --det_model_dir=output/CCPD/det/infer/ \ + --rec_model_dir=output/CCPD/rec/infer/ \ + --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ + --rec_image_shape=3,48,320 +``` +推理结果如下 + +![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) + +- 端侧部署 + +端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md) + + ### 4.5 实验总结 我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune+量化3种方案的实验,并基于[PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: From 7f1011d36ddca3a02850edf65a05a6895a74c389 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Fri, 20 May 2022 16:07:28 +0800 Subject: [PATCH 037/129] update doc --- applications/{车牌识别.md => 轻量级车牌识别.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename applications/{车牌识别.md => 轻量级车牌识别.md} (100%) diff --git a/applications/车牌识别.md b/applications/轻量级车牌识别.md similarity index 100% rename from applications/车牌识别.md rename to applications/轻量级车牌识别.md From d9d0ec457647ac19da0c73b37a3bf0da3bb170ac Mon Sep 17 00:00:00 2001 From: zhoujun Date: Sat, 21 May 2022 13:07:11 +0800 Subject: [PATCH 038/129] =?UTF-8?q?Update=20=E8=BD=BB=E9=87=8F=E7=BA=A7?= =?UTF-8?q?=E8=BD=A6=E7=89=8C=E8=AF=86=E5=88=AB.md=20(#6363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/轻量级车牌识别.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 270d7cef76..afa188c4c7 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -782,7 +782,7 @@ python tools/infer/predict_system.py \ |PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms | |PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms | |PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4,2ms | -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M | 1.8ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms | - 端到端指标如下: From 1e836600bb34c29e8e461c969daf907de5df2502 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 23 May 2022 03:41:03 +0000 Subject: [PATCH 039/129] update cpp infer for onnxruntime --- deploy/cpp_infer/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy/cpp_infer/CMakeLists.txt b/deploy/cpp_infer/CMakeLists.txt index 6d3ecb6ac2..7deacfadc5 100644 --- a/deploy/cpp_infer/CMakeLists.txt +++ b/deploy/cpp_infer/CMakeLists.txt @@ -92,6 +92,8 @@ include_directories("${PADDLE_LIB}/third_party/install/glog/include") include_directories("${PADDLE_LIB}/third_party/install/gflags/include") include_directories("${PADDLE_LIB}/third_party/install/xxhash/include") include_directories("${PADDLE_LIB}/third_party/install/zlib/include") +include_directories("${PADDLE_LIB}/third_party/install/onnxruntime/include") +include_directories("${PADDLE_LIB}/third_party/install/paddle2onnx/include") include_directories("${PADDLE_LIB}/third_party/boost") include_directories("${PADDLE_LIB}/third_party/eigen3") @@ -110,6 +112,8 @@ link_directories("${PADDLE_LIB}/third_party/install/protobuf/lib") link_directories("${PADDLE_LIB}/third_party/install/glog/lib") link_directories("${PADDLE_LIB}/third_party/install/gflags/lib") link_directories("${PADDLE_LIB}/third_party/install/xxhash/lib") +link_directories("${PADDLE_LIB}/third_party/install/onnxruntime/lib") +link_directories("${PADDLE_LIB}/third_party/install/paddle2onnx/lib") link_directories("${PADDLE_LIB}/paddle/lib") From f2c0a1a2fdbcbbbd7a56d9d7647b590661f7d72e Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Mon, 23 May 2022 23:38:33 +0800 Subject: [PATCH 040/129] Cherry pick to dygraph (#6383) * add starnet doc & test=document_fix * add starnet doc & test=document_fix * Update algorithm_rec_starnet.md * support xpu --- doc/doc_en/algorithm_rec_starnet.md | 139 ++++++++++++++++++++++++++++ tools/infer/utility.py | 3 + tools/program.py | 29 +++--- 3 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 doc/doc_en/algorithm_rec_starnet.md diff --git a/doc/doc_en/algorithm_rec_starnet.md b/doc/doc_en/algorithm_rec_starnet.md new file mode 100644 index 0000000000..dbb53a9c73 --- /dev/null +++ b/doc/doc_en/algorithm_rec_starnet.md @@ -0,0 +1,139 @@ +# STAR-Net + +- [1. Introduction](#1) +- [2. Environment](#2) +- [3. Model Training / Evaluation / Prediction](#3) + - [3.1 Training](#3-1) + - [3.2 Evaluation](#3-2) + - [3.3 Prediction](#3-3) +- [4. Inference and Deployment](#4) + - [4.1 Python Inference](#4-1) + - [4.2 C++ Inference](#4-2) + - [4.3 Serving](#4-3) + - [4.4 More](#4-4) +- [5. FAQ](#5) + + +## 1. Introduction + +Paper information: +> [STAR-Net: a spatial attention residue network for scene text recognition.](http://www.bmva.org/bmvc/2016/papers/paper043/paper043.pdf) +> Wei Liu, Chaofeng Chen, Kwan-Yee K. Wong, Zhizhong Su and Junyu Han. +> BMVC, pages 43.1-43.13, 2016 + +Refer to [DTRB](https://arxiv.org/abs/1904.01906) text Recognition Training and Evaluation Process . Using MJSynth and SynthText two text recognition datasets for training, and evaluating on IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE datasets, the algorithm reproduction effect is as follows: + +|Models|Backbone Networks|Avg Accuracy|Configuration Files|Download Links| +| --- | --- | --- | --- | --- | +|StarNet|Resnet34_vd|84.44%|[configs/rec/rec_r34_vd_tps_bilstm_ctc.yml](../../configs/rec/rec_r34_vd_tps_bilstm_ctc.yml)|[trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r34_vd_tps_bilstm_ctc_v2.0_train.tar)| +|StarNet|MobileNetV3|81.42%|[configs/rec/rec_mv3_tps_bilstm_ctc.yml](../../configs/rec/rec_mv3_tps_bilstm_ctc.yml)|[ trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mv3_tps_bilstm_ctc_v2.0_train.tar)| + + + +## 2. Environment +Please refer to [Operating Environment Preparation](./environment_en.md) to configure the PaddleOCR operating environment, and refer to [Project Clone](./clone_en.md) to clone the project code. + + +## 3. Model Training / Evaluation / Prediction + +Please refer to [Text Recognition Training Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. Take the backbone network based on Resnet34_vd as an example: + + +### 3.1 Training +After the data preparation is complete, the training can be started. The training command is as follows: + +```` +#Single card training (long training period, not recommended) +python3 tools/train.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml #Multi-card training, specify the card number through the --gpus parameter +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c rec_r34_vd_tps_bilstm_ctc.yml + ```` + + +### 3.2 Evaluation + +```` +# GPU evaluation, Global.pretrained_model is the model to be evaluated +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o Global.pretrained_model={path/to/weights}/best_accuracy + ```` + + +### 3.3 Prediction + +```` +# The configuration file used for prediction must match the training +python3 tools/infer_rec.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o Global.pretrained_model={path/to/weights}/best_accuracy Global.infer_img=doc/imgs_words/en/word_1.png + ```` + + +## 4. Inference + + +### 4.1 Python Inference +First, convert the model saved during the STAR-Net text recognition training process into an inference model. Take the model trained on the MJSynth and SynthText text recognition datasets based on the Resnet34_vd backbone network as an example [Model download address]( https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r34_vd_none_bilstm_ctc_v2.0_train.tar) , which can be converted using the following command: + +```shell +python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o Global.pretrained_model=./rec_r34_vd_tps_bilstm_ctc_v2.0_train/best_accuracy Global.save_inference_dir=./inference/rec_starnet + ```` + +STAR-Net text recognition model inference, you can execute the following commands: + +```shell +python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rec_starnet/" --rec_image_shape="3, 32, 100" --rec_char_dict_path="./ppocr/utils/ic15_dict.txt" + ```` + +![](../imgs_words_en/word_336.png) + +The inference results are as follows: + + +```bash +Predicts of ./doc/imgs_words_en/word_336.png:('super', 0.9999073) +``` + +**Attention** Since the above model refers to the [DTRB](https://arxiv.org/abs/1904.01906) text recognition training and evaluation process, it is different from the ultra-lightweight Chinese recognition model training in two aspects: + +- The image resolutions used during training are different. The image resolutions used for training the above models are [3, 32, 100], while for Chinese model training, in order to ensure the recognition effect of long texts, the image resolutions used during training are [ 3, 32, 320]. The default shape parameter of the predictive inference program is the image resolution used for training Chinese, i.e. [3, 32, 320]. Therefore, when inferring the above English model here, it is necessary to set the shape of the recognized image through the parameter rec_image_shape. + +- Character list, the experiment in the DTRB paper is only for 26 lowercase English letters and 10 numbers, a total of 36 characters. All uppercase and lowercase characters are converted to lowercase characters, and characters not listed above are ignored and considered spaces. Therefore, there is no input character dictionary here, but a dictionary is generated by the following command. Therefore, the parameter rec_char_dict_path needs to be set during inference, which is specified as an English dictionary "./ppocr/utils/ic15_dict.txt". + +``` +self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz" +dict_character = list(self.character_str) + + + ``` + + +### 4.2 C++ Inference + +After preparing the inference model, refer to the [cpp infer](../../deploy/cpp_infer/) tutorial to operate. + + +### 4.3 Serving + +After preparing the inference model, refer to the [pdserving](../../deploy/pdserving/) tutorial for Serving deployment, including two modes: Python Serving and C++ Serving. + + +### 4.4 More + +The STAR-Net model also supports the following inference deployment methods: + +- Paddle2ONNX Inference: After preparing the inference model, refer to the [paddle2onnx](../../deploy/paddle2onnx/) tutorial. + + +## 5. FAQ + +## Quote + +```bibtex +@inproceedings{liu2016star, + title={STAR-Net: a spatial attention residue network for scene text recognition.}, + author={Liu, Wei and Chen, Chaofeng and Wong, Kwan-Yee K and Su, Zhizhong and Han, Junyu}, + booktitle={BMVC}, + volume={2}, + pages={7}, + year={2016} +} +``` + + diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 48b16db4a0..3987d64571 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -34,6 +34,7 @@ def init_args(): parser = argparse.ArgumentParser() # params for prediction engine parser.add_argument("--use_gpu", type=str2bool, default=True) + parser.add_argument("--use_xpu", type=str2bool, default=False) parser.add_argument("--ir_optim", type=str2bool, default=True) parser.add_argument("--use_tensorrt", type=str2bool, default=False) parser.add_argument("--min_subgraph_size", type=int, default=15) @@ -286,6 +287,8 @@ def create_predictor(args, mode, logger): config.set_trt_dynamic_shape_info( min_input_shape, max_input_shape, opt_input_shape) + elif args.use_xpu: + config.enable_xpu(10 * 1024 * 1024) else: config.disable_gpu() if hasattr(args, "cpu_threads"): diff --git a/tools/program.py b/tools/program.py index 7c02dc0149..aa0d2698cf 100755 --- a/tools/program.py +++ b/tools/program.py @@ -112,20 +112,25 @@ def merge_config(config, opts): return config -def check_gpu(use_gpu): +def check_device(use_gpu, use_xpu=False): """ Log error and exit when set use_gpu=true in paddlepaddle cpu version. """ - err = "Config use_gpu cannot be set as true while you are " \ - "using paddlepaddle cpu version ! \nPlease try: \n" \ - "\t1. Install paddlepaddle-gpu to run model on GPU \n" \ - "\t2. Set use_gpu as false in config file to run " \ + err = "Config {} cannot be set as true while your paddle " \ + "is not compiled with {} ! \nPlease try: \n" \ + "\t1. Install paddlepaddle to run model on {} \n" \ + "\t2. Set {} as false in config file to run " \ "model on CPU" try: + if use_gpu and use_xpu: + print("use_xpu and use_gpu can not both be ture.") if use_gpu and not paddle.is_compiled_with_cuda(): - print(err) + print(err.format("use_gpu", "cuda", "gpu", "use_gpu")) + sys.exit(1) + if use_xpu and not paddle.device.is_compiled_with_xpu(): + print(err.format("use_xpu", "xpu", "xpu", "use_xpu")) sys.exit(1) except Exception as e: pass @@ -547,7 +552,7 @@ def preprocess(is_train=False): # check if set use_gpu=True in paddlepaddle cpu version use_gpu = config['Global']['use_gpu'] - check_gpu(use_gpu) + use_xpu = config['Global'].get('use_xpu', False) # check if set use_xpu=True in paddlepaddle cpu/gpu version use_xpu = False @@ -562,11 +567,13 @@ def preprocess(is_train=False): 'SEED', 'SDMGR', 'LayoutXLM', 'LayoutLM', 'PREN', 'FCE', 'SVTR' ] - device = 'cpu' - if use_gpu: - device = 'gpu:{}'.format(dist.ParallelEnv().dev_id) if use_xpu: - device = 'xpu' + device = 'xpu:{0}'.format(os.getenv('FLAGS_selected_xpus', 0)) + else: + device = 'gpu:{}'.format(dist.ParallelEnv() + .dev_id) if use_gpu else 'cpu' + check_device(use_gpu, use_xpu) + device = paddle.set_device(device) config['Global']['distributed'] = dist.get_world_size() != 1 From 96eb6287f77960f0a91a9e71bebe037638e485c4 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Tue, 24 May 2022 15:34:24 +0800 Subject: [PATCH 041/129] fix trt int8 inference (#6387) --- tools/infer/utility.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 3987d64571..366212f228 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -202,7 +202,8 @@ def create_predictor(args, mode, logger): workspace_size=1 << 30, precision_mode=precision, max_batch_size=args.max_batch_size, - min_subgraph_size=args.min_subgraph_size) + min_subgraph_size=args.min_subgraph_size, + use_calib_mode=False) # skip the minmum trt subgraph use_dynamic_shape = True if mode == "det": From c0e2a822ef9c84b35cab83935b6ac214adafe56a Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Tue, 24 May 2022 18:17:33 +0800 Subject: [PATCH 042/129] update doc --- applications/轻量级车牌识别.md | 110 +++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 41 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 270d7cef76..9ccd1a270d 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -25,14 +25,15 @@ 车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。 -本项目难点如下: -1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 -2. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 -3. 边缘和端测场景应用对模型大小有限制,推理速度有要求 +结合我国国情,目前车牌识别技术的难点有: +1. 车牌样式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 +2. 车牌位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; +3. 图像质量差: 运动模糊,由于强光,反射或阴影造成的光照和对比度较差, 车牌(部分)遮挡; +4. 在车辆管理等场景场景对于模型速度有着一定限制。 -针对以上问题, 本例选用 [PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 +针对以上问题, 本例选用 [PP-OCRv3](https://github.com/WenmuZhou/PaddleOCR/blob/flk/doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) @@ -82,31 +83,32 @@ unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip ### 3.1 数据集标注规则 -CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD +CPPD的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD 具体规则如下: 例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg -由分隔符'-'分为几个部分: +每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。 -- 025:车牌区域与整个图片区域的面积比。 +- 025:车牌面积与整个图片区域的面积比。025 (25%) -- 95_113: 车牌水平倾斜度和垂直倾斜度, 水平95°, 竖直113° +- 95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度 -- 154&383_386&473: 车牌边界框坐标:左上(154, 383), 右下(386, 473) +- 154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473) -- 386&473_177&454_154&383_363&402: 车牌四个角点坐标, 坐标顺序为[右下,左下,左上,右上] +- 386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402) -- 0_0_22_27_27_33_16: 车牌号码,CCPD中的每个图像只有一个LP。每个LP编号由一个汉字、一个字母和五个字母或数字组成。有效的中国车牌由七个字符组成:省(1个字符)、字母(1个字符)、字母+数字(5个字符)。“0_0_22_27_27_33_16”是每个字符的索引。这三个数组的定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们使用O作为“无字符”的标志,因为中国车牌字符中没有O。 +- 0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S + +- 37:牌照区域的亮度。 37 (37%) + +- 15:车牌区域的模糊度。15 (15%) ```python provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"] -alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', 'O'] -ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O'] - +alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', 'O'] +ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O'] ``` ### 3.2 制作符合PP-OCR训练格式的标注文件 @@ -653,16 +655,13 @@ python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OC ```bash # PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 -python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=output/ch_PP-OCRv3_rec_train/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain - -# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` -python3 tools/infer/predict_system.py --det_model_dir=output/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=output/ch_PP-OCRv3_rec_train/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/post +python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true # PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune -python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune +python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true # PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估 -python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant +python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true ``` 3. 转换label并计算指标 @@ -677,6 +676,7 @@ python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pret python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain # PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估 +# 需手动修改后处理函数 python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post python3 tools/end2end/eval_end2end.py end2end/gt end2end/post @@ -732,14 +732,41 @@ fmeasure: 87.36% 各个方案端到端指标如下: -|det|rec|fmeasure| -|---|---|---| -|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型|0.04%| -|PP-OCRv3中英文超轻量检测预训练模型|PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·`|76.84%| -|PP-OCRv3中英文超轻量检测预训练模型+fine-tune|PP-OCRv3中英文超轻量识别预训练模型+fine-tune|86.55%| -|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化|PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|87.36%| +|模型| 指标 | +|---|--------| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型| 0.04% | +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的`·`| 78.27% | +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune| 87.14% | +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化| 88% | -从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行 fine-tune 后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%。 +从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。 + +在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision + +为了快速评估,我们在 ` tools/end2end/convert_ppocr_label.py` 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤 +```python +if len(txt) != 8: # 车牌字符串长度为8 + continue +``` + +此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下: + +![](https://ai-studio-static-online.cdn.bcebos.com/59ab0411c8eb4dfd917fb2b6e5b69a17ee7ca48351444aec9ac6104b79ff1028) + +修改前后个方案指标对比如下: + + +各个方案端到端指标如下: + +|模型|base|A:识别结果过滤|B:use_dilation|C:flip_box|best| +|---|---|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型|0.04%|0.08%|0.02%|0.05%|0.00%(A)| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的`·`|78.27%|90.84%|78.61%|79.43%|91.66%(A+B+C)| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune|87.14%|90.40%|87.66%|89.98|92.5%(A+B+C)| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|88%|90.54%|88.5%|89.46%|92.02%(A+B+C)| + + +从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。 ### 4.4 部署 @@ -765,7 +792,7 @@ python tools/infer/predict_system.py \ ### 4.5 实验总结 -我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune+量化3种方案的实验,并基于[PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: +我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于[PaddleOCR lite教程](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: - 检测 @@ -773,7 +800,7 @@ python tools/infer/predict_system.py \ |---|---|------|------------| |PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| 233ms | |PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 233ms | -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化|98.91%| 1M | 189ms |fine-tune - 识别 @@ -782,22 +809,23 @@ python tools/infer/predict_system.py \ |PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms | |PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms | |PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4,2ms | -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M | 1.8ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms | - 端到端指标如下: -| det | rec |fmeasure|模型大小|预测速度(lite) | -|-----------------------------------|------------------------------------|---|---|---| -| PP-OCRv3中英文超轻量检测预训练模型 | PP-OCRv3中英文超轻量识别预训练模型 |0.04%|12.8M|298ms| -| PP-OCRv3中英文超轻量检测预训练模型 | PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` |76.84%|12.8M|298ms| -| PP-OCRv3中英文超轻量检测预训练模型+fine-tune | PP-OCRv3中英文超轻量识别预训练模型+fine-tune |86.55%|12.8M|298ms| -| PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化 | PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化 |87.36%|5.8M|224ms| +|方案|fmeasure|模型大小|预测速度(lite) | +|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型|0.08%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的`·`|91.66%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune|92.5%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|92.02%|5.8M|224ms| -*结论* + +**结论** PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 -从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到76.84%,在CCPD数据集上进行 fine-tune 后指标进一步提升到86.55%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到87.36%并且模型大小降低54%。 +从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。 From 7045ab34f5f19db2afbcb377d36e548b5b465bfc Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 25 May 2022 14:38:33 +0800 Subject: [PATCH 043/129] update doc --- applications/轻量级车牌识别.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 9ccd1a270d..f57451ce0b 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -25,15 +25,14 @@ 车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。 +本项目难点如下: -结合我国国情,目前车牌识别技术的难点有: +车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 +车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 +边缘和端测场景应用对模型大小有限制,推理速度有要求 +针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 -1. 车牌样式多。我国车牌颜色大致有四种:黄底黑字、蓝底白字、白底黑字、黑底白字;车牌格式包括民用车牌、武警车牌、军车车牌、外交车牌、特种车牌、消防车牌等等。 -2. 车牌位置不固定。由于不同汽车品牌公司出产的汽车型号和外形各有不同,每辆车的车牌悬挂位置也不一样; -3. 图像质量差: 运动模糊,由于强光,反射或阴影造成的光照和对比度较差, 车牌(部分)遮挡; -4. 在车辆管理等场景场景对于模型速度有着一定限制。 -针对以上问题, 本例选用 [PP-OCRv3](https://github.com/WenmuZhou/PaddleOCR/blob/flk/doc/doc_ch/PP-OCRv3_introduction.md) 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和中得到广泛应用。 aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) @@ -83,7 +82,7 @@ unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip ### 3.1 数据集标注规则 -CPPD的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD +CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD 具体规则如下: From 27b8a5621fb847c14302dc7d943c70a06dc18f4f Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 25 May 2022 14:40:00 +0800 Subject: [PATCH 044/129] update doc --- applications/轻量级车牌识别.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index f57451ce0b..31b1b427db 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -27,9 +27,10 @@ 本项目难点如下: -车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 -车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 -边缘和端测场景应用对模型大小有限制,推理速度有要求 +1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 +2. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 +3. 边缘和端测场景应用对模型大小有限制,推理速度有要求 + 针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 From 81bd4104e0a497bebe48e29f443242bd99f4361d Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 26 May 2022 12:09:48 +0000 Subject: [PATCH 045/129] update train infer python for tipc --- .../ch_PP-OCRv2_det/train_infer_python.txt | 10 +- .../train_infer_python.txt | 10 +- .../ch_PP-OCRv2_rec/train_infer_python.txt | 10 +- .../train_infer_python.txt | 10 +- .../ch_PP-OCRv3_det/train_infer_python.txt | 10 +- .../train_infer_python.txt | 10 +- .../ch_PP-OCRv3_rec/train_infer_python.txt | 10 +- .../train_infer_python.txt | 10 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 8 +- .../train_infer_python.txt | 6 +- .../det_mv3_db_v2_0/train_infer_python.txt | 6 +- .../det_mv3_east_v2.0/train_infer_python.txt | 4 +- .../det_mv3_pse_v2.0/train_infer_python.txt | 4 +- .../det_r18_vd_db_v2_0/train_infer_python.txt | 6 +- .../det_r50_db_v2.0/train_infer_python.txt | 6 +- .../train_infer_python.txt | 4 +- .../train_infer_python.txt | 4 +- .../train_infer_python.txt | 4 +- .../train_infer_python.txt | 4 +- .../en_server_pgnetA/train_infer_python.txt | 4 +- .../rec_mtb_nrtr/train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../rec_r31_sar/train_infer_python.txt | 8 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- .../train_infer_python.txt | 6 +- test_tipc/prepare.sh | 145 ++++++++++++------ test_tipc/test_train_inference_python.sh | 6 +- 39 files changed, 228 insertions(+), 179 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt index 797cf53a1d..0a4de9790b 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_det +model_name:ch_PP-OCRv2_det python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt index 038fa85061..c43ed862c1 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_det_PACT +model_name:ch_PP-OCRv2_det_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=1|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt index 188eb3ccc5..b3049212ae 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:PPOCRv2_ocr_rec +model_name:ch_PP-OCRv2_rec python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt index 98c125229d..f6c50bcefc 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_rec_PACT +model_name:ch_PP-OCRv2_rec_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:pretrain_models/ch_PP-OCRv2_rec_train/best_accuracy @@ -39,10 +39,10 @@ infer_export:null infer_quant:True inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt index 93f673289a..e81450464a 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_det +model_name:ch_PP-OCRv3_det python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt index f1ea7de5e5..626e05a37b 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_det_PACT +model_name:ch_PP-OCRv3_det_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=1|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt index c333c08330..5e607b1709 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:PPOCRv3_ocr_rec +model_name:ch_PP-OCRv3_rec python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt index 8d99024da4..4b63b65ae8 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_rec_PACT +model_name:ch_PP-OCRv3_rec_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy @@ -39,10 +39,10 @@ infer_export:null infer_quant:True inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt index 269693a86e..e2a0a1b1ff 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=100|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=100|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2 infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt index 47ccf2e69e..ec811bd509 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt index 9d2855d824..d042d2a285 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=20|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=20|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt index 5086f80d7b..9442b352a7 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/rec/rec_icdar15_train.yml -o infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt index 77494ac347..6ed6556cf9 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt index 94909ec340..ec62059a11 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.checkpoints:null @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt index 52489fe529..e8244661ca 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_lite_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_res18_db_ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt index 78a046c503..de6164ebe2 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt b/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt index fab8f50d54..19010e859e 100644 --- a/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt b/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt index 5634297973..ec23c852ea 100644 --- a/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_mv3_east_v2.0/det_mv infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|fp16|int8 diff --git a/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt b/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt index 661adc4a32..7563dcac22 100644 --- a/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_mv3_pse_v2.0/det_mv3 infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|fp16 diff --git a/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt b/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt index 77023ef2c1..df09cf0b10 100644 --- a/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt index 3fd875711e..d55621dc76 100644 --- a/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/det/det_r50_vd_db.yml -o infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt index c1748c5d2f..0d0f331777 100644 --- a/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_r50_vd_east_v2_0/det infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|fp16|int8 diff --git a/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt index 55ebcd3547..b4bf40f2b0 100644 --- a/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_r50_vd_pse_v2_0/det_ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|fp16|int8 diff --git a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt index 16f37ace6f..e7d75d802b 100644 --- a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_r50_vd_sast_icdar15_ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|int8 diff --git a/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt index 5e4c5666b7..17a87a1941 100644 --- a/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c test_tipc/configs/det_r50_vd_sast_totaltex infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|int8 diff --git a/test_tipc/configs/en_server_pgnetA/train_infer_python.txt b/test_tipc/configs/en_server_pgnetA/train_infer_python.txt index 8a1509baab..593ea00f1c 100644 --- a/test_tipc/configs/en_server_pgnetA/train_infer_python.txt +++ b/test_tipc/configs/en_server_pgnetA/train_infer_python.txt @@ -39,8 +39,8 @@ infer_export:tools/export_model.py -c configs/e2e/e2e_r50_vd_pg.yml -o infer_quant:False inference:tools/infer/predict_e2e.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32|fp16|int8 diff --git a/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt b/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt index de6de5a0ca..8bfbc7142b 100644 --- a/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt +++ b/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrt infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/EN_symbol_dict.txt --rec_image_shape="1,32,100" --rec_algorithm="NRTR" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt index e67dd15090..9f308988a7 100644 --- a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_mv3_none_bilstm_ctc_ infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt index aa3e88d284..e0c06f1e4d 100644 --- a/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_mv3_none_none_ctc_v2 infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt index c22767c60f..da599e62f8 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_mv3_tps_bilstm_att_v infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --rec_algorithm="RARE" --min_subgraph_size=5 --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt index 7a3096eb1e..7e6d4ad077 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_mv3_tps_bilstm_ctc_v infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --rec_algorithm="StarNet" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r31_sar/train_infer_python.txt b/test_tipc/configs/rec_r31_sar/train_infer_python.txt index 1a32a3d507..9475814129 100644 --- a/test_tipc/configs/rec_r31_sar/train_infer_python.txt +++ b/test_tipc/configs/rec_r31_sar/train_infer_python.txt @@ -38,11 +38,11 @@ train_model:./inference/rec_r31_sar_train/best_accuracy infer_export:tools/export_model.py -c test_tipc/configs/rec_r31_sar/rec_r31_sar.yml -o infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/dict90.txt --rec_image_shape="3,48,48,160" --rec_algorithm="SAR" ---use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--use_gpu:True +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt index 02cea56fbe..e85758ad70 100644 --- a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_r34_vd_none_bilstm_c infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt index 5e7c1d3431..0b8066ed74 100644 --- a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_r34_vd_none_none_ctc infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt index 55e937881b..970bf63261 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_r34_vd_tps_bilstm_at infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --rec_algorithm="RARE" --min_subgraph_size=5 --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt index 5b5ba0fd01..4dfcc0ab9c 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_r34_vd_tps_bilstm_ct infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,100" --rec_algorithm="StarNet" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt b/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt index 4877512b68..98eaca84af 100644 --- a/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt +++ b/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c test_tipc/configs/rec_r50_fpn_vd_none_srn/ infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="1,64,256" --rec_algorithm="SRN" --use_space_char=False --min_subgraph_size=3 --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False +--use_tensorrt:False --precision:fp32|int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 7bf71ecd70..501e597b16 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -44,11 +44,11 @@ if [ ${MODE} = "lite_train_lite_infer" ];then # pretrain lite train data wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams --no-check-certificate wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_db_v2.0_train.tar --no-check-certificate - if [[ ${model_name} =~ "PPOCRv2_det" ]];then + if [[ ${model_name} =~ "ch_PP-OCRv2_det" ]];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi - if [[ ${model_name} =~ "PPOCRv3_det" ]];then + if [[ ${model_name} =~ "ch_PP-OCRv3_det" ]];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -64,15 +64,15 @@ if [ ${MODE} = "lite_train_lite_infer" ];then ln -s ./icdar2015_lite ./icdar2015 cd ../ cd ./inference && tar xf rec_inference.tar && cd ../ - if [ ${model_name} == "ch_PPOCRv2_det" ] || [ ${model_name} == "ch_PPOCRv2_det_PACT" ]; then + if [ ${model_name} == "ch_PP-OCRv2_det" ] || [ ${model_name} == "ch_PP-OCRv2_det_PACT" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_ppocr_server_v2.0_det_train.tar && cd ../ fi - if [ ${model_name} == "ch_PPOCRv2_rec" ] || [ ${model_name} == "ch_PPOCRv2_rec_PACT" ]; then + if [ ${model_name} == "ch_PP-OCRv2_rec" ] || [ ${model_name} == "ch_PP-OCRv2_rec_PACT" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_rec_train.tar && cd ../ fi - if [ ${model_name} == "ch_PPOCRv3_rec" ] || [ ${model_name} == "ch_PPOCRv3_rec_PACT" ]; then + if [ ${model_name} == "ch_PP-OCRv3_rec" ] || [ ${model_name} == "ch_PP-OCRv3_rec_PACT" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_rec_train.tar && cd ../ fi @@ -115,11 +115,11 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate cd ./train_data/ && tar xf icdar2015.tar && tar xf ic15_data.tar && cd ../ - if [ ${model_name} == "ch_PPOCRv2_det" ]; then + if [ ${model_name} == "ch_PP-OCRv2_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi - if [ ${model_name} == "ch_PPOCRv3_det" ]; then + if [ ${model_name} == "ch_PP-OCRv3_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -143,11 +143,11 @@ elif [ ${MODE} = "lite_train_whole_infer" ];then cd ./train_data/ && tar xf icdar2015_infer.tar && tar xf ic15_data.tar ln -s ./icdar2015_infer ./icdar2015 cd ../ - if [ ${model_name} == "ch_PPOCRv2_det" ]; then + if [ ${model_name} == "ch_PP-OCRv2_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ fi - if [ ${model_name} == "ch_PPOCRv3_det" ]; then + if [ ${model_name} == "ch_PP-OCRv3_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi @@ -195,29 +195,29 @@ elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi - if [[ ${model_name} =~ "ch_PPOCRv2_det" ]]; then + if [[ ${model_name} =~ "ch_PP-OCRv2_det" ]]; then eval_model_name="ch_PP-OCRv2_det_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ fi - if [[ ${model_name} =~ "ch_PPOCRv3_det" ]]; then + if [[ ${model_name} =~ "ch_PP-OCRv3_det" ]]; then eval_model_name="ch_PP-OCRv3_det_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ fi - if [[ ${model_name} =~ "PPOCRv2_ocr_rec" ]]; then + if [[ ${model_name} =~ "ch_PP-OCRv2_rec" ]]; then eval_model_name="ch_PP-OCRv2_rec_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv2_rec_slim_quant_infer.tar && cd ../ fi - if [[ ${model_name} =~ "PPOCRv3_ocr_rec" ]]; then + if [[ ${model_name} =~ "ch_PP-OCRv3_rec" ]]; then eval_model_name="ch_PP-OCRv3_rec_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar --no-check-certificate cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_PP-OCRv3_rec_slim_infer.tar && cd ../ fi - if [[ ${model_name} == "ch_PPOCRv3_rec_PACT" ]]; then + if [[ ${model_name} == "ch_PP-OCRv3_rec_PACT" ]]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_slim_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_rec_slim_infer.tar && cd ../ fi @@ -320,14 +320,14 @@ if [ ${MODE} = "klquant_whole_infer" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi - if [ ${model_name} = "PPOCRv2_ocr_rec_kl" ]; then + if [ ${model_name} = "ch_PP-OCRv2_rec_KL" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate cd ./train_data/ && tar xf ic15_data.tar && cd ../ cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv2_rec_infer.tar && cd ../ fi - if [ ${model_name} = "PPOCRv3_ocr_rec_kl" ]; then + if [ ${model_name} = "ch_PP-OCRv3_rec_KL" ]; then # TODO check model link wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate @@ -335,12 +335,12 @@ if [ ${MODE} = "klquant_whole_infer" ]; then cd ./train_data/ && tar xf ic15_data.tar && cd ../ cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ fi - if [ ${model_name} = "PPOCRv2_ocr_det_kl" ]; then + if [ ${model_name} = "ch_PP-OCRv2_det_KL" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi - if [ ${model_name} = "PPOCRv3_ocr_det_kl" ]; then + if [ ${model_name} = "ch_PP-OCRv3_det_KL" ]; then # TODO check model link wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate @@ -356,28 +356,54 @@ if [ ${MODE} = "klquant_whole_infer" ]; then fi if [ ${MODE} = "cpp_infer" ];then - if [ ${model_name} = "ocr_det" ]; then + if [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_det_v3" ]; then - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate - cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_rec_v3" ]; then - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate - cd ./inference && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ elif [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf rec_inference.tar && cd ../ - elif [ ${model_name} = "ocr_system" ]; then + elif [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_det" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_rec" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_det" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_rec" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_mobile_v2.0" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_system_v3" ]; then + elif [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_PP-OCRv2_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate @@ -391,18 +417,30 @@ if [ ${MODE} = "serving_infer" ];then IFS='|' array=(${python_name_list}) python_name=${array[0]} - ${python_name} -m pip install paddle-serving-server-gpu==0.8.3.post101 - ${python_name} -m pip install paddle_serving_client==0.8.3 - ${python_name} -m pip install paddle-serving-app==0.8.3 - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar + # ${python_name} -m pip install paddle-serving-server-gpu==0.8.3.post101 + # ${python_name} -m pip install paddle_serving_client==0.8.3 + # ${python_name} -m pip install paddle-serving-app==0.8.3 + # wget model + if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_ppocr_server_v2.0" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_PP-OCRv2" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_PP-OCRv2_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_PP-OCRv3" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ + fi + # wget data wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate - cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ - cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_det_infer.tar && cd ../ + cd ./inference && tar xf rec_inference.tar && cd ../ fi if [ ${MODE} = "paddle2onnx_infer" ];then @@ -411,16 +449,27 @@ if [ ${MODE} = "paddle2onnx_infer" ];then ${python_name} -m pip install paddle2onnx ${python_name} -m pip install onnxruntime==1.4.0 # wget model - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar - cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ + if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_ppocr_server_v2.0" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_PP-OCRv2" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_PP-OCRv2_rec_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_PP-OCRv3" ]]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ + fi + # wget data wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar - cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && tar xf rec_inference.tar && cd ../ + cd ./inference && tar xf ch_det_data_50.tar && tar xf rec_inference.tar && cd ../ fi diff --git a/test_tipc/test_train_inference_python.sh b/test_tipc/test_train_inference_python.sh index 81d1bf8eef..82a373cf7b 100644 --- a/test_tipc/test_train_inference_python.sh +++ b/test_tipc/test_train_inference_python.sh @@ -142,9 +142,9 @@ function func_inference(){ for use_gpu in ${use_gpu_list[*]}; do if [ ${use_gpu} = "False" ] || [ ${use_gpu} = "cpu" ]; then for use_mkldnn in ${use_mkldnn_list[*]}; do - if [ ${use_mkldnn} = "False" ] && [ ${_flag_quant} = "True" ]; then - continue - fi + # if [ ${use_mkldnn} = "False" ] && [ ${_flag_quant} = "True" ]; then + # continue + # fi for threads in ${cpu_threads_list[*]}; do for batch_size in ${batch_size_list[*]}; do for precision in ${precision_list[*]}; do From 138371fb8b674d6dba294d1b57087e022ad9557d Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 26 May 2022 12:24:20 +0000 Subject: [PATCH 046/129] add cpp infer for tipc --- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 8 ++++---- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 8 ++++---- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 8 ++++---- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 8 ++++---- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 +++++++++++++++++++ test_tipc/test_inference_cpp.sh | 15 +++++++++++++- 13 files changed, 190 insertions(+), 17 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..ff271b94af --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2 +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_PP-OCRv2_rec_infer/ +--benchmark:True +--det:True +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..7bf584776f --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_det +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..3f8b4442c9 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_rec +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index da17069a96..ec82f320cf 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,14 +1,14 @@ ===========================cpp_infer_params=========================== -model_name:ocr_system_v3 +model_name:ch_PP-OCRv3 use_opencv:True infer_model:./inference/ch_PP-OCRv3_det_infer/ infer_quant:False inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index c7a37ddd59..bd69098560 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,14 +1,14 @@ ===========================cpp_infer_params=========================== -model_name:ocr_det_v3 +model_name:ch_PP-OCRv3_det use_opencv:True infer_model:./inference/ch_PP-OCRv3_det_infer/ infer_quant:False inference:./deploy/cpp_infer/build/ppocr --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 46b1c96c92..089f38d7a3 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,14 +1,14 @@ ===========================cpp_infer_params=========================== -model_name:ocr_rec_v3 +model_name:ch_PP-OCRv3_rec use_opencv:True infer_model:./inference/ch_PP-OCRv3_rec_infer/ infer_quant:False inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:6 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16 --rec_model_dir: --image_dir:./inference/rec_inference/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..1cb9c0c3d4 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0 +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--benchmark:True +--det:True +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index d0ae17ccb5..5d3d8615ae 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -1,14 +1,14 @@ ===========================cpp_infer_params=========================== -model_name:ocr_det +model_name:ch_ppocr_mobile_v2.0_det use_opencv:True infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ infer_quant:False inference:./deploy/cpp_infer/build/ppocr --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..c9ff73f007 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..ac23b804b7 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_server_v2.0 +use_opencv:True +infer_model:./inference/ch_ppocr_server_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +--benchmark:True +--det:True +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..75f5a4e93a --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_server_v2.0_det +use_opencv:True +infer_model:./inference/ch_ppocr_server_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..b102f5aecd --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_server_v2.0_rec +use_opencv:True +infer_model:./inference/ch_ppocr_server_v2.0_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/test_inference_cpp.sh b/test_tipc/test_inference_cpp.sh index 2bef621d98..92429c65da 100644 --- a/test_tipc/test_inference_cpp.sh +++ b/test_tipc/test_inference_cpp.sh @@ -43,7 +43,7 @@ cpp_cls_value=$(func_parser_value "${lines[18]}") cpp_use_angle_cls_key=$(func_parser_key "${lines[19]}") cpp_use_angle_cls_value=$(func_parser_value "${lines[19]}") -LOG_PATH="./test_tipc/output/cpp_infer/${model_name}" +LOG_PATH="./test_tipc/output/${model_name}/cpp_infer" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_cpp.log" @@ -178,6 +178,19 @@ if [ ${use_opencv} = "True" ]; then else OPENCV_DIR='' fi +if [ -d "paddle_inference/" ] ;then + echo "################### download paddle inference skipped ###################" +else + echo "################### download paddle inference ###################" + PADDLEInfer=$3 + if [ "" = "$PADDLEInfer" ];then + wget -nc https://paddle-inference-lib.bj.bcebos.com/2.3.0/cxx_c/Linux/GPU/x86-64_gcc8.2_avx_mkl_cuda10.1_cudnn7.6.5_trt6.0.1.5/paddle_inference.tgz --no-check-certificate + else + wget -nc $PADDLEInfer --no-check-certificate + fi + tar zxf paddle_inference.tgz + echo "################### download paddle inference finished ###################" +fi LIB_DIR=$(pwd)/paddle_inference/ CUDA_LIB_DIR=$(dirname `find /usr -name libcudart.so`) CUDNN_LIB_DIR=$(dirname `find /usr -name libcudnn.so`) From b7656e684eaf0df5344ba5036731e38c3cbf265a Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 26 May 2022 12:29:49 +0000 Subject: [PATCH 047/129] add paddle2onnx for tipc --- ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 9 +- ...al_normal_paddle2onnx_python_linux_cpu.txt | 11 +- ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 9 +- ...al_normal_paddle2onnx_python_linux_cpu.txt | 13 +- ...al_normal_paddle2onnx_python_linux_cpu.txt | 17 +++ ...al_normal_paddle2onnx_python_linux_cpu.txt | 11 +- ...al_normal_paddle2onnx_python_linux_cpu.txt | 13 +- test_tipc/test_paddle2onnx.sh | 122 +++++++++++++----- 13 files changed, 236 insertions(+), 54 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..fad9820a12 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_PP-OCRv2 +python:python3.7 +2onnx: paddle2onnx +--det_model_dir:./inference/ch_PP-OCRv2_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file:./inference/det_v2_onnx/model.onnx +--rec_model_dir:./inference/ch_PP-OCRv2_rec_infer/ +--rec_save_file:./inference/rec_v2_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_system.py --rec_image_shape="3,32,320" +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..2e7906076f --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_PP-OCRv2_det +python:python3.7 +2onnx: paddle2onnx +--det_model_dir:./inference/ch_PP-OCRv2_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file:./inference/det_v2_onnx/model.onnx +--rec_model_dir: +--rec_save_file: +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_det.py +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..e374a5d821 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_PP-OCRv2_rec +python:python3.7 +2onnx: paddle2onnx +--det_model_dir: +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file: +--rec_model_dir:./inference/ch_PP-OCRv2_rec_infer/ +--rec_save_file:./inference/rec_v2_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_rec.py --rec_image_shape="3,32,320" +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/rec_inference/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..15237664ac --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_PP-OCRv3 +python:python3.7 +2onnx: paddle2onnx +--det_model_dir:./inference/ch_PP-OCRv3_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file:./inference/det_v3_onnx/model.onnx +--rec_model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--rec_save_file:./inference/rec_v3_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_system.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index b4c681c0aa..a448713b1c 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_det_v3 +model_name:ch_PP-OCRv3_det python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_PP-OCRv3_det_infer/ +--det_model_dir:./inference/ch_PP-OCRv3_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/det_v3_onnx/model.onnx +--det_save_file:./inference/det_v3_onnx/model.onnx +--rec_model_dir: +--rec_save_file: --opset_version:10 --enable_onnx_checker:True inference:tools/infer/predict_det.py --use_gpu:True|False --det_model_dir: +--rec_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index eb1cbb9044..9114c0acfd 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_rec_v3 +model_name:ch_PP-OCRv3_rec python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--det_model_dir: --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/rec_v3_onnx/model.onnx +--det_save_file: +--rec_model_dir:./inference/ch_PP-OCRv3_rec_infer/ +--rec_save_file:./inference/rec_v3_onnx/model.onnx --opset_version:10 --enable_onnx_checker:True inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False +--det_model_dir: --rec_model_dir: ---image_dir:./inference/rec_inference \ No newline at end of file +--image_dir:./inference/rec_inference/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..17c2fbbae2 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_ppocr_mobile_v2.0 +python:python3.7 +2onnx: paddle2onnx +--det_model_dir:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file:./inference/det_mobile_onnx/model.onnx +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--rec_save_file:./inference/rec_mobile_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_system.py --rec_image_shape="3,32,320" +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index 160bcdbd88..00473d1062 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_det_mobile +model_name:ch_ppocr_mobile_v2.0_det python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--det_model_dir:./inference/ch_ppocr_mobile_v2.0_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/det_mobile_onnx/model.onnx +--det_save_file:./inference/det_mobile_onnx/model.onnx +--rec_model_dir: +--rec_save_file: --opset_version:10 --enable_onnx_checker:True inference:tools/infer/predict_det.py --use_gpu:True|False --det_model_dir: +--rec_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index f29b303879..5bab0c9e4c 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_rec_mobile +model_name:ch_ppocr_mobile_v2.0_rec python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--det_model_dir: --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/rec_mobile_onnx/model.onnx +--det_save_file: +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--rec_save_file:./inference/rec_mobile_onnx/model.onnx --opset_version:10 --enable_onnx_checker:True -inference:tools/infer/predict_rec.py +inference:tools/infer/predict_rec.py --rec_image_shape="3,32,320" --use_gpu:True|False +--det_model_dir: --rec_model_dir: ---image_dir:./inference/rec_inference \ No newline at end of file +--image_dir:./inference/rec_inference/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt new file mode 100644 index 0000000000..a60c3e9b83 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -0,0 +1,17 @@ +===========================paddle2onnx_params=========================== +model_name:ch_ppocr_server_v2.0 +python:python3.7 +2onnx: paddle2onnx +--det_model_dir:./inference/ch_ppocr_server_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_save_file:./inference/det_server_onnx/model.onnx +--rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +--rec_save_file:./inference/rec_server_onnx/model.onnx +--opset_version:10 +--enable_onnx_checker:True +inference:tools/infer/predict_system.py --rec_image_shape="3,32,320" +--use_gpu:True|False +--det_model_dir: +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index 40fdc11241..574e4f2e86 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_det_server +model_name:ch_ppocr_server_v2.0_det python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_ppocr_server_v2.0_det_infer/ +--det_model_dir:./inference/ch_ppocr_server_v2.0_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/det_server_onnx/model.onnx +--det_save_file:./inference/det_server_onnx/model.onnx +--rec_model_dir: +--rec_save_file: --opset_version:10 --enable_onnx_checker:True inference:tools/infer/predict_det.py --use_gpu:True|False --det_model_dir: ---image_dir:./inference/det_inference \ No newline at end of file +--rec_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index 05542332e9..462f6090d9 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -1,14 +1,17 @@ ===========================paddle2onnx_params=========================== -model_name:ocr_rec_server +model_name:ch_ppocr_server_v2.0_rec python:python3.7 2onnx: paddle2onnx ---model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +--det_model_dir: --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---save_file:./inference/rec_server_onnx/model.onnx +--det_save_file: +--rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +--rec_save_file:./inference/rec_server_onnx/model.onnx --opset_version:10 --enable_onnx_checker:True -inference:tools/infer/predict_rec.py +inference:tools/infer/predict_rec.py --rec_image_shape="3,32,320" --use_gpu:True|False +--det_model_dir: --rec_model_dir: ---image_dir:./inference/rec_inference \ No newline at end of file +--image_dir:./inference/rec_inference/ \ No newline at end of file diff --git a/test_tipc/test_paddle2onnx.sh b/test_tipc/test_paddle2onnx.sh index 4d1712cfda..fa230bde40 100644 --- a/test_tipc/test_paddle2onnx.sh +++ b/test_tipc/test_paddle2onnx.sh @@ -11,7 +11,7 @@ python=$(func_parser_value "${lines[2]}") # parser params -dataline=$(awk 'NR==1, NR==14{print}' $FILENAME) +dataline=$(awk 'NR==1, NR==17{print}' $FILENAME) IFS=$'\n' lines=(${dataline}) @@ -19,27 +19,32 @@ lines=(${dataline}) model_name=$(func_parser_value "${lines[1]}") python=$(func_parser_value "${lines[2]}") padlle2onnx_cmd=$(func_parser_value "${lines[3]}") -infer_model_dir_key=$(func_parser_key "${lines[4]}") -infer_model_dir_value=$(func_parser_value "${lines[4]}") +det_infer_model_dir_key=$(func_parser_key "${lines[4]}") +det_infer_model_dir_value=$(func_parser_value "${lines[4]}") model_filename_key=$(func_parser_key "${lines[5]}") model_filename_value=$(func_parser_value "${lines[5]}") params_filename_key=$(func_parser_key "${lines[6]}") params_filename_value=$(func_parser_value "${lines[6]}") -save_file_key=$(func_parser_key "${lines[7]}") -save_file_value=$(func_parser_value "${lines[7]}") -opset_version_key=$(func_parser_key "${lines[8]}") -opset_version_value=$(func_parser_value "${lines[8]}") -enable_onnx_checker_key=$(func_parser_key "${lines[9]}") -enable_onnx_checker_value=$(func_parser_value "${lines[9]}") +det_save_file_key=$(func_parser_key "${lines[7]}") +det_save_file_value=$(func_parser_value "${lines[7]}") +rec_infer_model_dir_key=$(func_parser_key "${lines[8]}") +rec_infer_model_dir_value=$(func_parser_value "${lines[8]}") +rec_save_file_key=$(func_parser_key "${lines[9]}") +rec_save_file_value=$(func_parser_value "${lines[9]}") +opset_version_key=$(func_parser_key "${lines[10]}") +opset_version_value=$(func_parser_value "${lines[10]}") +enable_onnx_checker_key=$(func_parser_key "${lines[11]}") +enable_onnx_checker_value=$(func_parser_value "${lines[11]}") # parser onnx inference -inference_py=$(func_parser_value "${lines[10]}") -use_gpu_key=$(func_parser_key "${lines[11]}") -use_gpu_list=$(func_parser_value "${lines[11]}") -det_model_key=$(func_parser_key "${lines[12]}") -image_dir_key=$(func_parser_key "${lines[13]}") -image_dir_value=$(func_parser_value "${lines[13]}") +inference_py=$(func_parser_value "${lines[12]}") +use_gpu_key=$(func_parser_key "${lines[13]}") +use_gpu_list=$(func_parser_value "${lines[13]}") +det_model_key=$(func_parser_key "${lines[14]}") +rec_model_key=$(func_parser_key "${lines[15]}") +image_dir_key=$(func_parser_key "${lines[16]}") +image_dir_value=$(func_parser_value "${lines[16]}") -LOG_PATH="./test_tipc/output/paddle2onnx/${model_name}" +LOG_PATH="./test_tipc/output/${model_name}/paddle2onnx" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_paddle2onnx.log" @@ -49,24 +54,72 @@ function func_paddle2onnx(){ _script=$1 # paddle2onnx - set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") - set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") - set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") - set_save_model=$(func_set_params "${save_file_key}" "${save_file_value}") - set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") - set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") - trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" - eval $trans_model_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${trans_model_cmd}" "${status_log}" + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + # trans det + set_dirname=$(func_set_params "--model_dir" "${det_infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_save_model=$(func_set_params "--save_file" "${det_save_file_value}") + set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") + set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + eval $trans_model_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${trans_model_cmd}" "${status_log}" + # trans rec + set_dirname=$(func_set_params "--model_dir" "${rec_infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_save_model=$(func_set_params "--save_file" "${rec_save_file_value}") + set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") + set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + eval $trans_model_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${trans_model_cmd}" "${status_log}" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + # trans det + set_dirname=$(func_set_params "--model_dir" "${det_infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_save_model=$(func_set_params "--save_file" "${det_save_file_value}") + set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") + set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + eval $trans_model_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${trans_model_cmd}" "${status_log}" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + # trans rec + set_dirname=$(func_set_params "--model_dir" "${rec_infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_save_model=$(func_set_params "--save_file" "${rec_save_file_value}") + set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") + set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + eval $trans_model_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${trans_model_cmd}" "${status_log}" + fi + # python inference for use_gpu in ${use_gpu_list[*]}; do if [ ${use_gpu} = "False" ] || [ ${use_gpu} = "cpu" ]; then _save_log_path="${LOG_PATH}/paddle2onnx_infer_cpu.log" set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu}") - set_model_dir=$(func_set_params "${det_model_key}" "${save_file_value}") set_img_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") - infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") + set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + fi eval $infer_model_cmd last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" @@ -74,9 +127,18 @@ function func_paddle2onnx(){ elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then _save_log_path="${LOG_PATH}/paddle2onnx_infer_gpu.log" set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu}") - set_model_dir=$(func_set_params "${det_model_key}" "${save_file_value}") set_img_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") - infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") + set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") + infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " + fi eval $infer_model_cmd last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" From 8ffef11f5ebd2e59f6034d52e4608660cb80382b Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Fri, 27 May 2022 02:38:23 +0000 Subject: [PATCH 048/129] update for tipc --- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../configs/ch_PP-OCRv2_det/train_infer_python.txt | 2 +- .../ch_PP-OCRv2_det_PACT/train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../configs/ch_PP-OCRv2_rec/train_infer_python.txt | 2 +- .../ch_PP-OCRv2_rec_PACT/train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../configs/ch_PP-OCRv3_det/train_infer_python.txt | 2 +- .../ch_PP-OCRv3_det_PACT/train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../configs/ch_PP-OCRv3_rec/train_infer_python.txt | 2 +- .../ch_PP-OCRv3_rec_PACT/train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../ch_ppocr_mobile_v2.0_det/train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../ch_ppocr_mobile_v2.0_rec/train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../ch_ppocr_server_v2.0_det/train_infer_python.txt | 2 +- ...nux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- .../ch_ppocr_server_v2.0_rec/train_infer_python.txt | 2 +- .../configs/det_mv3_db_v2_0/train_infer_python.txt | 2 +- .../configs/det_mv3_east_v2.0/train_infer_python.txt | 2 +- .../configs/det_mv3_pse_v2.0/train_infer_python.txt | 2 +- .../det_r18_vd_db_v2_0/train_infer_python.txt | 2 +- .../configs/det_r50_db_v2.0/train_infer_python.txt | 2 +- .../det_r50_vd_east_v2_0/train_infer_python.txt | 2 +- .../det_r50_vd_pse_v2_0/train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../configs/en_server_pgnetA/train_infer_python.txt | 2 +- .../configs/rec_mtb_nrtr/train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- test_tipc/configs/rec_r31_sar/train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../train_infer_python.txt | 2 +- .../rec_r50_fpn_vd_none_srn/train_infer_python.txt | 2 +- test_tipc/test_inference_cpp.sh | 4 ++-- test_tipc/test_paddle2onnx.sh | 12 ++++++------ test_tipc/test_train_inference_python.sh | 12 ++++++------ 52 files changed, 63 insertions(+), 63 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index ff271b94af..b31e102b62 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --rec_model_dir:./inference/ch_PP-OCRv2_rec_infer/ diff --git a/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 7bf584776f..7eccbd725c 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt index 0a4de9790b..cab0cb0aa3 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt index c43ed862c1..1a20f97fdb 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 3f8b4442c9..60f4788370 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:6 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt index b3049212ae..df42b342ba 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt index f6c50bcefc..4168326817 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index ec82f320cf..794af27d90 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./p --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --rec_model_dir:./inference/ch_PP-OCRv3_rec_infer/ diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index bd69098560..aecd0dd437 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt index e81450464a..a69e0ab81e 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt index 626e05a37b..b536e69b05 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 089f38d7a3..9d6ca2cf5e 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./p --cpu_threads:6 --rec_batch_num:6 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt index 5e607b1709..1feb9d49fc 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt index 4b63b65ae8..f26b86290a 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 1cb9c0c3d4..8f76631aa4 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 5d3d8615ae..1d1c2ae283 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt index e2a0a1b1ff..789ed4d23d 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt index ec811bd509..dae3f8053a 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt index d042d2a285..522f30d14b 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index c9ff73f007..25b0dcf3c0 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:6 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt index 9442b352a7..f02b93926c 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt index 6ed6556cf9..89daceeb5f 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt index ec62059a11..77472fbdfb 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ppocr_ke --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index ac23b804b7..b03130a15f 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 75f5a4e93a..69ae939e2b 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt index e8244661ca..c16ca15002 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index b102f5aecd..79fee95a1a 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -9,7 +9,7 @@ inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppoc --cpu_threads:6 --rec_batch_num:6 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference/ null:null diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt index de6164ebe2..64c0cf455c 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt b/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt index 19010e859e..ab3aa59b60 100644 --- a/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_db_v2_0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt b/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt index ec23c852ea..1ec1597a4d 100644 --- a/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_east_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt b/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt index 7563dcac22..daeec69f84 100644 --- a/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_mv3_pse_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt b/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt index df09cf0b10..33e4dbf233 100644 --- a/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r18_vd_db_v2_0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt index d55621dc76..151f2769cc 100644 --- a/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_db_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt index 0d0f331777..8477a4fa74 100644 --- a/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_east_v2_0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt index b4bf40f2b0..62da89fe1c 100644 --- a/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_pse_v2_0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt index e7d75d802b..11444a3ac1 100644 --- a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt index 17a87a1941..7be5af7dde 100644 --- a/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_totaltext_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_det.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/en_server_pgnetA/train_infer_python.txt b/test_tipc/configs/en_server_pgnetA/train_infer_python.txt index 593ea00f1c..a9dd4e676b 100644 --- a/test_tipc/configs/en_server_pgnetA/train_infer_python.txt +++ b/test_tipc/configs/en_server_pgnetA/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_e2e.py --cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False ---precision:fp32|fp16|int8 +--precision:fp32 --e2e_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt b/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt index 8bfbc7142b..fed8ba2675 100644 --- a/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt +++ b/test_tipc/configs/rec_mtb_nrtr/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/EN_symbo --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt index 9f308988a7..39bf922790 100644 --- a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt index e0c06f1e4d..593de3ff20 100644 --- a/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_none_none_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt index da599e62f8..1b2d9abb0f 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt index 7e6d4ad077..1367c7abd4 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r31_sar/train_infer_python.txt b/test_tipc/configs/rec_r31_sar/train_infer_python.txt index 9475814129..03ec54abb6 100644 --- a/test_tipc/configs/rec_r31_sar/train_infer_python.txt +++ b/test_tipc/configs/rec_r31_sar/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/dict90.t --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt index e85758ad70..46aa3d7190 100644 --- a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt index 0b8066ed74..3e066d7b72 100644 --- a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt index 970bf63261..1e4f46633e 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt index 4dfcc0ab9c..9e795b6645 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2.0/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt b/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt index 98eaca84af..b5a5286010 100644 --- a/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt +++ b/test_tipc/configs/rec_r50_fpn_vd_none_srn/train_infer_python.txt @@ -43,7 +43,7 @@ inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dic --cpu_threads:6 --rec_batch_num:1|6 --use_tensorrt:False ---precision:fp32|int8 +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/test_inference_cpp.sh b/test_tipc/test_inference_cpp.sh index 92429c65da..d759d2858e 100644 --- a/test_tipc/test_inference_cpp.sh +++ b/test_tipc/test_inference_cpp.sh @@ -84,7 +84,7 @@ function func_cpp_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done done @@ -117,7 +117,7 @@ function func_cpp_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done diff --git a/test_tipc/test_paddle2onnx.sh b/test_tipc/test_paddle2onnx.sh index fa230bde40..e7ab018b52 100644 --- a/test_tipc/test_paddle2onnx.sh +++ b/test_tipc/test_paddle2onnx.sh @@ -65,7 +65,7 @@ function func_paddle2onnx(){ trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" eval $trans_model_cmd last_status=${PIPESTATUS[0]} - status_check $last_status "${trans_model_cmd}" "${status_log}" + status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" # trans rec set_dirname=$(func_set_params "--model_dir" "${rec_infer_model_dir_value}") set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") @@ -76,7 +76,7 @@ function func_paddle2onnx(){ trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" eval $trans_model_cmd last_status=${PIPESTATUS[0]} - status_check $last_status "${trans_model_cmd}" "${status_log}" + status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then # trans det set_dirname=$(func_set_params "--model_dir" "${det_infer_model_dir_value}") @@ -88,7 +88,7 @@ function func_paddle2onnx(){ trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" eval $trans_model_cmd last_status=${PIPESTATUS[0]} - status_check $last_status "${trans_model_cmd}" "${status_log}" + status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then # trans rec set_dirname=$(func_set_params "--model_dir" "${rec_infer_model_dir_value}") @@ -100,7 +100,7 @@ function func_paddle2onnx(){ trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" eval $trans_model_cmd last_status=${PIPESTATUS[0]} - status_check $last_status "${trans_model_cmd}" "${status_log}" + status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" fi # python inference @@ -123,7 +123,7 @@ function func_paddle2onnx(){ eval $infer_model_cmd last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${infer_model_cmd}" "${status_log}" + status_check $last_status "${infer_model_cmd}" "${status_log}" "${model_name}" elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then _save_log_path="${LOG_PATH}/paddle2onnx_infer_gpu.log" set_gpu=$(func_set_params "${use_gpu_key}" "${use_gpu}") @@ -142,7 +142,7 @@ function func_paddle2onnx(){ eval $infer_model_cmd last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${infer_model_cmd}" "${status_log}" + status_check $last_status "${infer_model_cmd}" "${status_log}" "${model_name}" else echo "Does not support hardware other than CPU and GPU Currently!" fi diff --git a/test_tipc/test_train_inference_python.sh b/test_tipc/test_train_inference_python.sh index 82a373cf7b..1527875bea 100644 --- a/test_tipc/test_train_inference_python.sh +++ b/test_tipc/test_train_inference_python.sh @@ -169,7 +169,7 @@ function func_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done done @@ -200,7 +200,7 @@ function func_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done @@ -240,7 +240,7 @@ if [ ${MODE} = "whole_infer" ] || [ ${MODE} = "klquant_whole_infer" ]; then echo $export_cmd eval $export_cmd status_export=$? - status_check $status_export "${export_cmd}" "${status_log}" + status_check $status_export "${export_cmd}" "${status_log}" "${model_name}" else save_infer_dir=${infer_model} fi @@ -337,7 +337,7 @@ else fi # run train eval $cmd - status_check $? "${cmd}" "${status_log}" + status_check $? "${cmd}" "${status_log}" "${model_name}" set_eval_pretrain=$(func_set_params "${pretrain_model_key}" "${save_log}/${train_model_name}") @@ -347,7 +347,7 @@ else set_eval_params1=$(func_set_params "${eval_key1}" "${eval_value1}") eval_cmd="${python} ${eval_py} ${set_eval_pretrain} ${set_use_gpu} ${set_eval_params1}" eval $eval_cmd - status_check $? "${eval_cmd}" "${status_log}" + status_check $? "${eval_cmd}" "${status_log}" "${model_name}" fi # run export model if [ ${run_export} != "null" ]; then @@ -357,7 +357,7 @@ else set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_path}") export_cmd="${python} ${run_export} ${set_export_weight} ${set_save_infer_key}" eval $export_cmd - status_check $? "${export_cmd}" "${status_log}" + status_check $? "${export_cmd}" "${status_log}" "${model_name}" #run inference eval $env From 296809a05656efce241b0e9082396421164b8402 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 30 May 2022 02:35:42 +0000 Subject: [PATCH 049/129] debug_table --- ppstructure/table/predict_table.py | 37 ++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/ppstructure/table/predict_table.py b/ppstructure/table/predict_table.py index 402d6c2418..d7d1760d35 100644 --- a/ppstructure/table/predict_table.py +++ b/ppstructure/table/predict_table.py @@ -28,6 +28,7 @@ import numpy as np import time import tools.infer.predict_rec as predict_rec import tools.infer.predict_det as predict_det +import tools.infer.utility as utility from ppocr.utils.utility import get_image_file_list, check_and_read_gif from ppocr.utils.logging import get_logger from ppstructure.table.matcher import distance, compute_iou @@ -59,11 +60,37 @@ class TableSystem(object): self.text_recognizer = predict_rec.TextRecognizer( args) if text_recognizer is None else text_recognizer self.table_structurer = predict_strture.TableStructurer(args) + self.benchmark = args.benchmark + self.predictor, self.input_tensor, self.output_tensors, self.config = utility.create_predictor( + args, 'table', logger) + if args.benchmark: + import auto_log + pid = os.getpid() + gpu_id = utility.get_infer_gpuid() + self.autolog = auto_log.AutoLogger( + model_name="table", + model_precision=args.precision, + batch_size=1, + data_shape="dynamic", + save_path=None, #args.save_log_path, + inference_config=self.config, + pids=pid, + process_name=None, + gpu_ids=gpu_id if args.use_gpu else None, + time_keys=[ + 'preprocess_time', 'inference_time', 'postprocess_time' + ], + warmup=0, + logger=logger) def __call__(self, img, return_ocr_result_in_table=False): result = dict() ori_im = img.copy() + if self.benchmark: + self.autolog.times.start() structure_res, elapse = self.table_structurer(copy.deepcopy(img)) + if self.benchmark: + self.autolog.times.stamp() dt_boxes, elapse = self.text_detector(copy.deepcopy(img)) dt_boxes = sorted_boxes(dt_boxes) if return_ocr_result_in_table: @@ -77,13 +104,11 @@ class TableSystem(object): box = [x_min, y_min, x_max, y_max] r_boxes.append(box) dt_boxes = np.array(r_boxes) - logger.debug("dt_boxes num : {}, elapse : {}".format( len(dt_boxes), elapse)) if dt_boxes is None: return None, None img_crop_list = [] - for i in range(len(dt_boxes)): det_box = dt_boxes[i] x0, y0, x1, y1 = expand(2, det_box, ori_im.shape) @@ -92,10 +117,14 @@ class TableSystem(object): rec_res, elapse = self.text_recognizer(img_crop_list) logger.debug("rec_res num : {}, elapse : {}".format( len(rec_res), elapse)) + if self.benchmark: + self.autolog.times.stamp() if return_ocr_result_in_table: result['rec_res'] = rec_res pred_html, pred = self.rebuild_table(structure_res, dt_boxes, rec_res) result['html'] = pred_html + if self.benchmark: + self.autolog.times.end(stamp=True) return result def rebuild_table(self, structure_res, dt_boxes, rec_res): @@ -213,11 +242,15 @@ def main(args): logger.info('excel saved to {}'.format(excel_path)) elapse = time.time() - starttime logger.info("Predict time : {:.3f}s".format(elapse)) + if args.benchmark: + text_sys.autolog.report() + print('ok') if __name__ == "__main__": args = parse_args() if args.use_mp: + print('mp') p_list = [] total_process_num = args.total_process_num for process_id in range(total_process_num): From 354d5800072dbdf449b7bba36d59f61f30d046b5 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Mon, 30 May 2022 11:48:13 +0800 Subject: [PATCH 050/129] Update PP-OCRv3_introduction_en.md --- doc/doc_en/PP-OCRv3_introduction_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doc_en/PP-OCRv3_introduction_en.md b/doc/doc_en/PP-OCRv3_introduction_en.md index 07894340c2..2874703466 100644 --- a/doc/doc_en/PP-OCRv3_introduction_en.md +++ b/doc/doc_en/PP-OCRv3_introduction_en.md @@ -76,7 +76,7 @@ LK-PAN (Large Kernel PAN) is a lightweight [PAN](https://arxiv.org/pdf/1803.0153 **(2) DML: Deep Mutual Learning Strategy for Teacher Model** -[DML](https://arxiv.org/abs/1706.00384)(Collaborative Mutual Learning), as shown in the figure below, can effectively improve the accuracy of the text detection model by learning from each other with two models with the same structure. The DML strategy is adopted in the teacher model training, and the hmean is increased from 85% to 86%. By updating the teacher model of CML in PP-OCRv2 to the above-mentioned higher-precision one, the hmean of the student model can be further improved from 83.2% to 84.3%. +[DML](https://arxiv.org/abs/1706.00384)(Deep Mutual Learning), as shown in the figure below, can effectively improve the accuracy of the text detection model by learning from each other with two models with the same structure. The DML strategy is adopted in the teacher model training, and the hmean is increased from 85% to 86%. By updating the teacher model of CML in PP-OCRv2 to the above-mentioned higher-precision one, the hmean of the student model can be further improved from 83.2% to 84.3%.
From e37fbd138087c32694b3c3eaed1a5be0b688181d Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 30 May 2022 08:10:37 +0000 Subject: [PATCH 051/129] update doc for quickstart --- deploy/cpp_infer/readme.md | 8 ++------ deploy/cpp_infer/readme_ch.md | 8 ++------ deploy/cpp_infer/src/args.cpp | 2 +- deploy/cpp_infer/src/ocr_rec.cpp | 4 +++- doc/doc_ch/quickstart.md | 11 ++++++++++- doc/doc_en/quickstart_en.md | 13 ++++++++++++- ppocr/data/simple_dataset.py | 2 +- 7 files changed, 31 insertions(+), 17 deletions(-) diff --git a/deploy/cpp_infer/readme.md b/deploy/cpp_infer/readme.md index ddd15d4955..942a633fd3 100644 --- a/deploy/cpp_infer/readme.md +++ b/deploy/cpp_infer/readme.md @@ -208,7 +208,7 @@ Execute the built executable file: ./build/ppocr [--param1] [--param2] [...] ``` -**Note**:ppocr uses the `PP-OCRv3` model by default, and the input shape used by the recognition model is `3, 48, 320`, so if you use the recognition function, you need to add the parameter `--rec_img_h=48`, if you do not use the default `PP-OCRv3` model, you do not need to set this parameter. +**Note**:ppocr uses the `PP-OCRv3` model by default, and the input shape used by the recognition model is `3, 48, 320`, if you do not use the default `PP-OCRv3` model, you should add the parameter `--rec_img_h=32`. Specifically, @@ -222,7 +222,6 @@ Specifically, --det=true \ --rec=true \ --cls=true \ - --rec_img_h=48\ ``` ##### 2. det+rec: @@ -234,7 +233,6 @@ Specifically, --det=true \ --rec=true \ --cls=false \ - --rec_img_h=48\ ``` ##### 3. det @@ -254,7 +252,6 @@ Specifically, --det=false \ --rec=true \ --cls=true \ - --rec_img_h=48\ ``` ##### 5. rec @@ -265,7 +262,6 @@ Specifically, --det=false \ --rec=true \ --cls=false \ - --rec_img_h=48\ ``` ##### 6. cls @@ -330,7 +326,7 @@ More parameters are as follows, |rec_model_dir|string|-|Address of recognition inference model| |rec_char_dict_path|string|../../ppocr/utils/ppocr_keys_v1.txt|dictionary file| |rec_batch_num|int|6|batch size of recognition| -|rec_img_h|int|32|image height of recognition| +|rec_img_h|int|48|image height of recognition| |rec_img_w|int|320|image width of recognition| * Multi-language inference is also supported in PaddleOCR, you can refer to [recognition tutorial](../../doc/doc_en/recognition_en.md) for more supported languages and models in PaddleOCR. Specifically, if you want to infer using multi-language models, you just need to modify values of `rec_char_dict_path` and `rec_model_dir`. diff --git a/deploy/cpp_infer/readme_ch.md b/deploy/cpp_infer/readme_ch.md index e5a4869eca..4a79f978fb 100644 --- a/deploy/cpp_infer/readme_ch.md +++ b/deploy/cpp_infer/readme_ch.md @@ -213,7 +213,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir 本demo支持系统串联调用,也支持单个功能的调用,如,只使用检测或识别功能。 -**注意** ppocr默认使用`PP-OCRv3`模型,识别模型使用的输入shape为`3,48,320`, 因此如果使用识别功能,需要添加参数`--rec_img_h=48`,如果不使用默认的`PP-OCRv3`模型,则无需设置该参数。 +**注意** ppocr默认使用`PP-OCRv3`模型,识别模型使用的输入shape为`3,48,320`, 如果不使用默认的`PP-OCRv3`模型,则需要设置参数`--rec_img_h=32`。 运行方式: @@ -232,7 +232,6 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir --det=true \ --rec=true \ --cls=true \ - --rec_img_h=48\ ``` ##### 2. 检测+识别: @@ -244,7 +243,6 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir --det=true \ --rec=true \ --cls=false \ - --rec_img_h=48\ ``` ##### 3. 检测: @@ -264,7 +262,6 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir --det=false \ --rec=true \ --cls=true \ - --rec_img_h=48\ ``` ##### 5. 识别: @@ -275,7 +272,6 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir --det=false \ --rec=true \ --cls=false \ - --rec_img_h=48\ ``` ##### 6. 分类: @@ -339,7 +335,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir |rec_model_dir|string|-|识别模型inference model地址| |rec_char_dict_path|string|../../ppocr/utils/ppocr_keys_v1.txt|字典文件| |rec_batch_num|int|6|识别模型batchsize| -|rec_img_h|int|32|识别模型输入图像高度| +|rec_img_h|int|48|识别模型输入图像高度| |rec_img_w|int|320|识别模型输入图像宽度| diff --git a/deploy/cpp_infer/src/args.cpp b/deploy/cpp_infer/src/args.cpp index fe58236734..93d0f5ea5f 100644 --- a/deploy/cpp_infer/src/args.cpp +++ b/deploy/cpp_infer/src/args.cpp @@ -47,7 +47,7 @@ DEFINE_string(rec_model_dir, "", "Path of rec inference model."); DEFINE_int32(rec_batch_num, 6, "rec_batch_num."); DEFINE_string(rec_char_dict_path, "../../ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); -DEFINE_int32(rec_img_h, 32, "rec image height"); +DEFINE_int32(rec_img_h, 48, "rec image height"); DEFINE_int32(rec_img_w, 320, "rec image width"); // ocr forward related diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp index 0a6fe693e2..3438d4074e 100644 --- a/deploy/cpp_infer/src/ocr_rec.cpp +++ b/deploy/cpp_infer/src/ocr_rec.cpp @@ -132,7 +132,9 @@ void CRNNRecognizer::LoadModel(const std::string &model_dir) { paddle_infer::Config config; config.SetModel(model_dir + "/inference.pdmodel", model_dir + "/inference.pdiparams"); - + std::cout << "In PP-OCRv3, default rec_img_h is 48," + << "if you use other model, you should set the param rec_img_h=32" + << std::endl; if (this->use_gpu_) { config.EnableUseGpu(this->gpu_mem_, this->gpu_id_); if (this->use_tensorrt_) { diff --git a/doc/doc_ch/quickstart.md b/doc/doc_ch/quickstart.md index 29ca48fa83..d2c2f288b0 100644 --- a/doc/doc_ch/quickstart.md +++ b/doc/doc_ch/quickstart.md @@ -101,8 +101,17 @@ cd /path/to/ppocr_img ['韩国小馆', 0.994467] ``` +**版本说明** +paddleocr默认使用PP-OCRv3模型(`--ocr_version PP-OCRv3`),如需使用其他版本可通过设置参数`--ocr_version`,具体版本说明如下: +| 版本名称 | 版本说明 | +| --- | --- | +| PP-OCRv3 | 支持中、英文检测和识别,方向分类器,支持多语种识别 | +| PP-OCRv2 | 仅支持中英文的检测和识别 | +| PP-OCR | 支持中、英文检测和识别,方向分类器,支持多语种识别 | -如需使用2.0模型,请指定参数`--ocr_version PP-OCR`,paddleocr默认使用PP-OCRv3模型(`--ocr_version PP-OCRv3`)。更多whl包使用可参考[whl包文档](./whl.md) +如需新增自己训练的模型,可以在[paddleocr](../../paddleocr.py)中增加模型链接和字段,重新编译即可。 + +更多whl包使用可参考[whl包文档](./whl.md) diff --git a/doc/doc_en/quickstart_en.md b/doc/doc_en/quickstart_en.md index d7aeb77730..f0e41e313a 100644 --- a/doc/doc_en/quickstart_en.md +++ b/doc/doc_en/quickstart_en.md @@ -119,7 +119,18 @@ If you do not use the provided test image, you can replace the following `--imag ['PAIN', 0.9934559464454651] ``` -If you need to use the 2.0 model, please specify the parameter `--ocr_version PP-OCR`, paddleocr uses the PP-OCRv3 model by default(`--ocr_version PP-OCRv3`). More whl package usage can be found in [whl package](./whl_en.md) +**Version** +paddleocr uses the PP-OCRv3 model by default(`--ocr_version PP-OCRv3`). If you want to use other versions, you can set the parameter `--ocr_version`, the specific version description is as follows: +| version name | description | +| --- | --- | +| PP-OCRv3 | support Chinese and English detection and recognition, direction classifier, support multilingual recognition | +| PP-OCRv2 | only supports Chinese and English detection and recognition | +| PP-OCR | support Chinese and English detection and recognition, direction classifier, support multilingual recognition | + +If you want to add your own trained model, you can add model links and keys in [paddleocr](../../paddleocr.py) and recompile. + +More whl package usage can be found in [whl package](./whl_en.md) + #### 2.1.2 Multi-language Model diff --git a/ppocr/data/simple_dataset.py b/ppocr/data/simple_dataset.py index b5da9b8898..402f1e38fe 100644 --- a/ppocr/data/simple_dataset.py +++ b/ppocr/data/simple_dataset.py @@ -33,7 +33,7 @@ class SimpleDataSet(Dataset): self.delimiter = dataset_config.get('delimiter', '\t') label_file_list = dataset_config.pop('label_file_list') data_source_num = len(label_file_list) - ratio_list = dataset_config.get("ratio_list", [1.0]) + ratio_list = dataset_config.get("ratio_list", 1.0) if isinstance(ratio_list, (float, int)): ratio_list = [float(ratio_list)] * int(data_source_num) From feca63686d0dfdb0d46dc9c140e26643201bbbef Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 30 May 2022 16:44:50 +0800 Subject: [PATCH 052/129] add bda --- .../cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml | 3 +- configs/cls/cls_mv3.yml | 3 +- doc/doc_ch/FAQ.md | 2 +- ppocr/data/imaug/__init__.py | 2 +- ppocr/data/imaug/rec_img_aug.py | 160 ++++++++---------- 5 files changed, 70 insertions(+), 100 deletions(-) diff --git a/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml b/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml index 1ffeba0799..f7e327d1e0 100644 --- a/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml +++ b/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml @@ -63,8 +63,7 @@ Train: - DecodeImage: img_mode: BGR channel_first: false - - RecAug: - use_tia: False + - BaseDataAugmentation: - RandAugment: - SSLRotateResize: image_shape: [3, 48, 320] diff --git a/configs/cls/cls_mv3.yml b/configs/cls/cls_mv3.yml index 5e643dc383..0c46ff5602 100644 --- a/configs/cls/cls_mv3.yml +++ b/configs/cls/cls_mv3.yml @@ -60,8 +60,7 @@ Train: img_mode: BGR channel_first: False - ClsLabelEncode: # Class handling label - - RecAug: - use_tia: False + - BaseDataAugmentation: - RandAugment: - ClsResizeImg: image_shape: [3, 48, 192] diff --git a/doc/doc_ch/FAQ.md b/doc/doc_ch/FAQ.md index 24f8a3e92b..2dad829284 100644 --- a/doc/doc_ch/FAQ.md +++ b/doc/doc_ch/FAQ.md @@ -682,7 +682,7 @@ lr: #### Q: 关于dygraph分支中,文本识别模型训练,要使用数据增强应该如何设置? -**A**:可以参考[配置文件](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)在Train['dataset']['transforms']添加RecAug字段,使数据增强生效。可以通过添加对aug_prob设置,表示每种数据增强采用的概率。aug_prob默认是0.4.由于tia数据增强特殊性,默认不采用,可以通过添加use_tia设置,使tia数据增强生效。详细设置可以参考[ISSUE 1744](https://github.com/PaddlePaddle/PaddleOCR/issues/1744)。 +**A**:可以参考[配置文件](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)在Train['dataset']['transforms']添加RecAug字段,使数据增强生效。可以通过添加对aug_prob设置,表示每种数据增强采用的概率。aug_prob默认是0.4。详细设置可以参考[ISSUE 1744](https://github.com/PaddlePaddle/PaddleOCR/issues/1744)。 #### Q: 训练过程中,训练程序意外退出/挂起,应该如何解决? diff --git a/ppocr/data/imaug/__init__.py b/ppocr/data/imaug/__init__.py index 548832fb0d..f0fd578f61 100644 --- a/ppocr/data/imaug/__init__.py +++ b/ppocr/data/imaug/__init__.py @@ -22,7 +22,7 @@ from .make_shrink_map import MakeShrinkMap from .random_crop_data import EastRandomCropData, RandomCropImgMask from .make_pse_gt import MakePseGt -from .rec_img_aug import RecAug, RecConAug, RecResizeImg, ClsResizeImg, \ +from .rec_img_aug import BaseDataAugmentation, RecAug, RecConAug, RecResizeImg, ClsResizeImg, \ SRNRecResizeImg, NRTRRecResizeImg, SARRecResizeImg, PRENResizeImg from .ssl_img_aug import SSLRotateResize from .randaugment import RandAugment diff --git a/ppocr/data/imaug/rec_img_aug.py b/ppocr/data/imaug/rec_img_aug.py index 7483dffe5b..67b92d71bf 100644 --- a/ppocr/data/imaug/rec_img_aug.py +++ b/ppocr/data/imaug/rec_img_aug.py @@ -22,13 +22,74 @@ from .text_image_aug import tia_perspective, tia_stretch, tia_distort class RecAug(object): - def __init__(self, use_tia=True, aug_prob=0.4, **kwargs): - self.use_tia = use_tia - self.aug_prob = aug_prob + def __init__(self, + tia_prob=True, + crop_prob=0.4, + reverse_prob=0.4, + noise_prob=0.4, + jitter_prob=0.4, + blur_prob=0.4, + hsv_aug_prob=0.4, + **kwargs): + self.tia_prob = tia_prob + self.bda = BaseDataAugmentation(crop_prob, reverse_prob, noise_prob, + jitter_prob, blur_prob, hsv_aug_prob) def __call__(self, data): img = data['image'] - img = warp(img, 10, self.use_tia, self.aug_prob) + h, w, _ = img.shape + + # tia + if random.random() <= self.tia_prob: + if h >= 20 and w >= 20: + img = tia_distort(img, random.randint(3, 6)) + img = tia_stretch(img, random.randint(3, 6)) + img = tia_perspective(img) + + # bda + data['image'] = img + data = self.bda(data) + return data + + +class BaseDataAugmentation(object): + def __init__(self, + crop_prob=0.4, + reverse_prob=0.4, + noise_prob=0.4, + jitter_prob=0.4, + blur_prob=0.4, + hsv_aug_prob=0.4, + **kwargs): + self.crop_prob = crop_prob + self.reverse_prob = reverse_prob + self.noise_prob = noise_prob + self.jitter_prob = jitter_prob + self.blur_prob = blur_prob + self.hsv_aug_prob = hsv_aug_prob + + def __call__(self, data): + img = data['image'] + h, w, _ = img.shape + + if random.random() <= self.crop_prob and h >= 20 and w >= 20: + img = get_crop(img) + + if random.random() <= self.blur_prob: + img = blur(img) + + if random.random() <= self.hsv_aug_prob: + img = hsv_aug(img) + + if random.random() <= self.jitter_prob: + img = jitter(img) + + if random.random() <= self.noise_prob: + img = add_gasuss_noise(img) + + if random.random() <= self.reverse_prob: + img = 255 - img + data['image'] = img return data @@ -359,7 +420,7 @@ def flag(): return 1 if random.random() > 0.5000001 else -1 -def cvtColor(img): +def hsv_aug(img): """ cvtColor """ @@ -427,50 +488,6 @@ def get_crop(image): return crop_img -class Config: - """ - Config - """ - - def __init__(self, use_tia): - self.anglex = random.random() * 30 - self.angley = random.random() * 15 - self.anglez = random.random() * 10 - self.fov = 42 - self.r = 0 - self.shearx = random.random() * 0.3 - self.sheary = random.random() * 0.05 - self.borderMode = cv2.BORDER_REPLICATE - self.use_tia = use_tia - - def make(self, w, h, ang): - """ - make - """ - self.anglex = random.random() * 5 * flag() - self.angley = random.random() * 5 * flag() - self.anglez = -1 * random.random() * int(ang) * flag() - self.fov = 42 - self.r = 0 - self.shearx = 0 - self.sheary = 0 - self.borderMode = cv2.BORDER_REPLICATE - self.w = w - self.h = h - - self.perspective = self.use_tia - self.stretch = self.use_tia - self.distort = self.use_tia - - self.crop = True - self.affine = False - self.reverse = True - self.noise = True - self.jitter = True - self.blur = True - self.color = True - - def rad(x): """ rad @@ -554,48 +571,3 @@ def get_warpAffine(config): rz = np.array([[np.cos(rad(anglez)), np.sin(rad(anglez)), 0], [-np.sin(rad(anglez)), np.cos(rad(anglez)), 0]], np.float32) return rz - - -def warp(img, ang, use_tia=True, prob=0.4): - """ - warp - """ - h, w, _ = img.shape - config = Config(use_tia=use_tia) - config.make(w, h, ang) - new_img = img - - if config.distort: - img_height, img_width = img.shape[0:2] - if random.random() <= prob and img_height >= 20 and img_width >= 20: - new_img = tia_distort(new_img, random.randint(3, 6)) - - if config.stretch: - img_height, img_width = img.shape[0:2] - if random.random() <= prob and img_height >= 20 and img_width >= 20: - new_img = tia_stretch(new_img, random.randint(3, 6)) - - if config.perspective: - if random.random() <= prob: - new_img = tia_perspective(new_img) - - if config.crop: - img_height, img_width = img.shape[0:2] - if random.random() <= prob and img_height >= 20 and img_width >= 20: - new_img = get_crop(new_img) - - if config.blur: - if random.random() <= prob: - new_img = blur(new_img) - if config.color: - if random.random() <= prob: - new_img = cvtColor(new_img) - if config.jitter: - new_img = jitter(new_img) - if config.noise: - if random.random() <= prob: - new_img = add_gasuss_noise(new_img) - if config.reverse: - if random.random() <= prob: - new_img = 255 - new_img - return new_img From 32bcea9c1c72c7324371fcb59c9e56ceff78d789 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 30 May 2022 16:47:12 +0800 Subject: [PATCH 053/129] fix params error --- ppocr/data/imaug/rec_img_aug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppocr/data/imaug/rec_img_aug.py b/ppocr/data/imaug/rec_img_aug.py index 67b92d71bf..32de2b3fc3 100644 --- a/ppocr/data/imaug/rec_img_aug.py +++ b/ppocr/data/imaug/rec_img_aug.py @@ -23,7 +23,7 @@ from .text_image_aug import tia_perspective, tia_stretch, tia_distort class RecAug(object): def __init__(self, - tia_prob=True, + tia_prob=0.4, crop_prob=0.4, reverse_prob=0.4, noise_prob=0.4, From e2b2f33092874afe860b324450b49ea8bd8bc5f4 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 30 May 2022 09:25:21 +0000 Subject: [PATCH 054/129] update some note --- deploy/cpp_infer/readme.md | 2 +- deploy/cpp_infer/readme_ch.md | 2 +- doc/doc_ch/quickstart.md | 2 +- doc/doc_en/quickstart_en.md | 2 +- paddleocr.py | 8 +++++++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/deploy/cpp_infer/readme.md b/deploy/cpp_infer/readme.md index 942a633fd3..a87db7e659 100644 --- a/deploy/cpp_infer/readme.md +++ b/deploy/cpp_infer/readme.md @@ -208,7 +208,7 @@ Execute the built executable file: ./build/ppocr [--param1] [--param2] [...] ``` -**Note**:ppocr uses the `PP-OCRv3` model by default, and the input shape used by the recognition model is `3, 48, 320`, if you do not use the default `PP-OCRv3` model, you should add the parameter `--rec_img_h=32`. +**Note**:ppocr uses the `PP-OCRv3` model by default, and the input shape used by the recognition model is `3, 48, 320`, if you want to use the old version model, you should add the parameter `--rec_img_h=32`. Specifically, diff --git a/deploy/cpp_infer/readme_ch.md b/deploy/cpp_infer/readme_ch.md index 4a79f978fb..8c334851c0 100644 --- a/deploy/cpp_infer/readme_ch.md +++ b/deploy/cpp_infer/readme_ch.md @@ -213,7 +213,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir 本demo支持系统串联调用,也支持单个功能的调用,如,只使用检测或识别功能。 -**注意** ppocr默认使用`PP-OCRv3`模型,识别模型使用的输入shape为`3,48,320`, 如果不使用默认的`PP-OCRv3`模型,则需要设置参数`--rec_img_h=32`。 +**注意** ppocr默认使用`PP-OCRv3`模型,识别模型使用的输入shape为`3,48,320`, 如需使用旧版本的PP-OCR模型,则需要设置参数`--rec_img_h=32`。 运行方式: diff --git a/doc/doc_ch/quickstart.md b/doc/doc_ch/quickstart.md index d2c2f288b0..e425cdd8a8 100644 --- a/doc/doc_ch/quickstart.md +++ b/doc/doc_ch/quickstart.md @@ -106,7 +106,7 @@ paddleocr默认使用PP-OCRv3模型(`--ocr_version PP-OCRv3`),如需使用其 | 版本名称 | 版本说明 | | --- | --- | | PP-OCRv3 | 支持中、英文检测和识别,方向分类器,支持多语种识别 | -| PP-OCRv2 | 仅支持中英文的检测和识别 | +| PP-OCRv2 | 支持中英文的检测和识别,方向分类器,多语言暂未更新 | | PP-OCR | 支持中、英文检测和识别,方向分类器,支持多语种识别 | 如需新增自己训练的模型,可以在[paddleocr](../../paddleocr.py)中增加模型链接和字段,重新编译即可。 diff --git a/doc/doc_en/quickstart_en.md b/doc/doc_en/quickstart_en.md index f0e41e313a..c678dc4762 100644 --- a/doc/doc_en/quickstart_en.md +++ b/doc/doc_en/quickstart_en.md @@ -124,7 +124,7 @@ paddleocr uses the PP-OCRv3 model by default(`--ocr_version PP-OCRv3`). If you w | version name | description | | --- | --- | | PP-OCRv3 | support Chinese and English detection and recognition, direction classifier, support multilingual recognition | -| PP-OCRv2 | only supports Chinese and English detection and recognition | +| PP-OCRv2 | only supports Chinese and English detection and recognition, direction classifier, multilingual model is not updated | | PP-OCR | support Chinese and English detection and recognition, direction classifier, support multilingual recognition | If you want to add your own trained model, you can add model links and keys in [paddleocr](../../paddleocr.py) and recompile. diff --git a/paddleocr.py b/paddleocr.py index a1265f79de..470dc60da3 100644 --- a/paddleocr.py +++ b/paddleocr.py @@ -154,7 +154,13 @@ MODEL_URLS = { 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar', 'dict_path': './ppocr/utils/ppocr_keys_v1.txt' } - } + }, + 'cls': { + 'ch': { + 'url': + 'https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar', + } + }, }, 'PP-OCR': { 'det': { From eee786e51cadcac7f37cd1876c06a29d8a6a3881 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 30 May 2022 11:21:17 +0000 Subject: [PATCH 055/129] add KL PACT --- test_tipc/common_func.sh | 5 +++-- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 8 ++++---- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 10 +++++----- .../ch_PP-OCRv2_rec_PACT/train_infer_python.txt | 2 +- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 8 ++++---- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 10 +++++----- .../ch_PP-OCRv3_rec_PACT/train_infer_python.txt | 2 +- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 6 +++--- .../train_infer_python.txt | 2 +- ...ux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 8 ++++---- 10 files changed, 31 insertions(+), 30 deletions(-) diff --git a/test_tipc/common_func.sh b/test_tipc/common_func.sh index 85dfe21725..f7d8a1e04a 100644 --- a/test_tipc/common_func.sh +++ b/test_tipc/common_func.sh @@ -57,10 +57,11 @@ function status_check(){ last_status=$1 # the exit code run_command=$2 run_log=$3 + model_name=$4 if [ $last_status -eq 0 ]; then - echo -e "\033[33m Run successfully with command - ${run_command}! \033[0m" | tee -a ${run_log} + echo -e "\033[33m Run successfully with command - ${model_name} - ${run_command}! \033[0m" | tee -a ${run_log} else - echo -e "\033[33m Run failed with command - ${run_command}! \033[0m" | tee -a ${run_log} + echo -e "\033[33m Run failed with command - ${model_name} - ${run_command}! \033[0m" | tee -a ${run_log} fi } diff --git a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 1aad65b687..ccc9e5ced0 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -1,5 +1,5 @@ ===========================kl_quant_params=========================== -model_name:PPOCRv2_ocr_det_kl +model_name:ch_PP-OCRv2_det_KL python:python3.7 Global.pretrained_model:null Global.save_inference_dir:null @@ -8,10 +8,10 @@ infer_export:deploy/slim/quantization/quant_kl.py -c configs/det/ch_PP-OCRv2/ch_ infer_quant:True inference:tools/infer/predict_det.py --use_gpu:False|True ---enable_mkldnn:True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 083a3ae26e..c30e0858ef 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -1,17 +1,17 @@ ===========================kl_quant_params=========================== -model_name:PPOCRv2_ocr_rec_kl +model_name:ch_PP-OCRv2_rec_KL python:python3.7 Global.pretrained_model:null Global.save_inference_dir:null infer_model:./inference/ch_PP-OCRv2_rec_infer/ infer_export:deploy/slim/quantization/quant_kl.py -c test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml -o infer_quant:True -inference:tools/infer/predict_rec.py +inference:tools/infer/predict_rec.py --rec_image_shape="3,32,320" --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True +--use_tensorrt:False --precision:int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt index 4168326817..0ac75eff07 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=50 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:pretrain_models/ch_PP-OCRv2_rec_train/best_accuracy diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index e4a3aa6c61..c27e08a640 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -1,5 +1,5 @@ ===========================kl_quant_params=========================== -model_name:PPOCRv3_ocr_det_kl +model_name:ch_PP-OCRv3_det_KL python:python3.7 Global.pretrained_model:null Global.save_inference_dir:null @@ -8,10 +8,10 @@ infer_export:deploy/slim/quantization/quant_kl.py -c configs/det/ch_PP-OCRv3/ch_ infer_quant:True inference:tools/infer/predict_det.py --use_gpu:False|True ---enable_mkldnn:True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 51ad29a4ed..d1a8c7c001 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -1,17 +1,17 @@ ===========================kl_quant_params=========================== -model_name:PPOCRv3_ocr_rec_kl +model_name:ch_PP-OCRv3_rec_KL python:python3.7 -Global.pretrained_model:null +Global.pretrained_model: Global.save_inference_dir:null infer_model:./inference/ch_PP-OCRv3_rec_infer/ infer_export:deploy/slim/quantization/quant_kl.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o infer_quant:True inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True +--use_tensorrt:False --precision:int8 --rec_model_dir: --image_dir:./inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt index f26b86290a..24469a91cf 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:fp32 -Global.epoch_num:lite_train_lite_infer=6|whole_train_whole_infer=50 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 1039dcad06..2bdec84883 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -8,10 +8,10 @@ infer_export:deploy/slim/quantization/quant_kl.py -c configs/det/ch_ppocr_v2.0/c infer_quant:True inference:tools/infer/predict_det.py --use_gpu:False|True ---enable_mkldnn:True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt index 522f30d14b..04c8d0e194 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=20|whole_train_whole_infer=50 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 4b77994f3f..f63fe4c2bb 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -6,12 +6,12 @@ Global.save_inference_dir:null infer_model:./inference/ch_ppocr_mobile_v2.0_rec_infer/ infer_export:deploy/slim/quantization/quant_kl.py -c test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/rec_chinese_lite_train_v2.0.yml -o infer_quant:True -inference:tools/infer/predict_rec.py +inference:tools/infer/predict_rec.py --rec_image_shape="3,32,320" --use_gpu:False|True ---enable_mkldnn:True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:int8 --rec_model_dir: --image_dir:./inference/rec_inference From 0ac032ff1c238ccceeb2b128fd5a6dd0a378f146 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 30 May 2022 11:24:35 +0000 Subject: [PATCH 056/129] add KL PACT --- ppstructure/table/predict_table.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ppstructure/table/predict_table.py b/ppstructure/table/predict_table.py index d7d1760d35..aa05459589 100644 --- a/ppstructure/table/predict_table.py +++ b/ppstructure/table/predict_table.py @@ -244,13 +244,11 @@ def main(args): logger.info("Predict time : {:.3f}s".format(elapse)) if args.benchmark: text_sys.autolog.report() - print('ok') if __name__ == "__main__": args = parse_args() if args.use_mp: - print('mp') p_list = [] total_process_num = args.total_process_num for process_id in range(total_process_num): From 7379f612ec9b8d5e7d01b4e798837c12480e8491 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Tue, 31 May 2022 14:51:04 +0800 Subject: [PATCH 057/129] Update PP-OCRv3_introduction_en.md --- doc/doc_en/PP-OCRv3_introduction_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doc_en/PP-OCRv3_introduction_en.md b/doc/doc_en/PP-OCRv3_introduction_en.md index 2874703466..481e0b8174 100644 --- a/doc/doc_en/PP-OCRv3_introduction_en.md +++ b/doc/doc_en/PP-OCRv3_introduction_en.md @@ -100,7 +100,7 @@ Considering that the features of some channels will be suppressed if the convolu The recognition module of PP-OCRv3 is optimized based on the text recognition algorithm [SVTR](https://arxiv.org/abs/2205.00159). RNN is abandoned in SVTR, and the context information of the text line image is more effectively mined by introducing the Transformers structure, thereby improving the text recognition ability. -The recognition accuracy of SVTR_inty outperforms PP-OCRv2 recognition model by 5.3%, while the prediction speed nearly 11 times slower. It takes nearly 100ms to predict a text line on CPU. Therefore, as shown in the figure below, PP-OCRv3 adopts the following six optimization strategies to accelerate the recognition model. +The recognition accuracy of SVTR_tiny outperforms PP-OCRv2 recognition model by 5.3%, while the prediction speed nearly 11 times slower. It takes nearly 100ms to predict a text line on CPU. Therefore, as shown in the figure below, PP-OCRv3 adopts the following six optimization strategies to accelerate the recognition model.
From c367e4159a37e1901d2197243d70b6196d8faa15 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Tue, 31 May 2022 15:36:04 +0800 Subject: [PATCH 058/129] update doc for issues --- deploy/cpp_infer/src/ocr_rec.cpp | 4 +++- doc/doc_ch/FAQ.md | 7 +++++++ doc/doc_ch/recognition.md | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp index 3438d4074e..0f90ddfab4 100644 --- a/deploy/cpp_infer/src/ocr_rec.cpp +++ b/deploy/cpp_infer/src/ocr_rec.cpp @@ -83,7 +83,7 @@ void CRNNRecognizer::Run(std::vector img_list, int out_num = std::accumulate(predict_shape.begin(), predict_shape.end(), 1, std::multiplies()); predict_batch.resize(out_num); - + // predict_batch is the result of Last FC with softmax output_t->CopyToCpu(predict_batch.data()); auto inference_end = std::chrono::steady_clock::now(); inference_diff += inference_end - inference_start; @@ -98,9 +98,11 @@ void CRNNRecognizer::Run(std::vector img_list, float max_value = 0.0f; for (int n = 0; n < predict_shape[1]; n++) { + // get idx argmax_idx = int(Utility::argmax( &predict_batch[(m * predict_shape[1] + n) * predict_shape[2]], &predict_batch[(m * predict_shape[1] + n + 1) * predict_shape[2]])); + // get score max_value = float(*std::max_element( &predict_batch[(m * predict_shape[1] + n) * predict_shape[2]], &predict_batch[(m * predict_shape[1] + n + 1) * predict_shape[2]])); diff --git a/doc/doc_ch/FAQ.md b/doc/doc_ch/FAQ.md index 2dad829284..a4437b8b78 100644 --- a/doc/doc_ch/FAQ.md +++ b/doc/doc_ch/FAQ.md @@ -720,6 +720,13 @@ C++TensorRT预测需要使用支持TRT的预测库并在编译时打开[-DWITH_T 注:建议使用TensorRT大于等于6.1.0.5以上的版本。 +#### Q: 为什么识别模型做预测的时候,预测图片的数量数量还会影响预测的精度 +**A**: 推理时识别模型默认的batch_size=6, 如预测图片长度变化大,可能影响预测效果。如果出现上述问题可在推理的时候设置识别bs=1,命令如下: + +``` +python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/ch/word_4.jpg" --rec_model_dir="./ch_PP-OCRv3_rec_infer/" --rec_batch_num=1 +``` + ### 2.13 推理部署 diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md index 8457df69ff..5134422417 100644 --- a/doc/doc_ch/recognition.md +++ b/doc/doc_ch/recognition.md @@ -217,6 +217,30 @@ python3 tools/train.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.pre python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.pretrained_model=./pretrain_models/en_PP-OCRv3_rec_train/best_accuracy ``` +正常启动训练后,会看到以下log输出: + +``` +[2022/02/22 07:58:05] root INFO: epoch: [1/800], iter: 10, lr: 0.000000, loss: 0.754281, acc: 0.000000, norm_edit_dis: 0.000008, reader_cost: 0.55541 s, batch_cost: 0.91654 s, samples: 1408, ips: 153.62133 +[2022/02/22 07:58:13] root INFO: epoch: [1/800], iter: 20, lr: 0.000001, loss: 0.924677, acc: 0.000000, norm_edit_dis: 0.000008, reader_cost: 0.00236 s, batch_cost: 0.28528 s, samples: 1280, ips: 448.68599 +[2022/02/22 07:58:23] root INFO: epoch: [1/800], iter: 30, lr: 0.000002, loss: 0.967231, acc: 0.000000, norm_edit_dis: 0.000008, reader_cost: 0.14527 s, batch_cost: 0.42714 s, samples: 1280, ips: 299.66507 +[2022/02/22 07:58:31] root INFO: epoch: [1/800], iter: 40, lr: 0.000003, loss: 0.895318, acc: 0.000000, norm_edit_dis: 0.000008, reader_cost: 0.00173 s, batch_cost: 0.27719 s, samples: 1280, ips: 461.77252 +``` + +log 中自动打印如下信息: + +| 字段 | 含义 | +| :----: | :------: | +| epoch | 当前迭代轮次 | +| iter | 当前迭代次数 | +| lr | 当前学习率 | +| loss | 当前损失函数 | +| acc | 当前batch的准确率 | +| norm_edit_dis | 当前 batch 的编辑距离 | +| reader_cost | 当前 batch 数据处理耗时 | +| batch_cost | 当前 batch 总耗时 | +| samples | 当前 batch 内的样本数 | +| ips | 每秒处理图片的数量 | + PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml` 中修改 `eval_batch_step` 设置评估频率,默认每500个iter评估一次。评估过程中默认将最佳acc模型,保存为 `output/en_PP-OCRv3_rec/best_accuracy` 。 From 43c2e725450b88d8301786358e886621e67d70c9 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 31 May 2022 08:24:17 +0000 Subject: [PATCH 059/129] fix paddle2oonx tipc long cost time --- ...del_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt | 2 +- ...del_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt | 2 +- ...del_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt | 2 +- ...del_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index fad9820a12..24eb620eeb 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -14,4 +14,4 @@ inference:tools/infer/predict_system.py --rec_image_shape="3,32,320" --use_gpu:True|False --det_model_dir: --rec_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file +--image_dir:./inference/ch_det_data_50/all-sum-510/00008790.jpg \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index 15237664ac..bf2556ef17 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -14,4 +14,4 @@ inference:tools/infer/predict_system.py --rec_image_shape="3,48,320" --use_gpu:True|False --det_model_dir: --rec_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file +--image_dir:./inference/ch_det_data_50/all-sum-510/00008790.jpg \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index a60c3e9b83..e478896a54 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -14,4 +14,4 @@ inference:tools/infer/predict_system.py --rec_image_shape="3,32,320" --use_gpu:True|False --det_model_dir: --rec_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file +--image_dir:./inference/ch_det_data_50/all-sum-510/00008790.jpg \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt index 574e4f2e86..c8bebf54f2 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_paddle2onnx_python_linux_cpu.txt @@ -14,4 +14,4 @@ inference:tools/infer/predict_det.py --use_gpu:True|False --det_model_dir: --rec_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ \ No newline at end of file +--image_dir:./inference/ch_det_data_50/all-sum-510/00008790.jpg \ No newline at end of file From 300c679b5ca57a5b98b02a4d7de815eab99c5368 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 1 Jun 2022 07:12:26 +0000 Subject: [PATCH 060/129] update_tipc_cpp_infer --- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- ...linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt | 2 +- test_tipc/prepare.sh | 10 ++++------ test_tipc/test_inference_cpp.sh | 6 ++++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index b31e102b62..a0c49a0812 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_PP-OCRv2 use_opencv:True infer_model:./inference/ch_PP-OCRv2_det_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 60f4788370..b1bff00b09 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_PP-OCRv2_rec use_opencv:True infer_model:./inference/ch_PP-OCRv2_rec_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 8f76631aa4..b42ab9db36 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_ppocr_mobile_v2.0 use_opencv:True infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 25b0dcf3c0..480fb16cdd 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_ppocr_mobile_v2.0_rec use_opencv:True infer_model:./inference/ch_ppocr_mobile_v2.0_rec_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index b03130a15f..7c980b2bae 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_ppocr_server_v2.0 use_opencv:True infer_model:./inference/ch_ppocr_server_v2.0_det_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt index 79fee95a1a..cbec272cce 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -3,7 +3,7 @@ model_name:ch_ppocr_server_v2.0_rec use_opencv:True infer_model:./inference/ch_ppocr_server_v2.0_rec_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 501e597b16..4609cc24c1 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -328,7 +328,6 @@ if [ ${MODE} = "klquant_whole_infer" ]; then cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv2_rec_infer.tar && cd ../ fi if [ ${model_name} = "ch_PP-OCRv3_rec_KL" ]; then - # TODO check model link wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate @@ -341,7 +340,6 @@ if [ ${MODE} = "klquant_whole_infer" ]; then cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ fi if [ ${model_name} = "ch_PP-OCRv3_det_KL" ]; then - # TODO check model link wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ @@ -417,9 +415,9 @@ if [ ${MODE} = "serving_infer" ];then IFS='|' array=(${python_name_list}) python_name=${array[0]} - # ${python_name} -m pip install paddle-serving-server-gpu==0.8.3.post101 - # ${python_name} -m pip install paddle_serving_client==0.8.3 - # ${python_name} -m pip install paddle-serving-app==0.8.3 + ${python_name} -m pip install paddle-serving-server-gpu==0.8.3.post101 + ${python_name} -m pip install paddle_serving_client==0.8.3 + ${python_name} -m pip install paddle-serving-app==0.8.3 # wget model if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate @@ -447,7 +445,7 @@ if [ ${MODE} = "paddle2onnx_infer" ];then # prepare serving env python_name=$(func_parser_value "${lines[2]}") ${python_name} -m pip install paddle2onnx - ${python_name} -m pip install onnxruntime==1.4.0 + ${python_name} -m pip install onnxruntime # wget model if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate diff --git a/test_tipc/test_inference_cpp.sh b/test_tipc/test_inference_cpp.sh index d759d2858e..c0c7c18a38 100644 --- a/test_tipc/test_inference_cpp.sh +++ b/test_tipc/test_inference_cpp.sh @@ -189,6 +189,9 @@ else wget -nc $PADDLEInfer --no-check-certificate fi tar zxf paddle_inference.tgz + if [ ! -d "paddle_inference" ]; then + ln -s paddle_inference_install_dir paddle_inference + fi echo "################### download paddle inference finished ###################" fi LIB_DIR=$(pwd)/paddle_inference/ @@ -218,11 +221,10 @@ echo "################### build PaddleOCR demo finished ###################" # set cuda device GPUID=$2 if [ ${#GPUID} -le 0 ];then - env=" " + env="export CUDA_VISIBLE_DEVICES=0" else env="export CUDA_VISIBLE_DEVICES=${GPUID}" fi -set CUDA_VISIBLE_DEVICES eval $env From ef8b330a6db3b56e947b8716c576d33ee53c83a0 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 1 Jun 2022 07:20:14 +0000 Subject: [PATCH 061/129] update_tipc_cpp_infer --- test_tipc/prepare.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 4609cc24c1..6ef7e847bd 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -415,9 +415,9 @@ if [ ${MODE} = "serving_infer" ];then IFS='|' array=(${python_name_list}) python_name=${array[0]} - ${python_name} -m pip install paddle-serving-server-gpu==0.8.3.post101 - ${python_name} -m pip install paddle_serving_client==0.8.3 - ${python_name} -m pip install paddle-serving-app==0.8.3 + ${python_name} -m pip install paddle-serving-server-gpu + ${python_name} -m pip install paddle_serving_client + ${python_name} -m pip install paddle-serving-app # wget model if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate From 41a2e1fa299abc5d4deb975615225b08104f75e7 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 1 Jun 2022 09:28:54 +0000 Subject: [PATCH 062/129] add python serving tipc --- deploy/pdserving/pipeline_http_client.py | 22 +- ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 25 +- ...al_normal_serving_python_linux_gpu_cpu.txt | 25 +- ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 27 ++- ...al_normal_serving_python_linux_gpu_cpu.txt | 31 ++- ...al_normal_serving_python_linux_gpu_cpu.txt | 23 ++ ...al_normal_serving_python_linux_gpu_cpu.txt | 31 ++- ...al_normal_serving_python_linux_gpu_cpu.txt | 31 ++- test_tipc/test_serving.sh | 191 --------------- test_tipc/test_serving_python.sh | 224 ++++++++++++++++++ 15 files changed, 481 insertions(+), 264 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt delete mode 100644 test_tipc/test_serving.sh create mode 100644 test_tipc/test_serving_python.sh diff --git a/deploy/pdserving/pipeline_http_client.py b/deploy/pdserving/pipeline_http_client.py index a1226a9469..0a86a63987 100644 --- a/deploy/pdserving/pipeline_http_client.py +++ b/deploy/pdserving/pipeline_http_client.py @@ -36,11 +36,27 @@ def cv2_to_base64(image): return base64.b64encode(image).decode('utf8') +def _check_image_file(path): + img_end = {'jpg', 'bmp', 'png', 'jpeg', 'rgb', 'tif', 'tiff', 'gif'} + return any([path.lower().endswith(e) for e in img_end]) + + url = "http://127.0.0.1:9998/ocr/prediction" test_img_dir = args.image_dir -for idx, img_file in enumerate(os.listdir(test_img_dir)): - with open(os.path.join(test_img_dir, img_file), 'rb') as file: +test_img_list = [] +if os.path.isfile(test_img_dir) and _check_image_file(test_img_dir): + test_img_list.append(test_img_dir) +elif os.path.isdir(test_img_dir): + for single_file in os.listdir(test_img_dir): + file_path = os.path.join(test_img_dir, single_file) + if os.path.isfile(file_path) and _check_image_file(file_path): + test_img_list.append(file_path) +if len(test_img_list) == 0: + raise Exception("not found any img file in {}".format(test_img_dir)) + +for idx, img_file in enumerate(test_img_list): + with open(img_file, 'rb') as file: image_data1 = file.read() # print file name print('{}{}{}'.format('*' * 10, img_file, '*' * 10)) @@ -70,4 +86,4 @@ for idx, img_file in enumerate(os.listdir(test_img_dir)): print( "For details about error message, see PipelineServingLogs/pipeline.log" ) -print("==> total number of test imgs: ", len(os.listdir(test_img_dir))) +print("==> total number of test imgs: ", len(test_img_list)) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..4ad64db03c --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_client/ +serving_dir:./deploy/pdserving +web_service:web_service.py --config=config.yml --opt op.det.concurrency="1" op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..587a7d7ea6 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_det +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..e9e90d372e --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_rec +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv2_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..6f699ef5c0 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_client/ +serving_dir:./deploy/pdserving +web_service:web_service.py --config=config.yml --opt op.det.concurrency="1" op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index 624b13e0d5..6e2ec22cbd 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_det_v3 +model_name:ch_PP-OCRv3_det python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_PP-OCRv3_det_infer/ +--det_dirname:./inference/ch_PP-OCRv3_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_det_v3_serving/ ---serving_client:./deploy/pdserving/ppocr_det_v3_client/ +--det_serving_server:./deploy/pdserving/ppocr_det_v3_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null serving_dir:./deploy/pdserving web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" op.det.local_service_conf.devices:gpu|null -op.det.local_service_conf.use_mkldnn:True|False -op.det.local_service_conf.thread_num:1|6 -op.det.local_service_conf.use_trt:False|True -op.det.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py ---image_dir:../../doc/imgs +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index 89bde9c8ce..f01db2e950 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_rec_v3 +model_name:ch_PP-OCRv3_rec python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_PP-OCRv3_rec_infer/ +--det_dirname:null --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_rec_v3_serving/ ---serving_client:./deploy/pdserving/ppocr_rec_v3_client/ +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv3_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_client/ serving_dir:./deploy/pdserving web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" -op.rec.local_service_conf.devices:gpu|null -op.rec.local_service_conf.use_mkldnn:False -op.rec.local_service_conf.thread_num:1|6 -op.rec.local_service_conf.use_trt:False|True -op.rec.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False --image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..842c934017 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_client/ +serving_dir:./deploy/pdserving +web_service:web_service.py --config=config.yml --opt op.det.concurrency="1" op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index ed72889970..c9dd5ad920 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_det_mobile -python:python3.7|cpp +model_name:ch_ppocr_mobile_v2.0_det +python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_det_mobile_2.0_serving/ ---serving_client:./deploy/pdserving/ppocr_det_mobile_2.0_client/ +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null serving_dir:./deploy/pdserving web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" op.det.local_service_conf.devices:gpu|null -op.det.local_service_conf.use_mkldnn:True|False -op.det.local_service_conf.thread_num:1|6 -op.det.local_service_conf.use_trt:False|True -op.det.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py ---image_dir:../../doc/imgs +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index f890eff469..c0c5291cc4 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_rec_mobile -python:python3.7|cpp +model_name:ch_ppocr_mobile_v2.0_rec +python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--det_dirname:null --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_rec_mobile_2.0_serving/ ---serving_client:./deploy/pdserving/ppocr_rec_mobile_2.0_client/ +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_client/ serving_dir:./deploy/pdserving -web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency=1 -op.rec.local_service_conf.devices:"0"|null -op.rec.local_service_conf.use_mkldnn:True|False -op.rec.local_service_conf.thread_num:1|6 -op.rec.local_service_conf.use_trt:False|True -op.rec.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py ---image_dir:../../doc/imgs_words_en \ No newline at end of file +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..8853e709d4 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_server_v2.0 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_server_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_server_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_server_client/ +--rec_dirname:./inference/ch_ppocr_server_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_server_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_server_client/ +serving_dir:./deploy/pdserving +web_service:web_service.py --config=config.yml --opt op.det.concurrency="1" op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index ec54646046..018dd1a227 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_det_server -python:python3.7|cpp +model_name:ch_ppocr_server_v2.0_det +python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_ppocr_server_v2.0_det_infer/ +--det_dirname:./inference/ch_ppocr_server_v2.0_det_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_det_server_2.0_serving/ ---serving_client:./deploy/pdserving/ppocr_det_server_2.0_client/ +--det_serving_server:./deploy/pdserving/ppocr_det_server_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_server_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null serving_dir:./deploy/pdserving -web_service:web_service_det.py --config=config.yml --opt op.det.concurrency=1 -op.det.local_service_conf.devices:"0"|null -op.det.local_service_conf.use_mkldnn:True|False -op.det.local_service_conf.thread_num:1|6 -op.det.local_service_conf.use_trt:False|True -op.det.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py ---image_dir:../../doc/imgs \ No newline at end of file +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt index d72abc6054..7f456320b6 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -1,18 +1,23 @@ ===========================serving_params=========================== -model_name:ocr_rec_server -python:python3.7|cpp +model_name:ch_ppocr_server_v2.0_rec +python:python3.7 trans_model:-m paddle_serving_client.convert ---dirname:./inference/ch_ppocr_server_v2.0_rec_infer/ +--det_dirname:null --model_filename:inference.pdmodel --params_filename:inference.pdiparams ---serving_server:./deploy/pdserving/ppocr_rec_server_2.0_serving/ ---serving_client:./deploy/pdserving/ppocr_rec_server_2.0_client/ +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_ppocr_server_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_server_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_server_client/ serving_dir:./deploy/pdserving -web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency=1 -op.rec.local_service_conf.devices:"0"|null -op.rec.local_service_conf.use_mkldnn:True|False -op.rec.local_service_conf.thread_num:1|6 -op.rec.local_service_conf.use_trt:False|True -op.rec.local_service_conf.precision:fp32|fp16|int8 -pipline:pipeline_rpc_client.py|pipeline_http_client.py ---image_dir:../../doc/imgs_words_en \ No newline at end of file +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/test_serving.sh b/test_tipc/test_serving.sh deleted file mode 100644 index 3a6c88f313..0000000000 --- a/test_tipc/test_serving.sh +++ /dev/null @@ -1,191 +0,0 @@ -#!/bin/bash -source test_tipc/common_func.sh - -FILENAME=$1 -dataline=$(awk 'NR==1, NR==18{print}' $FILENAME) - -# parser params -IFS=$'\n' -lines=(${dataline}) - -# parser serving -model_name=$(func_parser_value "${lines[1]}") -python_list=$(func_parser_value "${lines[2]}") -trans_model_py=$(func_parser_value "${lines[3]}") -infer_model_dir_key=$(func_parser_key "${lines[4]}") -infer_model_dir_value=$(func_parser_value "${lines[4]}") -model_filename_key=$(func_parser_key "${lines[5]}") -model_filename_value=$(func_parser_value "${lines[5]}") -params_filename_key=$(func_parser_key "${lines[6]}") -params_filename_value=$(func_parser_value "${lines[6]}") -serving_server_key=$(func_parser_key "${lines[7]}") -serving_server_value=$(func_parser_value "${lines[7]}") -serving_client_key=$(func_parser_key "${lines[8]}") -serving_client_value=$(func_parser_value "${lines[8]}") -serving_dir_value=$(func_parser_value "${lines[9]}") -web_service_py=$(func_parser_value "${lines[10]}") -web_use_gpu_key=$(func_parser_key "${lines[11]}") -web_use_gpu_list=$(func_parser_value "${lines[11]}") -web_use_mkldnn_key=$(func_parser_key "${lines[12]}") -web_use_mkldnn_list=$(func_parser_value "${lines[12]}") -web_cpu_threads_key=$(func_parser_key "${lines[13]}") -web_cpu_threads_list=$(func_parser_value "${lines[13]}") -web_use_trt_key=$(func_parser_key "${lines[14]}") -web_use_trt_list=$(func_parser_value "${lines[14]}") -web_precision_key=$(func_parser_key "${lines[15]}") -web_precision_list=$(func_parser_value "${lines[15]}") -pipeline_py=$(func_parser_value "${lines[16]}") -image_dir_key=$(func_parser_key "${lines[17]}") -image_dir_value=$(func_parser_value "${lines[17]}") - -LOG_PATH="$(pwd)/test_tipc/output/pdserving/${model_name}" -mkdir -p ${LOG_PATH} -status_log="${LOG_PATH}/results_serving.log" - -function func_serving(){ - IFS='|' - _python=$1 - _script=$2 - _model_dir=$3 - # pdserving - set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") - set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") - set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") - set_serving_server=$(func_set_params "${serving_server_key}" "${serving_server_value}") - set_serving_client=$(func_set_params "${serving_client_key}" "${serving_client_value}") - set_image_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") - python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - cd ${serving_dir_value} - unset https_proxy - unset http_proxy - for python in ${python_list[*]}; do - if [ ${python} = "cpp" ]; then - for use_gpu in ${web_use_gpu_list[*]}; do - if [ ${use_gpu} = "null" ]; then - if [ ${model_name} = "ocr_det_mobile" ]; then - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293" - elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_v3_serving/ ppocr_rec_v3_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293" - fi - eval $web_service_cpp_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${web_service_cpp_cmd}" "${status_log}" - sleep 2s - _save_log_path="${LOG_PATH}/server_infer_cpp_cpu_pipeline_usemkldnn_False_threads_4_batchsize_1.log" - if [ ${model_name} = "ocr_det_mobile" ]; then - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" - elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_v3_client/ ppocr_rec_v3_client/" - fi - eval $pipeline_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${pipeline_cmd}" "${status_log}" - sleep 2s - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 - else - if [ ${model_name} = "ocr_det_mobile" ]; then - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_mobile_2.0_serving/ ppocr_rec_mobile_2.0_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293 --gpu_id=0" - elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then - web_service_cpp_cmd="${python_list[0]} -m paddle_serving_server.serve --model ppocr_det_v3_serving/ ppocr_rec_v3_serving/ --op GeneralDetectionOp GeneralInferOp --port 9293 --gpu_id=0" - fi - eval $web_service_cpp_cmd - sleep 2s - _save_log_path="${LOG_PATH}/server_infer_cpp_cpu_pipeline_usemkldnn_False_threads_4_batchsize_1.log" - if [ ${model_name} = "ocr_det_mobile" ]; then - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_mobile_2.0_client/ ppocr_rec_mobile_2.0_client/" - elif [ ${model_name} = "ocr_det_v3" ] || [ ${model_name} = "ocr_rec_v3" ]; then - pipeline_cmd="${python_list[0]} ocr_cpp_client.py ppocr_det_v3_client/ ppocr_rec_v3_client/" - fi - eval $pipeline_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${pipeline_cmd}" "${status_log}" - sleep 2s - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 - fi - done - else - # python serving - for use_gpu in ${web_use_gpu_list[*]}; do - if [ ${use_gpu} = "null" ]; then - for use_mkldnn in ${web_use_mkldnn_list[*]}; do - for threads in ${web_cpu_threads_list[*]}; do - set_cpu_threads=$(func_set_params "${web_cpu_threads_key}" "${threads}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} &" - eval $web_service_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${web_service_cmd}" "${status_log}" - sleep 2s - for pipeline in ${pipeline_py[*]}; do - _save_log_path="${LOG_PATH}/server_infer_cpu_${pipeline%_client*}_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" - pipeline_cmd="${python} ${pipeline} ${set_image_dir} > ${_save_log_path} 2>&1 " - eval $pipeline_cmd - last_status=${PIPESTATUS[0]} - eval "cat ${_save_log_path}" - status_check $last_status "${pipeline_cmd}" "${status_log}" - sleep 2s - done - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 - done - done - elif [ ${use_gpu} = "gpu" ]; then - for use_trt in ${web_use_trt_list[*]}; do - for precision in ${web_precision_list[*]}; do - if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then - continue - fi - if [[ ${precision} =~ "fp16" || ${precision} =~ "int8" ]] && [ ${use_trt} = "False" ]; then - continue - fi - if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [[ ${_flag_quant} = "True" ]]; then - continue - fi - set_tensorrt=$(func_set_params "${web_use_trt_key}" "${use_trt}") - if [ ${use_trt} = True ]; then - device_type=2 - fi - set_precision=$(func_set_params "${web_precision_key}" "${precision}") - web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} & " - eval $web_service_cmd - last_status=${PIPESTATUS[0]} - status_check $last_status "${web_service_cmd}" "${status_log}" - - sleep 2s - for pipeline in ${pipeline_py[*]}; do - _save_log_path="${LOG_PATH}/server_infer_gpu_${pipeline%_client*}_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" - pipeline_cmd="${python} ${pipeline} ${set_image_dir}> ${_save_log_path} 2>&1" - eval $pipeline_cmd - last_status=${PIPESTATUS[0]} - eval "cat ${_save_log_path}" - status_check $last_status "${pipeline_cmd}" "${status_log}" - sleep 2s - done - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 - done - done - else - echo "Does not support hardware other than CPU and GPU Currently!" - fi - done - fi - done -} - - -#set cuda device -GPUID=$2 -if [ ${#GPUID} -le 0 ];then - env="export CUDA_VISIBLE_DEVICES=0" -else - env="export CUDA_VISIBLE_DEVICES=${GPUID}" -fi -eval $env -echo $env - - -echo "################### run test ###################" - -export Count=0 -IFS="|" -func_serving "${web_service_cmd}" diff --git a/test_tipc/test_serving_python.sh b/test_tipc/test_serving_python.sh new file mode 100644 index 0000000000..4affa417e1 --- /dev/null +++ b/test_tipc/test_serving_python.sh @@ -0,0 +1,224 @@ +#!/bin/bash +source test_tipc/common_func.sh + +function func_parser_model_config(){ + strs=$1 + IFS="/" + array=(${strs}) + tmp=${array[-1]} + echo ${tmp} +} + +FILENAME=$1 +dataline=$(awk 'NR==1, NR==23{print}' $FILENAME) + +# parser params +IFS=$'\n' +lines=(${dataline}) + +# parser serving +model_name=$(func_parser_value "${lines[1]}") +python_list=$(func_parser_value "${lines[2]}") +trans_model_py=$(func_parser_value "${lines[3]}") +det_infer_model_dir_key=$(func_parser_key "${lines[4]}") +det_infer_model_dir_value=$(func_parser_value "${lines[4]}") +model_filename_key=$(func_parser_key "${lines[5]}") +model_filename_value=$(func_parser_value "${lines[5]}") +params_filename_key=$(func_parser_key "${lines[6]}") +params_filename_value=$(func_parser_value "${lines[6]}") +det_serving_server_key=$(func_parser_key "${lines[7]}") +det_serving_server_value=$(func_parser_value "${lines[7]}") +det_serving_client_key=$(func_parser_key "${lines[8]}") +det_serving_client_value=$(func_parser_value "${lines[8]}") +rec_infer_model_dir_key=$(func_parser_key "${lines[9]}") +rec_infer_model_dir_value=$(func_parser_value "${lines[9]}") +rec_serving_server_key=$(func_parser_key "${lines[10]}") +rec_serving_server_value=$(func_parser_value "${lines[10]}") +rec_serving_client_key=$(func_parser_key "${lines[11]}") +rec_serving_client_value=$(func_parser_value "${lines[11]}") +serving_dir_value=$(func_parser_value "${lines[12]}") +web_service_py=$(func_parser_value "${lines[13]}") +web_use_gpu_key=$(func_parser_key "${lines[14]}") +web_use_gpu_list=$(func_parser_value "${lines[14]}") +web_use_mkldnn_key=$(func_parser_key "${lines[15]}") +web_use_mkldnn_list=$(func_parser_value "${lines[15]}") +web_cpu_threads_key=$(func_parser_key "${lines[16]}") +web_cpu_threads_list=$(func_parser_value "${lines[16]}") +web_use_trt_key=$(func_parser_key "${lines[17]}") +web_use_trt_list=$(func_parser_value "${lines[17]}") +web_precision_key=$(func_parser_key "${lines[18]}") +web_precision_list=$(func_parser_value "${lines[18]}") +det_server_key=$(func_parser_key "${lines[19]}") +det_server_value=$(func_parser_model_config "${lines[7]}") +det_client_value=$(func_parser_model_config "${lines[8]}") +rec_server_key=$(func_parser_key "${lines[20]}") +rec_server_value=$(func_parser_model_config "${lines[10]}") +rec_client_value=$(func_parser_model_config "${lines[11]}") +pipeline_py=$(func_parser_value "${lines[21]}") +image_dir_key=$(func_parser_key "${lines[22]}") +image_dir_value=$(func_parser_value "${lines[22]}") + +LOG_PATH="$(pwd)/test_tipc/output/${model_name}/python_serving" +mkdir -p ${LOG_PATH} +status_log="${LOG_PATH}/results_python_serving.log" + +function func_serving(){ + IFS='|' + _python=$1 + _script=$2 + _model_dir=$3 + # pdserving + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + # trans det + set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + # trans rec + set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + # trans det + set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + # trans rec + set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + fi + set_image_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") + python_list=(${python_list}) + + cd ${serving_dir_value} + unset https_proxy + unset http_proxy + python=${python_list[0]} + + # python serving + for use_gpu in ${web_use_gpu_list[*]}; do + if [ ${use_gpu} = "null" ]; then + for use_mkldnn in ${web_use_mkldnn_list[*]}; do + for threads in ${web_cpu_threads_list[*]}; do + set_cpu_threads=$(func_set_params "${web_cpu_threads_key}" "${threads}") + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") + set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} ${set_rec_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_rec_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + fi + sleep 2s + for pipeline in ${pipeline_py[*]}; do + _save_log_path="${LOG_PATH}/server_infer_cpu_${pipeline%_client*}_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" + pipeline_cmd="${python} ${pipeline} ${set_image_dir} > ${_save_log_path} 2>&1 " + eval $pipeline_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${pipeline_cmd}" "${status_log}" "${model_name}" + sleep 2s + done + ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 + done + done + elif [ ${use_gpu} = "gpu" ]; then + for use_trt in ${web_use_trt_list[*]}; do + for precision in ${web_precision_list[*]}; do + if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then + continue + fi + if [[ ${precision} =~ "fp16" || ${precision} =~ "int8" ]] && [ ${use_trt} = "False" ]; then + continue + fi + if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [[ ${_flag_quant} = "True" ]]; then + continue + fi + set_tensorrt=$(func_set_params "${web_use_trt_key}" "${use_trt}") + if [ ${use_trt} = True ]; then + device_type=2 + fi + set_precision=$(func_set_params "${web_precision_key}" "${precision}") + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") + set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} ${set_rec_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_rec_model_config} &" + eval $web_service_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" + fi + sleep 2s + for pipeline in ${pipeline_py[*]}; do + _save_log_path="${LOG_PATH}/server_infer_gpu_${pipeline%_client*}_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" + pipeline_cmd="${python} ${pipeline} ${set_image_dir}> ${_save_log_path} 2>&1" + eval $pipeline_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${pipeline_cmd}" "${status_log}" "${model_name}" + sleep 2s + done + ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 + done + done + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done +} + + +#set cuda device +GPUID=$2 +if [ ${#GPUID} -le 0 ];then + env="export CUDA_VISIBLE_DEVICES=0" +else + env="export CUDA_VISIBLE_DEVICES=${GPUID}" +fi +eval $env +echo $env + + +echo "################### run test ###################" + +export Count=0 +IFS="|" +func_serving "${web_service_cmd}" From 2dbdae6101fb73487eb3d160fea9d1a98cd7568b Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:09:58 +0800 Subject: [PATCH 063/129] [Cherry pick] update python serving for v3 (#6467) * update pipeline to v3 * update pipeline to v3 --- deploy/pdserving/ocr_reader.py | 6 +++--- deploy/pdserving/web_service.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/deploy/pdserving/ocr_reader.py b/deploy/pdserving/ocr_reader.py index 75f0f3d5c3..d488cc0920 100644 --- a/deploy/pdserving/ocr_reader.py +++ b/deploy/pdserving/ocr_reader.py @@ -339,7 +339,7 @@ class CharacterOps(object): class OCRReader(object): def __init__(self, algorithm="CRNN", - image_shape=[3, 32, 320], + image_shape=[3, 48, 320], char_type="ch", batch_num=1, char_dict_path="./ppocr_keys_v1.txt"): @@ -356,7 +356,7 @@ class OCRReader(object): def resize_norm_img(self, img, max_wh_ratio): imgC, imgH, imgW = self.rec_image_shape if self.character_type == "ch": - imgW = int(32 * max_wh_ratio) + imgW = int(imgH * max_wh_ratio) h = img.shape[0] w = img.shape[1] ratio = w / float(h) @@ -377,7 +377,7 @@ class OCRReader(object): def preprocess(self, img_list): img_num = len(img_list) norm_img_batch = [] - max_wh_ratio = 0 + max_wh_ratio = 320/48. for ino in range(img_num): h, w = img_list[ino].shape[0:2] wh_ratio = w * 1.0 / h diff --git a/deploy/pdserving/web_service.py b/deploy/pdserving/web_service.py index f05806ce03..d8491dc572 100644 --- a/deploy/pdserving/web_service.py +++ b/deploy/pdserving/web_service.py @@ -63,7 +63,6 @@ class DetOp(Op): dt_boxes_list = self.post_func(det_out, [ratio_list]) dt_boxes = self.filter_func(dt_boxes_list[0], [self.ori_h, self.ori_w]) out_dict = {"dt_boxes": dt_boxes, "image": self.raw_im} - return out_dict, None, "" @@ -86,7 +85,7 @@ class RecOp(Op): dt_boxes = copy.deepcopy(self.dt_list) feed_list = [] img_list = [] - max_wh_ratio = 0 + max_wh_ratio = 320/48. ## Many mini-batchs, the type of feed_data is list. max_batch_size = 6 # len(dt_boxes) @@ -150,7 +149,8 @@ class RecOp(Op): for i in range(dt_num): text = rec_list[i] dt_box = self.dt_list[i] - result_list.append([text, dt_box.tolist()]) + if text[1] >= 0.5: + result_list.append([text, dt_box.tolist()]) res = {"result": str(result_list)} return res, None, "" From 88fc3318c5381649c651bf54d2193f3096e769ff Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Jun 2022 02:21:02 +0000 Subject: [PATCH 064/129] add cpp serving tipc --- deploy/pdserving/ocr_cpp_client.py | 23 ++- deploy/pdserving/serving_client_conf.prototxt | 16 ++ test_tipc/build_server.sh | 69 +++++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++ test_tipc/test_serving_cpp.sh | 184 ++++++++++++++++++ 8 files changed, 365 insertions(+), 3 deletions(-) create mode 100644 deploy/pdserving/serving_client_conf.prototxt create mode 100644 test_tipc/build_server.sh create mode 100644 test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/test_serving_cpp.sh diff --git a/deploy/pdserving/ocr_cpp_client.py b/deploy/pdserving/ocr_cpp_client.py index 7f9333dd85..92ccb9cd8f 100755 --- a/deploy/pdserving/ocr_cpp_client.py +++ b/deploy/pdserving/ocr_cpp_client.py @@ -30,7 +30,7 @@ client.load_client_config(sys.argv[1:]) client.connect(["127.0.0.1:9293"]) import paddle -test_img_dir = "../../doc/imgs/" +test_img_dir = "../../doc/imgs/1.jpg" ocr_reader = OCRReader(char_dict_path="../../ppocr/utils/ppocr_keys_v1.txt") @@ -40,12 +40,29 @@ def cv2_to_base64(image): 'utf8') #data.tostring()).decode('utf8') -for img_file in os.listdir(test_img_dir): - with open(os.path.join(test_img_dir, img_file), 'rb') as file: +def _check_image_file(path): + img_end = {'jpg', 'bmp', 'png', 'jpeg', 'rgb', 'tif', 'tiff', 'gif'} + return any([path.lower().endswith(e) for e in img_end]) + + +test_img_list = [] +if os.path.isfile(test_img_dir) and _check_image_file(test_img_dir): + test_img_list.append(test_img_dir) +elif os.path.isdir(test_img_dir): + for single_file in os.listdir(test_img_dir): + file_path = os.path.join(test_img_dir, single_file) + if os.path.isfile(file_path) and _check_image_file(file_path): + test_img_list.append(file_path) +if len(test_img_list) == 0: + raise Exception("not found any img file in {}".format(test_img_dir)) + +for img_file in test_img_list: + with open(img_file, 'rb') as file: image_data = file.read() image = cv2_to_base64(image_data) res_list = [] fetch_map = client.predict(feed={"x": image}, fetch=[], batch=True) + print(fetch_map) one_batch_res = ocr_reader.postprocess(fetch_map, with_score=True) for res in one_batch_res: res_list.append(res[0]) diff --git a/deploy/pdserving/serving_client_conf.prototxt b/deploy/pdserving/serving_client_conf.prototxt new file mode 100644 index 0000000000..33960540a2 --- /dev/null +++ b/deploy/pdserving/serving_client_conf.prototxt @@ -0,0 +1,16 @@ +feed_var { + name: "x" + alias_name: "x" + is_lod_tensor: false + feed_type: 20 + shape: 1 +} +fetch_var { + name: "save_infer_model/scale_0.tmp_1" + alias_name: "save_infer_model/scale_0.tmp_1" + is_lod_tensor: false + fetch_type: 1 + shape: 1 + shape: 640 + shape: 640 +} diff --git a/test_tipc/build_server.sh b/test_tipc/build_server.sh new file mode 100644 index 0000000000..3173359785 --- /dev/null +++ b/test_tipc/build_server.sh @@ -0,0 +1,69 @@ +#使用镜像: +#registry.baidubce.com/paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82 + +#编译Serving Server: + +#client和app可以直接使用release版本 + +#server因为加入了自定义OP,需要重新编译 + +apt-get update +apt install -y libcurl4-openssl-dev libbz2-dev +wget https://paddle-serving.bj.bcebos.com/others/centos_ssl.tar && tar xf centos_ssl.tar && rm -rf centos_ssl.tar && mv libcrypto.so.1.0.2k /usr/lib/libcrypto.so.1.0.2k && mv libssl.so.1.0.2k /usr/lib/libssl.so.1.0.2k && ln -sf /usr/lib/libcrypto.so.1.0.2k /usr/lib/libcrypto.so.10 && ln -sf /usr/lib/libssl.so.1.0.2k /usr/lib/libssl.so.10 && ln -sf /usr/lib/libcrypto.so.10 /usr/lib/libcrypto.so && ln -sf /usr/lib/libssl.so.10 /usr/lib/libssl.so + +# 安装go依赖 +rm -rf /usr/local/go +wget -qO- https://paddle-ci.cdn.bcebos.com/go1.17.2.linux-amd64.tar.gz | tar -xz -C /usr/local +export GOROOT=/usr/local/go +export GOPATH=/root/gopath +export PATH=$PATH:$GOPATH/bin:$GOROOT/bin +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@v1.15.2 +go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@v1.15.2 +go install github.com/golang/protobuf/protoc-gen-go@v1.4.3 +go install google.golang.org/grpc@v1.33.0 +go env -w GO111MODULE=auto + +# 下载opencv库 +wget https://paddle-qa.bj.bcebos.com/PaddleServing/opencv3.tar.gz && tar -xvf opencv3.tar.gz && rm -rf opencv3.tar.gz +export OPENCV_DIR=$PWD/opencv3 + +# clone Serving +git clone https://github.com/PaddlePaddle/Serving.git -b develop --depth=1 +cd Serving +export Serving_repo_path=$PWD +git submodule update --init --recursive +python -m pip install -r python/requirements.txt + + +export PYTHON_INCLUDE_DIR=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") +export PYTHON_LIBRARIES=$(python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR'))") +export PYTHON_EXECUTABLE=`which python` + +export CUDA_PATH='/usr/local/cuda' +export CUDNN_LIBRARY='/usr/local/cuda/lib64/' +export CUDA_CUDART_LIBRARY='/usr/local/cuda/lib64/' +export TENSORRT_LIBRARY_PATH='/usr/local/TensorRT6-cuda10.1-cudnn7/targets/x86_64-linux-gnu/' + +# cp 自定义OP代码 +cp -rf ../deploy/pdserving/general_detection_op.cpp ${Serving_repo_path}/core/general-server/op + +# 编译Server, export SERVING_BIN +mkdir server-build-gpu-opencv && cd server-build-gpu-opencv +cmake -DPYTHON_INCLUDE_DIR=$PYTHON_INCLUDE_DIR \ + -DPYTHON_LIBRARIES=$PYTHON_LIBRARIES \ + -DPYTHON_EXECUTABLE=$PYTHON_EXECUTABLE \ + -DCUDA_TOOLKIT_ROOT_DIR=${CUDA_PATH} \ + -DCUDNN_LIBRARY=${CUDNN_LIBRARY} \ + -DCUDA_CUDART_LIBRARY=${CUDA_CUDART_LIBRARY} \ + -DTENSORRT_ROOT=${TENSORRT_LIBRARY_PATH} \ + -DOPENCV_DIR=${OPENCV_DIR} \ + -DWITH_OPENCV=ON \ + -DSERVER=ON \ + -DWITH_GPU=ON .. +make -j32 + +python -m pip install python/dist/paddle* +export SERVING_BIN=$PWD/core/general-server/serving +cd ../../ diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..7aa4a2febe --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:9293 +device:gpu +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..74fffee0f8 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:9293 +device:gpu +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..2542f568b0 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:9293 +device:gpu +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..7087807f36 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_server_v2.0 +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_server_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_server_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_server_client/ +--rec_dirname:./inference/ch_ppocr_server_v2.0_rec_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_server_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_server_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:9293 +device:gpu +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs diff --git a/test_tipc/test_serving_cpp.sh b/test_tipc/test_serving_cpp.sh new file mode 100644 index 0000000000..c9945416b6 --- /dev/null +++ b/test_tipc/test_serving_cpp.sh @@ -0,0 +1,184 @@ +#!/bin/bash +source test_tipc/common_func.sh + +function func_parser_model_config(){ + strs=$1 + IFS="/" + array=(${strs}) + tmp=${array[-1]} + echo ${tmp} +} + +FILENAME=$1 +dataline=$(awk 'NR==1, NR==19{print}' $FILENAME) + +# parser params +IFS=$'\n' +lines=(${dataline}) + +# parser serving +model_name=$(func_parser_value "${lines[1]}") +python_list=$(func_parser_value "${lines[2]}") +trans_model_py=$(func_parser_value "${lines[3]}") +det_infer_model_dir_key=$(func_parser_key "${lines[4]}") +det_infer_model_dir_value=$(func_parser_value "${lines[4]}") +model_filename_key=$(func_parser_key "${lines[5]}") +model_filename_value=$(func_parser_value "${lines[5]}") +params_filename_key=$(func_parser_key "${lines[6]}") +params_filename_value=$(func_parser_value "${lines[6]}") +det_serving_server_key=$(func_parser_key "${lines[7]}") +det_serving_server_value=$(func_parser_value "${lines[7]}") +det_serving_client_key=$(func_parser_key "${lines[8]}") +det_serving_client_value=$(func_parser_value "${lines[8]}") +rec_infer_model_dir_key=$(func_parser_key "${lines[9]}") +rec_infer_model_dir_value=$(func_parser_value "${lines[9]}") +rec_serving_server_key=$(func_parser_key "${lines[10]}") +rec_serving_server_value=$(func_parser_value "${lines[10]}") +rec_serving_client_key=$(func_parser_key "${lines[11]}") +rec_serving_client_value=$(func_parser_value "${lines[11]}") +det_server_value=$(func_parser_model_config "${lines[7]}") +det_client_value=$(func_parser_model_config "${lines[8]}") +rec_server_value=$(func_parser_model_config "${lines[10]}") +rec_client_value=$(func_parser_model_config "${lines[11]}") +serving_dir_value=$(func_parser_value "${lines[12]}") +web_service_py=$(func_parser_value "${lines[13]}") +op_key=$(func_parser_key "${lines[14]}") +op_value=$(func_parser_value "${lines[14]}") +port_key=$(func_parser_key "${lines[15]}") +port_value=$(func_parser_value "${lines[15]}") +device_value=$(func_parser_value "${lines[16]}") +cpp_client_py=$(func_parser_value "${lines[17]}") +image_dir_key=$(func_parser_key "${lines[18]}") +image_dir_value=$(func_parser_value "${lines[18]}") + +LOG_PATH="$(pwd)/test_tipc/output/${model_name}/cpp_serving" +mkdir -p ${LOG_PATH} +status_log="${LOG_PATH}/results_cpp_serving.log" + +function func_serving(){ + IFS='|' + _python=$1 + _script=$2 + _model_dir=$3 + # pdserving + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + # trans det + set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} + # trans rec + set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + # trans det + set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + # trans rec + set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + fi + last_status=${PIPESTATUS[0]} + status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" + set_image_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") + python_list=(${python_list}) + + cd ${serving_dir_value} + export SERVING_BIN=/paddle/kaitao/tipc/PaddleOCR-cppinfer/deploy/pdserving/Serving/build_server/core/general-server/serving + # cpp serving + unset https_proxy + unset http_proxy + for device in ${device_value[*]}; do + if [ ${device} = "cpu" ]; then + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" + fi + eval $web_service_cpp_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${web_service_cpp_cmd}" "${status_log}" "${model_name}" + sleep 5s + _save_log_path="${LOG_PATH}/server_infer_cpp_cpu.log" + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} > ${_save_log_path} 2>&1" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${rec_client_value} > ${_save_log_path} 2>&1" + fi + eval $cpp_client_cmd + last_status=${PIPESTATUS[0]} + status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" + sleep 5s + ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 + ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 + elif [ ${device} = "gpu" ]; then + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + fi + eval $web_service_cpp_cmd + sleep 5s + _save_log_path="${LOG_PATH}/server_infer_cpp_gpu.log" + if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" + elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} > ${_save_log_path} 2>&1" + elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${rec_client_value} > ${_save_log_path} 2>&1" + fi + eval $cpp_client_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" + sleep 5s + ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 + ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done +} + + +#set cuda device +GPUID=$2 +if [ ${#GPUID} -le 0 ];then + env="export CUDA_VISIBLE_DEVICES=0" +else + env="export CUDA_VISIBLE_DEVICES=${GPUID}" +fi +eval $env +echo $env + + +echo "################### run test ###################" + +export Count=0 +IFS="|" +func_serving "${web_service_cpp_cmd}" From a4f4454225bf538efa6dda6b203a02ea773cbeeb Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Jun 2022 02:26:16 +0000 Subject: [PATCH 065/129] add cpp serving tipc --- .../model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt | 2 +- .../model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt | 2 +- .../model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt | 2 +- .../model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 7aa4a2febe..645409d3c2 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -16,4 +16,4 @@ web_service:-m paddle_serving_server.serve --port:9293 device:gpu cpp_client:ocr_cpp_client.py ---image_dir:../../doc/imgs +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 74fffee0f8..fee9f307de 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -16,4 +16,4 @@ web_service:-m paddle_serving_server.serve --port:9293 device:gpu cpp_client:ocr_cpp_client.py ---image_dir:../../doc/imgs +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 2542f568b0..bc9e77cc73 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -16,4 +16,4 @@ web_service:-m paddle_serving_server.serve --port:9293 device:gpu cpp_client:ocr_cpp_client.py ---image_dir:../../doc/imgs +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 7087807f36..67f4833e0c 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -16,4 +16,4 @@ web_service:-m paddle_serving_server.serve --port:9293 device:gpu cpp_client:ocr_cpp_client.py ---image_dir:../../doc/imgs +--image_dir:../../doc/imgs/1.jpg From 05a983054e22b966d44fcdbb18313a6555a188d2 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Jun 2022 02:52:51 +0000 Subject: [PATCH 066/129] update doc --- test_tipc/docs/test_serving.md | 16 +++++++++++++--- ...ng_python.sh => test_serving_infer_python.sh} | 0 2 files changed, 13 insertions(+), 3 deletions(-) rename test_tipc/{test_serving_python.sh => test_serving_infer_python.sh} (100%) diff --git a/test_tipc/docs/test_serving.md b/test_tipc/docs/test_serving.md index 8600eff3b9..b9acaa8ee1 100644 --- a/test_tipc/docs/test_serving.md +++ b/test_tipc/docs/test_serving.md @@ -1,6 +1,6 @@ # PaddleServing预测功能测试 -PaddleServing预测功能测试的主程序为`test_serving.sh`,可以测试基于PaddleServing的部署功能。 +PaddleServing预测功能测试的主程序为`test_serving_infer_python.sh`和`test_serving_infer_cpp.sh`,可以测试基于PaddleServing的部署功能。 ## 1. 测试结论汇总 @@ -17,13 +17,23 @@ PaddleServing预测功能测试的主程序为`test_serving.sh`,可以测试 运行环境配置请参考[文档](./install.md)的内容配置TIPC的运行环境。 ### 2.1 功能测试 -先运行`prepare.sh`准备数据和模型,然后运行`test_serving.sh`进行测试,最终在```test_tipc/output```目录下生成`serving_infer_*.log`后缀的日志文件。 +**python serving** +先运行`prepare.sh`准备数据和模型,然后运行`test_serving_infer_python.sh`进行测试,最终在```test_tipc/output```目录下生成`serving_infer_python*.log`后缀的日志文件。 ```shell bash test_tipc/prepare.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt "serving_infer" # 用法: -bash test_tipc/test_serving.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +bash test_tipc/test_serving_infer_python.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +``` +**cpp serving** +先运行`prepare.sh`准备数据和模型,然后运行`test_serving_infer_cpp.sh`进行测试,最终在```test_tipc/output```目录下生成`serving_infer_cpp*.log`后缀的日志文件。 + +```shell +bash test_tipc/prepare.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt "serving_infer" + +# 用法: +bash test_tipc/test_serving_infer_cpp.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt ``` #### 运行结果 diff --git a/test_tipc/test_serving_python.sh b/test_tipc/test_serving_infer_python.sh similarity index 100% rename from test_tipc/test_serving_python.sh rename to test_tipc/test_serving_infer_python.sh From 4f998a84bebf5c2285dd5588da3e21ddc6df8dc5 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Thu, 2 Jun 2022 14:46:40 +0800 Subject: [PATCH 067/129] fix doc (#6442) * fix doc * fix doc * rename * fix doc * fix link --- doc/doc_ch/detection.md | 19 ++- doc/doc_ch/distributed_training.md | 17 ++- doc/doc_ch/inference_args.md | 120 ++++++++++++++++++ doc/doc_ch/recognition.md | 11 +- doc/doc_en/detection_en.md | 2 +- ...training.md => distributed_training_en.md} | 18 ++- doc/doc_en/recognition_en.md | 2 +- 7 files changed, 171 insertions(+), 18 deletions(-) create mode 100644 doc/doc_ch/inference_args.md rename doc/doc_en/{distributed_training.md => distributed_training_en.md} (70%) diff --git a/doc/doc_ch/detection.md b/doc/doc_ch/detection.md index 8a71b75c24..2cf0732219 100644 --- a/doc/doc_ch/detection.md +++ b/doc/doc_ch/detection.md @@ -13,6 +13,7 @@ - [2.5 分布式训练](#25-分布式训练) - [2.6 知识蒸馏训练](#26-知识蒸馏训练) - [2.7 其他训练环境](#27-其他训练环境) + - [2.8 模型微调](#28-模型微调) - [3. 模型评估与预测](#3-模型评估与预测) - [3.1 指标评估](#31-指标评估) - [3.2 测试检测效果](#32-测试检测效果) @@ -141,7 +142,8 @@ python3 tools/train.py -c configs/det/det_mv3_db.yml \ Global.use_amp=True Global.scale_loss=1024.0 Global.use_dynamic_loss_scaling=True ``` - + + ## 2.5 分布式训练 多机多卡训练时,通过 `--ips` 参数设置使用的机器IP地址,通过 `--gpus` 参数设置使用的GPU ID: @@ -151,7 +153,7 @@ python3 -m paddle.distributed.launch --ips="xx.xx.xx.xx,xx.xx.xx.xx" --gpus '0,1 -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained ``` -**注意:** 采用多机多卡训练时,需要替换上面命令中的ips值为您机器的地址,机器之间需要能够相互ping通。另外,训练时需要在多个机器上分别启动命令。查看机器ip地址的命令为`ifconfig`。 +**注意:** (1)采用多机多卡训练时,需要替换上面命令中的ips值为您机器的地址,机器之间需要能够相互ping通;(2)训练时需要在多个机器上分别启动命令。查看机器ip地址的命令为`ifconfig`;(3)更多关于分布式训练的性能优势等信息,请参考:[分布式训练教程](./distributed_training.md)。 @@ -177,6 +179,13 @@ Windows平台只支持`单卡`的训练与预测,指定GPU进行训练`set CUD - Linux DCU DCU设备上运行需要设置环境变量 `export HIP_VISIBLE_DEVICES=0,1,2,3`,其余训练评估预测命令与Linux GPU完全相同。 + + +## 2.8 模型微调 + +实际使用过程中,建议加载官方提供的预训练模型,在自己的数据集中进行微调,关于检测模型的微调方法,请参考:[模型微调教程](./finetune.md)。 + + # 3. 模型评估与预测 @@ -196,6 +205,7 @@ python3 tools/eval.py -c configs/det/det_mv3_db.yml -o Global.checkpoints="{pat ## 3.2 测试检测效果 测试单张图像的检测效果: + ```shell python3 tools/infer_det.py -c configs/det/det_mv3_db.yml -o Global.infer_img="./doc/imgs_en/img_10.jpg" Global.pretrained_model="./output/det_db/best_accuracy" ``` @@ -226,14 +236,19 @@ python3 tools/export_model.py -c configs/det/det_mv3_db.yml -o Global.pretrained ``` DB检测模型inference 模型预测: + ```shell python3 tools/infer/predict_det.py --det_algorithm="DB" --det_model_dir="./output/det_db_inference/" --image_dir="./doc/imgs/" --use_gpu=True ``` 如果是其他检测,比如EAST模型,det_algorithm参数需要修改为EAST,默认为DB算法: + ```shell python3 tools/infer/predict_det.py --det_algorithm="EAST" --det_model_dir="./output/det_db_inference/" --image_dir="./doc/imgs/" --use_gpu=True ``` +更多关于推理超参数的配置与解释,请参考:[模型推理超参数解释教程](./inference_args.md)。 + + # 5. FAQ diff --git a/doc/doc_ch/distributed_training.md b/doc/doc_ch/distributed_training.md index e0251b21ea..6afa4a5b9f 100644 --- a/doc/doc_ch/distributed_training.md +++ b/doc/doc_ch/distributed_training.md @@ -41,11 +41,16 @@ python3 -m paddle.distributed.launch \ ## 性能效果测试 -* 基于单机8卡P40,和2机8卡P40,在26W公开识别数据集(LSVT, RCTW, MTWI)上进行训练,最终耗时如下。 +* 在2机8卡P40的机器上,基于26W公开识别数据集(LSVT, RCTW, MTWI)上进行训练,最终耗时如下。 -| 模型 | 配置文件 | 机器数量 | 每台机器的GPU数量 | 训练时间 | 识别Acc | 加速比 | -| :----------------------: | :------------: | :------------: | :---------------: | :----------: | :-----------: | :-----------: | -| CRNN | configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml | 1 | 8 | 60h | 66.7% | - | -| CRNN | configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml | 2 | 8 | 40h | 67.0% | 150% | +| 模型 | 配置 | 精度 | 单机8卡耗时 | 2机8卡耗时 | 加速比 | +|------|-----|--------|--------|--------|-----| +| CRNN | [rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml) | 67.0% | 2.50d | 1.67d | **1.5** | -可以看出,精度没有下降的情况下,训练时间由60h缩短为了40h,加速比可以达到60h/40h=150%,效率为60h/(40h*2)=75%。 + +* 在4机8卡V100的机器上,基于全量数据训练,最终耗时如下 + + +| 模型 | 配置 | 精度 | 单机8卡耗时 | 4机8卡耗时 | 加速比 | +|------|-----|--------|--------|--------|-----| +| SVTR | [ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml) | 74.0% | 10d | 2.84d | **3.5** | diff --git a/doc/doc_ch/inference_args.md b/doc/doc_ch/inference_args.md new file mode 100644 index 0000000000..fa188ab7c8 --- /dev/null +++ b/doc/doc_ch/inference_args.md @@ -0,0 +1,120 @@ +# PaddleOCR模型推理参数解释 + +在使用PaddleOCR进行模型推理时,可以自定义修改参数,来修改模型、数据、预处理、后处理等内容(参数文件:[utility.py](../../tools/infer/utility.py)),详细的参数解释如下所示。 + +* 全局信息 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| image_dir | str | 无,必须显式指定 | 图像或者文件夹路径 | +| vis_font_path | str | "./doc/fonts/simfang.ttf" | 用于可视化的字体路径 | +| drop_score | float | 0.5 | 识别得分小于该值的结果会被丢弃,不会作为返回结果 | +| use_pdserving | bool | False | 是否使用Paddle Serving进行预测 | +| warmup | bool | False | 是否开启warmup,在统计预测耗时的时候,可以使用这种方法 | +| draw_img_save_dir | str | "./inference_results" | 系统串联预测OCR结果的保存文件夹 | +| save_crop_res | bool | False | 是否保存OCR的识别文本图像 | +| crop_res_save_dir | str | "./output" | 保存OCR识别出来的文本图像路径 | +| use_mp | bool | False | 是否开启多进程预测 | +| total_process_num | int | 6 | 开启的进城数,`use_mp`为`True`时生效 | +| process_id | int | 0 | 当前进程的id号,无需自己修改 | +| benchmark | bool | False | 是否开启benchmark,对预测速度、显存占用等进行统计 | +| save_log_path | str | "./log_output/" | 开启`benchmark`时,日志结果的保存文件夹 | +| show_log | bool | True | 是否显示预测中的日志信息 | +| use_onnx | bool | False | 是否开启onnx预测 | + + +* 预测引擎相关 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| use_gpu | bool | True | 是否使用GPU进行预测 | +| ir_optim | bool | True | 是否对计算图进行分析与优化,开启后可以加速预测过程 | +| use_tensorrt | bool | False | 是否开启tensorrt | +| min_subgraph_size | int | 15 | tensorrt中最小子图size,当子图的size大于该值时,才会尝试对该子图使用trt engine计算 | +| precision | str | fp32 | 预测的精度,支持`fp32`, `fp16`, `int8` 3种输入 | +| enable_mkldnn | bool | True | 是否开启mkldnn | +| cpu_threads | int | 10 | 开启mkldnn时,cpu预测的线程数 | + +* 文本检测模型相关 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| det_algorithm | str | "DB" | 文本检测算法名称,目前支持`DB`, `EAST`, `SAST`, `PSE` | +| det_model_dir | str | xx | 检测inference模型路径 | +| det_limit_side_len | int | 960 | 检测的图像边长限制 | +| det_limit_type | str | "max" | 检测的变成限制类型,目前支持`min`, `max`,`min`表示保证图像最短边不小于`det_limit_side_len`,`max`表示保证图像最长边不大于`det_limit_side_len` | + +其中,DB算法相关参数如下 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| det_db_thresh | float | 0.3 | DB输出的概率图中,得分大于该阈值的像素点才会被认为是文字像素点 | +| det_db_box_thresh | float | 0.6 | 检测结果边框内,所有像素点的平均得分大于该阈值时,该结果会被认为是文字区域 | +| det_db_unclip_ratio | float | 1.5 | `Vatti clipping`算法的扩张系数,使用该方法对文字区域进行扩张 | +| max_batch_size | int | 10 | 预测的batch size | +| use_dilation | bool | False | 是否对分割结果进行膨胀以获取更优检测效果 | +| det_db_score_mode | str | "fast" | DB的检测结果得分计算方法,支持`fast`和`slow`,`fast`是根据polygon的外接矩形边框内的所有像素计算平均得分,`slow`是根据原始polygon内的所有像素计算平均得分,计算速度相对较慢一些,但是更加准确一些。 | + +EAST算法相关参数如下 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| det_east_score_thresh | float | 0.8 | EAST后处理中score map的阈值 | +| det_east_cover_thresh | float | 0.1 | EAST后处理中文本框的平均得分阈值 | +| det_east_nms_thresh | float | 0.2 | EAST后处理中nms的阈值 | + +SAST算法相关参数如下 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| det_sast_score_thresh | float | 0.5 | SAST后处理中的得分阈值 | +| det_sast_nms_thresh | float | 0.5 | SAST后处理中nms的阈值 | +| det_sast_polygon | bool | False | 是否多边形检测,弯曲文本场景(如Total-Text)设置为True | + +PSE算法相关参数如下 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| det_pse_thresh | float | 0.0 | 对输出图做二值化的阈值 | +| det_pse_box_thresh | float | 0.85 | 对box进行过滤的阈值,低于此阈值的丢弃 | +| det_pse_min_area | float | 16 | box的最小面积,低于此阈值的丢弃 | +| det_pse_box_type | str | "box" | 返回框的类型,box:四点坐标,poly: 弯曲文本的所有点坐标 | +| det_pse_scale | int | 1 | 输入图像相对于进后处理的图的比例,如`640*640`的图像,网络输出为`160*160`,scale为2的情况下,进后处理的图片shape为`320*320`。这个值调大可以加快后处理速度,但是会带来精度的下降 | + +* 文本识别模型相关 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| rec_algorithm | str | "CRNN" | 文本识别算法名称,目前支持`CRNN`, `SRN`, `RARE`, `NETR`, `SAR` | +| rec_model_dir | str | 无,如果使用识别模型,该项是必填项 | 识别inference模型路径 | +| rec_image_shape | list | [3, 32, 320] | 识别时的图像尺寸, | +| rec_batch_num | int | 6 | 识别的batch size | +| max_text_length | int | 25 | 识别结果最大长度,在`SRN`中有效 | +| rec_char_dict_path | str | "./ppocr/utils/ppocr_keys_v1.txt" | 识别的字符字典文件 | +| use_space_char | bool | True | 是否包含空格,如果为`True`,则会在最后字符字典中补充`空格`字符 | + + +* 端到端文本检测与识别模型相关 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| e2e_algorithm | str | "PGNet" | 端到端算法名称,目前支持`PGNet` | +| e2e_model_dir | str | 无,如果使用端到端模型,该项是必填项 | 端到端模型inference模型路径 | +| e2e_limit_side_len | int | 768 | 端到端的输入图像边长限制 | +| e2e_limit_type | str | "max" | 端到端的边长限制类型,目前支持`min`, `max`,`min`表示保证图像最短边不小于`e2e_limit_side_len`,`max`表示保证图像最长边不大于`e2e_limit_side_len` | +| e2e_pgnet_score_thresh | float | 0.5 | 端到端得分阈值,小于该阈值的结果会被丢弃 | +| e2e_char_dict_path | str | "./ppocr/utils/ic15_dict.txt" | 识别的字典文件路径 | +| e2e_pgnet_valid_set | str | "totaltext" | 验证集名称,目前支持`totaltext`, `partvgg`,不同数据集对应的后处理方式不同,与训练过程保持一致即可 | +| e2e_pgnet_mode | str | "fast" | PGNet的检测结果得分计算方法,支持`fast`和`slow`,`fast`是根据polygon的外接矩形边框内的所有像素计算平均得分,`slow`是根据原始polygon内的所有像素计算平均得分,计算速度相对较慢一些,但是更加准确一些。 | + + +* 方向分类器模型相关 + +| 参数名称 | 类型 | 默认值 | 含义 | +| :--: | :--: | :--: | :--: | +| use_angle_cls | bool | False | 是否使用方向分类器 | +| cls_model_dir | str | 无,如果需要使用,则必须显式指定路径 | 方向分类器inference模型路径 | +| cls_image_shape | list | [3, 48, 192] | 预测尺度 | +| label_list | list | ['0', '180'] | class id对应的角度值 | +| cls_batch_num | int | 6 | 方向分类器预测的batch size | +| cls_thresh | float | 0.9 | 预测阈值,模型预测结果为180度,且得分大于该阈值时,认为最终预测结果为180度,需要翻转 | diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md index 5134422417..acf09f7bde 100644 --- a/doc/doc_ch/recognition.md +++ b/doc/doc_ch/recognition.md @@ -18,6 +18,7 @@ - [2.6. 知识蒸馏训练](#26-知识蒸馏训练) - [2.7. 多语言模型训练](#27-多语言模型训练) - [2.8. 其他训练环境](#28-其他训练环境) + - [2.9. 模型微调](#29-模型微调) - [3. 模型评估与预测](#3-模型评估与预测) - [3.1. 指标评估](#31-指标评估) - [3.2. 测试识别效果](#32-测试识别效果) @@ -387,7 +388,7 @@ python3 -m paddle.distributed.launch --ips="xx.xx.xx.xx,xx.xx.xx.xx" --gpus '0,1 -o Global.pretrained_model=./pretrain_models/en_PP-OCRv3_rec_train/best_accuracy ``` -**注意:** 采用多机多卡训练时,需要替换上面命令中的ips值为您机器的地址,机器之间需要能够相互ping通。另外,训练时需要在多个机器上分别启动命令。查看机器ip地址的命令为`ifconfig`。 +**注意:** (1)采用多机多卡训练时,需要替换上面命令中的ips值为您机器的地址,机器之间需要能够相互ping通;(2)训练时需要在多个机器上分别启动命令。查看机器ip地址的命令为`ifconfig`;(3)更多关于分布式训练的性能优势等信息,请参考:[分布式训练教程](./distributed_training.md)。 ## 2.6. 知识蒸馏训练 @@ -462,6 +463,11 @@ Windows平台只支持`单卡`的训练与预测,指定GPU进行训练`set CUD - Linux DCU DCU设备上运行需要设置环境变量 `export HIP_VISIBLE_DEVICES=0,1,2,3`,其余训练评估预测命令与Linux GPU完全相同。 +## 2.9 模型微调 + +实际使用过程中,建议加载官方提供的预训练模型,在自己的数据集中进行微调,关于识别模型的微调方法,请参考:[模型微调教程](./finetune.md)。 + + # 3. 模型评估与预测 ## 3.1. 指标评估 @@ -564,12 +570,13 @@ inference/en_PP-OCRv3_rec/ - 自定义模型推理 - 如果训练时修改了文本的字典,在使用inference模型预测时,需要通过`--rec_char_dict_path`指定使用的字典路径 + 如果训练时修改了文本的字典,在使用inference模型预测时,需要通过`--rec_char_dict_path`指定使用的字典路径,更多关于推理超参数的配置与解释,请参考:[模型推理超参数解释教程](./inference_args.md)。 ``` python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./your inference model" --rec_image_shape="3, 48, 320" --rec_char_dict_path="your text dict path" ``` + # 5. FAQ Q1: 训练模型转inference 模型之后预测效果不一致? diff --git a/doc/doc_en/detection_en.md b/doc/doc_en/detection_en.md index 76e0f8509b..f85bf585cb 100644 --- a/doc/doc_en/detection_en.md +++ b/doc/doc_en/detection_en.md @@ -159,7 +159,7 @@ python3 -m paddle.distributed.launch --ips="xx.xx.xx.xx,xx.xx.xx.xx" --gpus '0,1 -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained ``` -**Note:** When using multi-machine and multi-gpu training, you need to replace the ips value in the above command with the address of your machine, and the machines need to be able to ping each other. In addition, training needs to be launched separately on multiple machines. The command to view the ip address of the machine is `ifconfig`. +**Note:** (1) When using multi-machine and multi-gpu training, you need to replace the ips value in the above command with the address of your machine, and the machines need to be able to ping each other. (2) Training needs to be launched separately on multiple machines. The command to view the ip address of the machine is `ifconfig`. (3) For more details about the distributed training speedup ratio, please refer to [Distributed Training Tutorial](./distributed_training_en.md). ### 2.6 Training with knowledge distillation diff --git a/doc/doc_en/distributed_training.md b/doc/doc_en/distributed_training_en.md similarity index 70% rename from doc/doc_en/distributed_training.md rename to doc/doc_en/distributed_training_en.md index 2822ee5e4e..5a219ed2b4 100644 --- a/doc/doc_en/distributed_training.md +++ b/doc/doc_en/distributed_training_en.md @@ -40,11 +40,17 @@ python3 -m paddle.distributed.launch \ ## Performance comparison -* Based on 26W public recognition dataset (LSVT, rctw, mtwi), training on single 8-card P40 and dual 8-card P40, the final time consumption is as follows. +* On two 8-card P40 graphics cards, the final time consumption and speedup ratio for public recognition dataset (LSVT, RCTW, MTWI) containing 260k images are as follows. -| Model | Config file | Number of machines | Number of GPUs per machine | Training time | Recognition acc | Speedup ratio | -| :-------: | :------------: | :----------------: | :----------------------------: | :------------------: | :--------------: | :-----------: | -| CRNN | configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml | 1 | 8 | 60h | 66.7% | - | -| CRNN | configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml | 2 | 8 | 40h | 67.0% | 150% | -It can be seen that the training time is shortened from 60h to 40h, the speedup ratio can reach 150% (60h / 40h), and the efficiency is 75% (60h / (40h * 2)). +| Model | Config file | Recognition acc | single 8-card training time | two 8-card training time | Speedup ratio | +|------|-----|--------|--------|--------|-----| +| CRNN | [rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml) | 67.0% | 2.50d | 1.67d | **1.5** | + + +* On four 8-card V100 graphics cards, the final time consumption and speedup ratio for full data are as follows. + + +| Model | Config file | Recognition acc | single 8-card training time | four 8-card training time | Speedup ratio | +|------|-----|--------|--------|--------|-----| +| SVTR | [ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml) | 74.0% | 10d | 2.84d | **3.5** | diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md index 60b4a1b26b..7d31b0ffe2 100644 --- a/doc/doc_en/recognition_en.md +++ b/doc/doc_en/recognition_en.md @@ -306,7 +306,7 @@ python3 -m paddle.distributed.launch --ips="xx.xx.xx.xx,xx.xx.xx.xx" --gpus '0,1 -o Global.pretrained_model=./pretrain_models/rec_mv3_none_bilstm_ctc_v2.0_train ``` -**Note:** When using multi-machine and multi-gpu training, you need to replace the ips value in the above command with the address of your machine, and the machines need to be able to ping each other. In addition, training needs to be launched separately on multiple machines. The command to view the ip address of the machine is `ifconfig`. +**Note:** (1) When using multi-machine and multi-gpu training, you need to replace the ips value in the above command with the address of your machine, and the machines need to be able to ping each other. (2) Training needs to be launched separately on multiple machines. The command to view the ip address of the machine is `ifconfig`. (3) For more details about the distributed training speedup ratio, please refer to [Distributed Training Tutorial](./distributed_training_en.md). ### 2.6 Training with Knowledge Distillation From 908ee7948c155918ffb437d9adfa8b3ea9704af0 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Jun 2022 08:37:13 +0000 Subject: [PATCH 068/129] update mode --- test_tipc/{test_serving_cpp.sh => test_serving_infer_cpp.sh} | 5 +++-- .../{test_serving_python.sh => test_serving_infer_python.sh} | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) rename test_tipc/{test_serving_cpp.sh => test_serving_infer_cpp.sh} (99%) rename test_tipc/{test_serving_python.sh => test_serving_infer_python.sh} (99%) diff --git a/test_tipc/test_serving_cpp.sh b/test_tipc/test_serving_infer_cpp.sh similarity index 99% rename from test_tipc/test_serving_cpp.sh rename to test_tipc/test_serving_infer_cpp.sh index c9945416b6..9aafc6a827 100644 --- a/test_tipc/test_serving_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -11,6 +11,7 @@ function func_parser_model_config(){ FILENAME=$1 dataline=$(awk 'NR==1, NR==19{print}' $FILENAME) +MODE=$2 # parser params IFS=$'\n' @@ -51,7 +52,7 @@ cpp_client_py=$(func_parser_value "${lines[17]}") image_dir_key=$(func_parser_key "${lines[18]}") image_dir_value=$(func_parser_value "${lines[18]}") -LOG_PATH="$(pwd)/test_tipc/output/${model_name}/cpp_serving" +LOG_PATH="$(pwd)/test_tipc/output/${model_name}/${MODE}/cpp" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_cpp_serving.log" @@ -167,7 +168,7 @@ function func_serving(){ #set cuda device -GPUID=$2 +GPUID=$3 if [ ${#GPUID} -le 0 ];then env="export CUDA_VISIBLE_DEVICES=0" else diff --git a/test_tipc/test_serving_python.sh b/test_tipc/test_serving_infer_python.sh similarity index 99% rename from test_tipc/test_serving_python.sh rename to test_tipc/test_serving_infer_python.sh index 4affa417e1..8bdb27bce7 100644 --- a/test_tipc/test_serving_python.sh +++ b/test_tipc/test_serving_infer_python.sh @@ -11,6 +11,7 @@ function func_parser_model_config(){ FILENAME=$1 dataline=$(awk 'NR==1, NR==23{print}' $FILENAME) +MODE=$2 # parser params IFS=$'\n' @@ -58,7 +59,7 @@ pipeline_py=$(func_parser_value "${lines[21]}") image_dir_key=$(func_parser_key "${lines[22]}") image_dir_value=$(func_parser_value "${lines[22]}") -LOG_PATH="$(pwd)/test_tipc/output/${model_name}/python_serving" +LOG_PATH="$(pwd)/test_tipc/output/${model_name}/${MODE}/python" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_python_serving.log" @@ -207,7 +208,7 @@ function func_serving(){ #set cuda device -GPUID=$2 +GPUID=$3 if [ ${#GPUID} -le 0 ];then env="export CUDA_VISIBLE_DEVICES=0" else From 18dec7fa78ae39442f1343b617c354f947f84ddf Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Jun 2022 08:39:50 +0000 Subject: [PATCH 069/129] update doc --- test_tipc/docs/test_serving.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_tipc/docs/test_serving.md b/test_tipc/docs/test_serving.md index b9acaa8ee1..71f01c0d5f 100644 --- a/test_tipc/docs/test_serving.md +++ b/test_tipc/docs/test_serving.md @@ -24,7 +24,7 @@ PaddleServing预测功能测试的主程序为`test_serving_infer_python.sh`和` bash test_tipc/prepare.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt "serving_infer" # 用法: -bash test_tipc/test_serving_infer_python.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt +bash test_tipc/test_serving_infer_python.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt "serving_infer" ``` **cpp serving** 先运行`prepare.sh`准备数据和模型,然后运行`test_serving_infer_cpp.sh`进行测试,最终在```test_tipc/output```目录下生成`serving_infer_cpp*.log`后缀的日志文件。 @@ -33,7 +33,7 @@ bash test_tipc/test_serving_infer_python.sh ./test_tipc/configs/ch_ppocr_mobile_ bash test_tipc/prepare.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt "serving_infer" # 用法: -bash test_tipc/test_serving_infer_cpp.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +bash test_tipc/test_serving_infer_cpp.sh ./test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt "serving_infer" ``` #### 运行结果 From 11acfe5124129ba88d529849ef79701beaf03b08 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Thu, 2 Jun 2022 09:53:01 +0000 Subject: [PATCH 070/129] replace fluid to paddle --- ppocr/losses/rec_aster_loss.py | 4 ++-- ppocr/losses/table_att_loss.py | 25 +++++++++++----------- ppocr/modeling/backbones/kie_unet_sdmgr.py | 2 +- ppocr/modeling/backbones/rec_resnet_fpn.py | 1 - ppocr/modeling/heads/rec_srn_head.py | 2 -- ppocr/modeling/heads/self_attention.py | 13 ++++++----- 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/ppocr/losses/rec_aster_loss.py b/ppocr/losses/rec_aster_loss.py index fbb99d29a6..52605e46db 100644 --- a/ppocr/losses/rec_aster_loss.py +++ b/ppocr/losses/rec_aster_loss.py @@ -27,12 +27,12 @@ class CosineEmbeddingLoss(nn.Layer): self.epsilon = 1e-12 def forward(self, x1, x2, target): - similarity = paddle.fluid.layers.reduce_sum( + similarity = paddle.sum( x1 * x2, dim=-1) / (paddle.norm( x1, axis=-1) * paddle.norm( x2, axis=-1) + self.epsilon) one_list = paddle.full_like(target, fill_value=1) - out = paddle.fluid.layers.reduce_mean( + out = paddle.mean( paddle.where( paddle.equal(target, one_list), 1. - similarity, paddle.maximum( diff --git a/ppocr/losses/table_att_loss.py b/ppocr/losses/table_att_loss.py index d7fd99e695..51377efa2b 100644 --- a/ppocr/losses/table_att_loss.py +++ b/ppocr/losses/table_att_loss.py @@ -19,7 +19,6 @@ from __future__ import print_function import paddle from paddle import nn from paddle.nn import functional as F -from paddle import fluid class TableAttentionLoss(nn.Layer): def __init__(self, structure_weight, loc_weight, use_giou=False, giou_weight=1.0, **kwargs): @@ -36,13 +35,13 @@ class TableAttentionLoss(nn.Layer): :param bbox:[[x1,y1,x2,y2], [x1,y1,x2,y2],,,] :return: loss ''' - ix1 = fluid.layers.elementwise_max(preds[:, 0], bbox[:, 0]) - iy1 = fluid.layers.elementwise_max(preds[:, 1], bbox[:, 1]) - ix2 = fluid.layers.elementwise_min(preds[:, 2], bbox[:, 2]) - iy2 = fluid.layers.elementwise_min(preds[:, 3], bbox[:, 3]) + ix1 = paddle.maximum(preds[:, 0], bbox[:, 0]) + iy1 = paddle.maximum(preds[:, 1], bbox[:, 1]) + ix2 = paddle.minimum(preds[:, 2], bbox[:, 2]) + iy2 = paddle.minimum(preds[:, 3], bbox[:, 3]) - iw = fluid.layers.clip(ix2 - ix1 + 1e-3, 0., 1e10) - ih = fluid.layers.clip(iy2 - iy1 + 1e-3, 0., 1e10) + iw = paddle.clip(ix2 - ix1 + 1e-3, 0., 1e10) + ih = paddle.clip(iy2 - iy1 + 1e-3, 0., 1e10) # overlap inters = iw * ih @@ -55,12 +54,12 @@ class TableAttentionLoss(nn.Layer): # ious ious = inters / uni - ex1 = fluid.layers.elementwise_min(preds[:, 0], bbox[:, 0]) - ey1 = fluid.layers.elementwise_min(preds[:, 1], bbox[:, 1]) - ex2 = fluid.layers.elementwise_max(preds[:, 2], bbox[:, 2]) - ey2 = fluid.layers.elementwise_max(preds[:, 3], bbox[:, 3]) - ew = fluid.layers.clip(ex2 - ex1 + 1e-3, 0., 1e10) - eh = fluid.layers.clip(ey2 - ey1 + 1e-3, 0., 1e10) + ex1 = paddle.minimum(preds[:, 0], bbox[:, 0]) + ey1 = paddle.minimum(preds[:, 1], bbox[:, 1]) + ex2 = paddle.maximum(preds[:, 2], bbox[:, 2]) + ey2 = paddle.maximum(preds[:, 3], bbox[:, 3]) + ew = paddle.clip(ex2 - ex1 + 1e-3, 0., 1e10) + eh = paddle.clip(ey2 - ey1 + 1e-3, 0., 1e10) # enclose erea enclose = ew * eh + eps diff --git a/ppocr/modeling/backbones/kie_unet_sdmgr.py b/ppocr/modeling/backbones/kie_unet_sdmgr.py index 545e4e7511..793c68c6dd 100644 --- a/ppocr/modeling/backbones/kie_unet_sdmgr.py +++ b/ppocr/modeling/backbones/kie_unet_sdmgr.py @@ -175,7 +175,7 @@ class Kie_backbone(nn.Layer): img, relations, texts, gt_bboxes, tag, img_size) x = self.img_feat(img) boxes, rois_num = self.bbox2roi(gt_bboxes) - feats = paddle.fluid.layers.roi_align( + feats = paddle.vision.ops.roi_align( x, boxes, spatial_scale=1.0, diff --git a/ppocr/modeling/backbones/rec_resnet_fpn.py b/ppocr/modeling/backbones/rec_resnet_fpn.py index a7e876a2bd..79efd6e41e 100644 --- a/ppocr/modeling/backbones/rec_resnet_fpn.py +++ b/ppocr/modeling/backbones/rec_resnet_fpn.py @@ -18,7 +18,6 @@ from __future__ import print_function from paddle import nn, ParamAttr from paddle.nn import functional as F -import paddle.fluid as fluid import paddle import numpy as np diff --git a/ppocr/modeling/heads/rec_srn_head.py b/ppocr/modeling/heads/rec_srn_head.py index 8d59e4711a..1070d8cd64 100644 --- a/ppocr/modeling/heads/rec_srn_head.py +++ b/ppocr/modeling/heads/rec_srn_head.py @@ -20,13 +20,11 @@ import math import paddle from paddle import nn, ParamAttr from paddle.nn import functional as F -import paddle.fluid as fluid import numpy as np from .self_attention import WrapEncoderForFeature from .self_attention import WrapEncoder from paddle.static import Program from ppocr.modeling.backbones.rec_resnet_fpn import ResNetFPN -import paddle.fluid.framework as framework from collections import OrderedDict gradient_clip = 10 diff --git a/ppocr/modeling/heads/self_attention.py b/ppocr/modeling/heads/self_attention.py index 6c27fdbe43..6e4c65e393 100644 --- a/ppocr/modeling/heads/self_attention.py +++ b/ppocr/modeling/heads/self_attention.py @@ -22,7 +22,6 @@ import paddle from paddle import ParamAttr, nn from paddle import nn, ParamAttr from paddle.nn import functional as F -import paddle.fluid as fluid import numpy as np gradient_clip = 10 @@ -288,10 +287,10 @@ class PrePostProcessLayer(nn.Layer): "layer_norm_%d" % len(self.sublayers()), paddle.nn.LayerNorm( normalized_shape=d_model, - weight_attr=fluid.ParamAttr( - initializer=fluid.initializer.Constant(1.)), - bias_attr=fluid.ParamAttr( - initializer=fluid.initializer.Constant(0.))))) + weight_attr=paddle.ParamAttr( + initializer=paddle.nn.initializer.Constant(1.)), + bias_attr=paddle.ParamAttr( + initializer=paddle.nn.initializer.Constant(0.))))) elif cmd == "d": # add dropout self.functors.append(lambda x: F.dropout( x, p=dropout_rate, mode="downscale_in_infer") @@ -324,7 +323,7 @@ class PrepareEncoder(nn.Layer): def forward(self, src_word, src_pos): src_word_emb = src_word - src_word_emb = fluid.layers.cast(src_word_emb, 'float32') + src_word_emb = paddle.cast(src_word_emb, 'float32') src_word_emb = paddle.scale(x=src_word_emb, scale=self.src_emb_dim**0.5) src_pos = paddle.squeeze(src_pos, axis=-1) src_pos_enc = self.emb(src_pos) @@ -367,7 +366,7 @@ class PrepareDecoder(nn.Layer): self.dropout_rate = dropout_rate def forward(self, src_word, src_pos): - src_word = fluid.layers.cast(src_word, 'int64') + src_word = paddle.cast(src_word, 'int64') src_word = paddle.squeeze(src_word, axis=-1) src_word_emb = self.emb0(src_word) src_word_emb = paddle.scale(x=src_word_emb, scale=self.src_emb_dim**0.5) From 7399cbac200187154fede35d122d688b9ea663b8 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 6 Jun 2022 07:48:40 +0000 Subject: [PATCH 071/129] add tipc for cpp infer --- deploy/pdserving/ocr_cpp_client.py | 29 ++++++++++++++----- ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 4 +-- ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 4 +-- ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 4 +-- ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 4 +-- test_tipc/test_serving_infer_cpp.sh | 25 ++++++++-------- 6 files changed, 41 insertions(+), 29 deletions(-) diff --git a/deploy/pdserving/ocr_cpp_client.py b/deploy/pdserving/ocr_cpp_client.py index 92ccb9cd8f..649dfe0463 100755 --- a/deploy/pdserving/ocr_cpp_client.py +++ b/deploy/pdserving/ocr_cpp_client.py @@ -22,15 +22,16 @@ import cv2 from paddle_serving_app.reader import Sequential, URL2Image, ResizeByFactor from paddle_serving_app.reader import Div, Normalize, Transpose from ocr_reader import OCRReader +import codecs client = Client() # TODO:load_client need to load more than one client model. # this need to figure out some details. client.load_client_config(sys.argv[1:]) -client.connect(["127.0.0.1:9293"]) +client.connect(["127.0.0.1:8181"]) # 9293 import paddle -test_img_dir = "../../doc/imgs/1.jpg" +test_img_dir = "../../doc/imgs/" ocr_reader = OCRReader(char_dict_path="../../ppocr/utils/ppocr_keys_v1.txt") @@ -62,9 +63,21 @@ for img_file in test_img_list: image = cv2_to_base64(image_data) res_list = [] fetch_map = client.predict(feed={"x": image}, fetch=[], batch=True) - print(fetch_map) - one_batch_res = ocr_reader.postprocess(fetch_map, with_score=True) - for res in one_batch_res: - res_list.append(res[0]) - res = {"res": str(res_list)} - print(res) + if fetch_map is None: + print('no results') + else: + if "text" in fetch_map: + for x in fetch_map["text"]: + x = codecs.encode(x) + words = base64.b64decode(x).decode('utf-8') + res_list.append(words) + else: + try: + one_batch_res = ocr_reader.postprocess( + fetch_map, with_score=True) + for res in one_batch_res: + res_list.append(res[0]) + except: + print('no results') + res = {"res": str(res_list)} + print(res) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 645409d3c2..f0456b5c35 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -13,7 +13,7 @@ trans_model:-m paddle_serving_client.convert serving_dir:./deploy/pdserving web_service:-m paddle_serving_server.serve --op:GeneralDetectionOp GeneralInferOp ---port:9293 -device:gpu +--port:8181 +--gpu_id:"0"|null cpp_client:ocr_cpp_client.py --image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index fee9f307de..91c57bed1b 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -13,7 +13,7 @@ trans_model:-m paddle_serving_client.convert serving_dir:./deploy/pdserving web_service:-m paddle_serving_server.serve --op:GeneralDetectionOp GeneralInferOp ---port:9293 -device:gpu +--port:8181 +--gpu_id:"0"|null cpp_client:ocr_cpp_client.py --image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index bc9e77cc73..d18e9f11fd 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -13,7 +13,7 @@ trans_model:-m paddle_serving_client.convert serving_dir:./deploy/pdserving web_service:-m paddle_serving_server.serve --op:GeneralDetectionOp GeneralInferOp ---port:9293 -device:gpu +--port:8181 +--gpu_id:"0"|null cpp_client:ocr_cpp_client.py --image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt index 67f4833e0c..bbfec44dba 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -13,7 +13,7 @@ trans_model:-m paddle_serving_client.convert serving_dir:./deploy/pdserving web_service:-m paddle_serving_server.serve --op:GeneralDetectionOp GeneralInferOp ---port:9293 -device:gpu +--port:8181 +--gpu_id:"0"|null cpp_client:ocr_cpp_client.py --image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/test_serving_infer_cpp.sh b/test_tipc/test_serving_infer_cpp.sh index 9aafc6a827..e0e31b59e8 100644 --- a/test_tipc/test_serving_infer_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -47,7 +47,8 @@ op_key=$(func_parser_key "${lines[14]}") op_value=$(func_parser_value "${lines[14]}") port_key=$(func_parser_key "${lines[15]}") port_value=$(func_parser_value "${lines[15]}") -device_value=$(func_parser_value "${lines[16]}") +gpu_key=$(func_parser_key "${lines[16]}") +gpu_value=$(func_parser_value "${lines[16]}") cpp_client_py=$(func_parser_value "${lines[17]}") image_dir_key=$(func_parser_key "${lines[18]}") image_dir_value=$(func_parser_value "${lines[18]}") @@ -108,8 +109,8 @@ function func_serving(){ # cpp serving unset https_proxy unset http_proxy - for device in ${device_value[*]}; do - if [ ${device} = "cpu" ]; then + for gpu_id in ${gpu_value[*]}; do + if [ ${gpu_id} = "null" ]; then if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then @@ -132,16 +133,16 @@ function func_serving(){ eval $cpp_client_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" - sleep 5s + # sleep 5s ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 - ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 - elif [ ${device} = "gpu" ]; then + # ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 + else if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} --gpu_id=0 > serving_log_gpu.log &" + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" fi eval $web_service_cpp_cmd sleep 5s @@ -157,11 +158,9 @@ function func_serving(){ last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" - sleep 5s + # sleep 5s ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 - ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 - else - echo "Does not support hardware other than CPU and GPU Currently!" + # ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 fi done } From 6d73332b975efec7aa89aac99f523d0e87234d74 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 6 Jun 2022 07:50:12 +0000 Subject: [PATCH 072/129] add tipc for cpp infer --- deploy/pdserving/ocr_cpp_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/pdserving/ocr_cpp_client.py b/deploy/pdserving/ocr_cpp_client.py index 649dfe0463..3aaf031559 100755 --- a/deploy/pdserving/ocr_cpp_client.py +++ b/deploy/pdserving/ocr_cpp_client.py @@ -28,10 +28,10 @@ client = Client() # TODO:load_client need to load more than one client model. # this need to figure out some details. client.load_client_config(sys.argv[1:]) -client.connect(["127.0.0.1:8181"]) # 9293 +client.connect(["127.0.0.1:8181"]) import paddle -test_img_dir = "../../doc/imgs/" +test_img_dir = "../../doc/imgs/1.jpg" ocr_reader = OCRReader(char_dict_path="../../ppocr/utils/ppocr_keys_v1.txt") From d249075203e2919417517516b1c1e480c467ff8c Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 6 Jun 2022 07:51:20 +0000 Subject: [PATCH 073/129] add tipc for cpp infer --- test_tipc/test_serving_infer_cpp.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/test_tipc/test_serving_infer_cpp.sh b/test_tipc/test_serving_infer_cpp.sh index e0e31b59e8..cad17506e5 100644 --- a/test_tipc/test_serving_infer_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -105,7 +105,6 @@ function func_serving(){ python_list=(${python_list}) cd ${serving_dir_value} - export SERVING_BIN=/paddle/kaitao/tipc/PaddleOCR-cppinfer/deploy/pdserving/Serving/build_server/core/general-server/serving # cpp serving unset https_proxy unset http_proxy From 6c7170f172c2f3d9abd60f0f1cffafe5f33ddc26 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 6 Jun 2022 08:21:28 +0000 Subject: [PATCH 074/129] update doc --- deploy/pdserving/README.md | 2 +- deploy/pdserving/README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/pdserving/README.md b/deploy/pdserving/README.md index 55e03c4c26..29c85c0826 100644 --- a/deploy/pdserving/README.md +++ b/deploy/pdserving/README.md @@ -217,7 +217,7 @@ The C++ service deployment is the same as python in the environment setup and da 2. Run the following command to start the service. ``` # Start the service and save the running log in log.txt - python3 -m paddle_serving_server.serve --model ppocr_det_v3_serving ppocr_rec_v3_serving --op GeneralDetectionOp GeneralInferOp --port 9293 &>log.txt & + python3 -m paddle_serving_server.serve --model ppocr_det_v3_serving ppocr_rec_v3_serving --op GeneralDetectionOp GeneralInferOp --port 8181 &>log.txt & ``` After the service is successfully started, a log similar to the following will be printed in log.txt ![](./imgs/start_server.png) diff --git a/deploy/pdserving/README_CN.md b/deploy/pdserving/README_CN.md index 0891611db5..92b1ad0c69 100644 --- a/deploy/pdserving/README_CN.md +++ b/deploy/pdserving/README_CN.md @@ -230,7 +230,7 @@ cp -rf general_detection_op.cpp Serving/core/general-server/op ``` # 启动服务,运行日志保存在log.txt - python3 -m paddle_serving_server.serve --model ppocr_det_v3_serving ppocr_rec_v3_serving --op GeneralDetectionOp GeneralInferOp --port 9293 &>log.txt & + python3 -m paddle_serving_server.serve --model ppocr_det_v3_serving ppocr_rec_v3_serving --op GeneralDetectionOp GeneralInferOp --port 8181 &>log.txt & ``` 成功启动服务后,log.txt中会打印类似如下日志 ![](./imgs/start_server.png) From 6425721d1829d500e4935f85b2e1f738bd12c214 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Mon, 6 Jun 2022 18:42:47 +0800 Subject: [PATCH 075/129] add tipc dist (#6482) * add tipc dist * fix * fix * add note * add readme --- .../train_fleet_infer_python.txt | 53 +++++++++ .../docs/test_train_fleet_inference_python.md | 107 ++++++++++++++++++ test_tipc/readme.md | 1 + test_tipc/test_train_inference_python.sh | 6 +- 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt create mode 100644 test_tipc/docs/test_train_fleet_inference_python.md diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt new file mode 100644 index 0000000000..08e1fe9ba0 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PP-OCRv3_rec +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=64 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_infer +infer_export:null +infer_quant:False +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/docs/test_train_fleet_inference_python.md b/test_tipc/docs/test_train_fleet_inference_python.md new file mode 100644 index 0000000000..89cf5d5b6d --- /dev/null +++ b/test_tipc/docs/test_train_fleet_inference_python.md @@ -0,0 +1,107 @@ +# Linux GPU/CPU 多机多卡训练推理测试 + +Linux GPU/CPU 多机多卡训练推理测试的主程序为`test_train_inference_python.sh`,可以测试基于Python的模型训练、评估、推理等基本功能。 + +## 1. 测试结论汇总 + +- 训练相关: + +| 算法名称 | 模型名称 | 多机多卡 | +| :----: | :----: | :----: | +| PP-OCRv3 | ch_PP-OCRv3_rec | 分布式训练 | + + +- 推理相关: + +| 算法名称 | 模型名称 | device_CPU | device_GPU | batchsize | +| :----: | :----: | :----: | :----: | :----: | +| PP-OCRv3 | ch_PP-OCRv3_rec | 支持 | 支持 | 1 | + + +## 2. 测试流程 + +运行环境配置请参考[文档](./install.md)的内容配置TIPC的运行环境。 + +### 2.1 功能测试 + +#### 2.1.1 修改配置文件 + +首先,修改配置文件中的`ip`设置: 假设两台机器的`ip`地址分别为`192.168.0.1`和`192.168.0.2`,则对应的配置文件`gpu_list`字段需要修改为`gpu_list:192.168.0.1,192.168.0.2;0,1`; `ip`地址查看命令为`ifconfig`。 + + +#### 2.1.2 准备数据 + +运行`prepare.sh`准备数据和模型,以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt`为例,数据准备命令如下所示。 + +```shell +bash test_tipc/prepare.sh test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt lite_train_lite_infer +``` + +**注意:** 由于是多机训练,这里需要在所有的节点上均运行启动上述命令,准备数据。 + +#### 2.1.3 修改起始端口并开始测试 + +在多机的节点上使用下面的命令设置分布式的起始端口(否则后面运行的时候会由于无法找到运行端口而hang住),一般建议设置在`10000~20000`之间。 + +```shell +export FLAGS_START_PORT=17000 +``` + +以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt`为例,测试方法如下所示。 + +```shell +bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt lite_train_lite_infer +``` + +**注意:** 由于是多机训练,这里需要在所有的节点上均运行启动上述命令进行测试。 + + +#### 2.1.4 输出结果 + +输出结果如下,表示命令运行成功。 + +```bash + Run successfully with command - ch_PP-OCRv3_rec - python3.7 -m paddle.distributed.launch --ips=192.168.0.1,192.168.0.2 --gpus=0,1 tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o Global.use_gpu=True Global.save_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2 Global.epoch_num=3 Global.auto_cast=fp32 Train.loader.batch_size_per_card=16 ! + ...... + Run successfully with command - ch_PP-OCRv3_rec - python3.7 tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu=False --enable_mkldnn=False --cpu_threads=6 --rec_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2/Student --rec_batch_num=1 --image_dir=./inference/rec_inference --benchmark=True --precision=fp32 > ./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/python_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_1.log 2>&1 ! +``` + +在开启benchmark参数时,可以得到测试的详细数据,包含运行环境信息(系统版本、CUDA版本、CUDNN版本、驱动版本),Paddle版本信息,参数设置信息(运行设备、线程数、是否开启内存优化等),模型信息(模型名称、精度),数据信息(batchsize、是否为动态shape等),性能信息(CPU,GPU的占用、运行耗时、预处理耗时、推理耗时、后处理耗时),内容如下所示: + +``` +[2022/06/02 22:53:35] ppocr INFO: + +[2022/06/02 22:53:35] ppocr INFO: ---------------------- Env info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: OS_version: Ubuntu 16.04 +[2022/06/02 22:53:35] ppocr INFO: CUDA_version: 10.1.243 +[2022/06/02 22:53:35] ppocr INFO: CUDNN_version: 7.6.5 +[2022/06/02 22:53:35] ppocr INFO: drivier_version: 460.32.03 +[2022/06/02 22:53:35] ppocr INFO: ---------------------- Paddle info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: paddle_version: 2.3.0-rc0 +[2022/06/02 22:53:35] ppocr INFO: paddle_commit: 5d4980c052583fec022812d9c29460aff7cdc18b +[2022/06/02 22:53:35] ppocr INFO: log_api_version: 1.0 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Conf info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: runtime_device: cpu +[2022/06/02 22:53:35] ppocr INFO: ir_optim: True +[2022/06/02 22:53:35] ppocr INFO: enable_memory_optim: True +[2022/06/02 22:53:35] ppocr INFO: enable_tensorrt: False +[2022/06/02 22:53:35] ppocr INFO: enable_mkldnn: False +[2022/06/02 22:53:35] ppocr INFO: cpu_math_library_num_threads: 6 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Model info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: model_name: rec +[2022/06/02 22:53:35] ppocr INFO: precision: fp32 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Data info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: batch_size: 1 +[2022/06/02 22:53:35] ppocr INFO: input_shape: dynamic +[2022/06/02 22:53:35] ppocr INFO: data_num: 6 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Perf info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: cpu_rss(MB): 288.957, gpu_rss(MB): None, gpu_util: None% +[2022/06/02 22:53:35] ppocr INFO: total time spent(s): 0.4824 +[2022/06/02 22:53:35] ppocr INFO: preprocess_time(ms): 0.1136, inference_time(ms): 79.5877, postprocess_time(ms): 0.6945 +``` + +该信息可以在运行log中查看,以上面的`ch_PP-OCRv3_rec`为例,log位置在`./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/results_python.log`。 + +如果运行失败,也会在终端中输出运行失败的日志信息以及对应的运行命令。可以基于该命令,分析运行失败的原因。 + +**注意:** 由于分布式训练时,仅在`trainer_id=0`所在的节点中保存模型,因此其他的节点中在运行模型导出与推理时会报错,为正常现象。 diff --git a/test_tipc/readme.md b/test_tipc/readme.md index 8110f0073b..effb2f168b 100644 --- a/test_tipc/readme.md +++ b/test_tipc/readme.md @@ -138,6 +138,7 @@ bash test_tipc/test_train_inference_python.sh ./test_tipc/configs/ch_ppocr_mobil ## 4. 开始测试 各功能测试中涉及混合精度、裁剪、量化等训练相关,及mkldnn、Tensorrt等多种预测相关参数配置,请点击下方相应链接了解更多细节和使用教程: - [test_train_inference_python 使用](docs/test_train_inference_python.md) :测试基于Python的模型训练、评估、推理等基本功能,包括裁剪、量化、蒸馏。 +- [test_train_fleet_inference_python 使用](./docs/test_train_fleet_inference_python.md):测试基于Python的多机多卡训练与推理等基本功能。 - [test_inference_cpp 使用](docs/test_inference_cpp.md):测试基于C++的模型推理。 - [test_serving 使用](docs/test_serving.md):测试基于Paddle Serving的服务化部署功能。 - [test_lite_arm_cpp 使用](docs/test_lite_arm_cpp.md):测试基于Paddle-Lite的ARM CPU端c++预测部署功能。 diff --git a/test_tipc/test_train_inference_python.sh b/test_tipc/test_train_inference_python.sh index 1527875bea..62a56a32ce 100644 --- a/test_tipc/test_train_inference_python.sh +++ b/test_tipc/test_train_inference_python.sh @@ -315,7 +315,9 @@ else set_batchsize=$(func_set_params "${train_batch_key}" "${train_batch_value}") set_train_params1=$(func_set_params "${train_param_key1}" "${train_param_value1}") set_use_gpu=$(func_set_params "${train_use_gpu_key}" "${train_use_gpu}") - if [ ${#ips} -le 26 ];then + # if length of ips >= 15, then it is seen as multi-machine + # 15 is the min length of ips info for multi-machine: 0.0.0.0,0.0.0.0 + if [ ${#ips} -le 15 ];then save_log="${LOG_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}" nodes=1 else @@ -330,7 +332,7 @@ else set_save_model=$(func_set_params "${save_model_key}" "${save_log}") if [ ${#gpu} -le 2 ];then # train with cpu or single gpu cmd="${python} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config} " - elif [ ${#ips} -le 26 ];then # train with multi-gpu + elif [ ${#ips} -le 15 ];then # train with multi-gpu cmd="${python} -m paddle.distributed.launch --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}" else # train with multi-machine cmd="${python} -m paddle.distributed.launch --ips=${ips} --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_pretrain} ${set_epoch} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}" From dfcdec49a7d1afb4ea9326783c078344196fc52a Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 6 Jun 2022 11:46:47 +0000 Subject: [PATCH 076/129] add amp tipc --- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 14 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 12 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 14 ++--- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 10 ++-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 8 +-- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ 17 files changed, 142 insertions(+), 89 deletions(-) create mode 100644 test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 033d40a80a..85b0ebcb9d 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_det +model_name:ch_PP-OCRv2_det python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index d922a4a5da..3afc0acb79 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_det_PACT +model_name:ch_PP-OCRv2_det_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 7c438cb8a3..1b8800f5cf 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:PPOCRv2_ocr_rec +model_name:ch_PP-OCRv2_rec python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index e22d8a564b..e0f86d9020 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,13 +1,13 @@ ===========================train_params=========================== -model_name:ch_PPOCRv2_rec_PACT +model_name:ch_PP-OCRv2_rec_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 -Global.pretrained_model:null +Global.pretrained_model:pretrain_models/ch_PP-OCRv2_rec_train/best_accuracy train_model_name:latest train_infer_img_dir:./inference/rec_inference null:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:True inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 98bc36a80d..fe72cfb4e9 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_det +model_name:ch_PP-OCRv3_det python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 6d6862607a..252378e4dc 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_det_PACT +model_name:ch_PP-OCRv3_det_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 47cc3e2f53..68888082c3 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,10 +1,10 @@ ===========================train_params=========================== -model_name:PPOCRv3_ocr_rec +model_name:ch_PP-OCRv3_rec python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 6049a377a6..c00e6c4e4b 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -1,13 +1,13 @@ ===========================train_params=========================== -model_name:ch_PPOCRv3_rec_PACT +model_name:ch_PP-OCRv3_rec_PACT python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 -Global.pretrained_model:null +Global.pretrained_model:pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy train_model_name:latest train_infer_img_dir:./inference/rec_inference null:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:True inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 593e7ec7ed..6b3352f741 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=100|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=100|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2 infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 5a95f02685..150a8a0315 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 1f9bec12ad..3a5d8faf3f 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=20|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 30fb939bff..bd9c4a8df2 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:tools/export_model.py -c configs/rec/rec_icdar15_train.yml -o infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index fda9cf4dde..7abc3e9340 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_FPGM/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index abed3cfba9..a1a2a8e63d 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 Global.checkpoints:null @@ -39,11 +39,11 @@ infer_export:null infer_quant:False inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_image_shape="3,32,100" --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:False|True ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 3e3764e8c6..93ed14cb60 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_lite_infer=4 Global.pretrained_model:null @@ -39,11 +39,11 @@ infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_res18_db_ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ --save_log_path:null diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 78c15047fb..63ddaa4a8b 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -39,11 +39,11 @@ infer_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec infer_quant:False inference:tools/infer/predict_rec.py --use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1|6 ---use_tensorrt:True|False ---precision:fp32|int8 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: --image_dir:./inference/rec_inference --save_log_path:./test/output/ diff --git a/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..c4bf14778b --- /dev/null +++ b/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./inference/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:False +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] From b5f282c496af8bebfb4e6dbd8a8eeb05499bc5b1 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Jun 2022 06:59:13 +0000 Subject: [PATCH 077/129] add kl pact to cpp infer tipc --- ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ ..._normal_normal_infer_cpp_linux_gpu_cpu.txt | 20 ++++++++ test_tipc/prepare.sh | 48 +++++++++++++++++++ 13 files changed, 288 insertions(+) create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..1975e099d7 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_det_KL +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_det_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..43ef97d506 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_det_PACT +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_det_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..95e4062d14 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_rec_KL +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_rec_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..b807eadd3f --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv2_rec_PACT +use_opencv:True +infer_model:./inference/ch_PP-OCRv2_rec_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..a34ffe22ae --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv3_det_KL +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_det_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..3198b87552 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv3_det_PACT +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_det_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..f1a308fcc8 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv3_rec_KL +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_rec_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..8fc1132ca6 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_PP-OCRv3_rec_PACT +use_opencv:True +infer_model:./inference/ch_PP-OCRv3_rec_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_img_h=48 --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..eb2fd0a001 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_KL +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_det_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..17723f41ab --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_PACT +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_det_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +--det:True +--rec:False +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..adf06257a7 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_KL +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_rec_klquant_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..ba2df90f75 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_infer_cpp_linux_gpu_cpu.txt @@ -0,0 +1,20 @@ +===========================cpp_infer_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_PACT +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_rec_pact_infer +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_img_h=32 +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +--det:False +--rec:True +--cls:False +--use_angle_cls:False \ No newline at end of file diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 6ef7e847bd..37b8678205 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -358,10 +358,26 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_mobile_v2.0_det_KL" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_det_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_klquant_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_mobile_v2.0_det_PACT" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_det_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_pact_infer.tar && tar xf ch_det_data_50.tar && cd ../ elif [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_mobile_v2.0_rec_KL" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_klquant_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_ppocr_mobile_v2.0_rec_PACT" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_pact_infer.tar && tar xf rec_inference.tar && cd ../ elif [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar --no-check-certificate @@ -374,18 +390,50 @@ if [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv2_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_det_KL" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_det_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_klquant_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_det_PACT" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_det_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_pact_infer.tar && tar xf ch_det_data_50.tar && cd ../ elif [ ${model_name} = "ch_PP-OCRv2_rec" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv2_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_rec_KL" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_rec_klquant_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv2_rec_PACT" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_rec_pact_infer.tar && tar xf rec_inference.tar && cd ../ elif [ ${model_name} = "ch_PP-OCRv3_det" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_det_KL" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_det_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_klquant_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_det_PACT" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_det_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_pact_infer.tar && tar xf ch_det_data_50.tar && cd ../ elif [ ${model_name} = "ch_PP-OCRv3_rec" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_PP-OCRv3_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_rec_KL" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_rec_klquant_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ch_PP-OCRv3_rec_PACT" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_rec_pact_infer.tar && tar xf rec_inference.tar && cd ../ elif [ ${model_name} = "ch_ppocr_mobile_v2.0" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate From 7c1bec9484c890164fd35029148421e67fdea413 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Jun 2022 08:48:46 +0000 Subject: [PATCH 078/129] add kl pact to serving python --- ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ ...al_normal_serving_python_linux_gpu_cpu.txt | 23 +++++++++++++++++++ test_tipc/test_paddle2onnx.sh | 12 +++++----- test_tipc/test_serving_infer_python.sh | 12 +++++----- 14 files changed, 288 insertions(+), 12 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..2c96d2bfd8 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_kl_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..d5d99ab56d --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_pact_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..3405f2b587 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv2_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_kl_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..2b7ed81172 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv2_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_pact_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..23dbc49a38 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_kl_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..4546644cbc --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_pact_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..68586af0d9 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv3_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_kl_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..826f586f0c --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_PP-OCRv3_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_pact_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..049ec78458 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_kl_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..909d738919 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_pact_client/ +--rec_dirname:null +--rec_serving_server:null +--rec_serving_client:null +serving_dir:./deploy/pdserving +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..948e3dceb3 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_kl_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..f123f36543 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_python_linux_gpu_cpu.txt @@ -0,0 +1,23 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:null +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:null +--det_serving_client:null +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_pact_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency="1" +op.det.local_service_conf.devices:gpu|null +op.det.local_service_conf.use_mkldnn:False +op.det.local_service_conf.thread_num:6 +op.det.local_service_conf.use_trt:False +op.det.local_service_conf.precision:fp32 +op.det.local_service_conf.model_config: +op.rec.local_service_conf.model_config: +pipline:pipeline_http_client.py --det=False +--image_dir:../../inference/rec_inference diff --git a/test_tipc/test_paddle2onnx.sh b/test_tipc/test_paddle2onnx.sh index e7ab018b52..4ad2035f48 100644 --- a/test_tipc/test_paddle2onnx.sh +++ b/test_tipc/test_paddle2onnx.sh @@ -77,7 +77,7 @@ function func_paddle2onnx(){ eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then # trans det set_dirname=$(func_set_params "--model_dir" "${det_infer_model_dir_value}") set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") @@ -89,7 +89,7 @@ function func_paddle2onnx(){ eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then # trans rec set_dirname=$(func_set_params "--model_dir" "${rec_infer_model_dir_value}") set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") @@ -113,10 +113,10 @@ function func_paddle2onnx(){ set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " fi @@ -132,10 +132,10 @@ function func_paddle2onnx(){ set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then set_det_model_dir=$(func_set_params "${det_model_key}" "${det_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_det_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_dir=$(func_set_params "${rec_model_key}" "${rec_save_file_value}") infer_model_cmd="${python} ${inference_py} ${set_gpu} ${set_img_dir} ${set_rec_model_dir} --use_onnx=True > ${_save_log_path} 2>&1 " fi diff --git a/test_tipc/test_serving_infer_python.sh b/test_tipc/test_serving_infer_python.sh index 8bdb27bce7..58a64c9fe6 100644 --- a/test_tipc/test_serving_infer_python.sh +++ b/test_tipc/test_serving_infer_python.sh @@ -86,7 +86,7 @@ function func_serving(){ python_list=(${python_list}) trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" eval $trans_model_cmd - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then # trans det set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") @@ -94,7 +94,7 @@ function func_serving(){ python_list=(${python_list}) trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" eval $trans_model_cmd - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then # trans rec set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") @@ -124,13 +124,13 @@ function func_serving(){ eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} &" eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_rec_model_config} &" eval $web_service_cmd @@ -174,13 +174,13 @@ function func_serving(){ eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then + elif [[ ${model_name} =~ "det" ]]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} &" eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then + elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_rec_model_config} &" eval $web_service_cmd From f3905297ba0a7381cbbd3c5903f1f45ab9ab2c8e Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Jun 2022 09:22:46 +0000 Subject: [PATCH 079/129] add kl pact to serving python --- test_tipc/prepare.sh | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 37b8678205..daf6a32961 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -467,7 +467,31 @@ if [ ${MODE} = "serving_infer" ];then ${python_name} -m pip install paddle_serving_client ${python_name} -m pip install paddle-serving-app # wget model - if [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then + if [ ${model_name} == "ch_ppocr_mobile_v2.0_det_KL" ] || [ ${model_name} == "ch_ppocr_mobile_v2.0_rec_KL" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_det_klquant_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_klquant_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_klquant_infer.tar && cd ../ + elif [ ${model_name} == "ch_PP-OCRv2_det_KL" ] || [ ${model_name} == "ch_PP-OCRv2_rec_KL" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_det_klquant_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_klquant_infer.tar && tar xf ch_PP-OCRv2_rec_klquant_infer.tar && cd ../ + elif [ ${model_name} == "ch_PP-OCRv3_det_KL" ] || [ ${model_name} == "ch_PP-OCRv3_rec_KL" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_det_klquant_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_rec_klquant_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_klquant_infer.tar && tar xf ch_PP-OCRv3_rec_klquant_infer.tar && cd ../ + elif [ ${model_name} == "ch_ppocr_mobile_v2.0_det_PACT" ] || [ ${model_name} == "ch_ppocr_mobile_v2.0_rec_PACT" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_det_pact_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_ppocr_mobile_v2.0_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_pact_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_pact_infer.tar && cd ../ + elif [ ${model_name} == "ch_PP-OCRv2_det_PACT" ] || [ ${model_name} == "ch_PP-OCRv2_rec_PACT" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_det_pact_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv2_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv2_det_pact_infer.tar && tar xf ch_PP-OCRv2_rec_pact_infer.tar && cd ../ + elif [ ${model_name} == "ch_PP-OCRv3_det_PACT" ] || [ ${model_name} == "ch_PP-OCRv3_rec_PACT" ] ; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_det_pact_infer.tar --no-check-certificate + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/tipc_fake_model/ch_PP-OCRv3_rec_pact_infer.tar --no-check-certificate + cd ./inference && tar xf ch_PP-OCRv3_det_pact_infer.tar && tar xf ch_PP-OCRv3_rec_pact_infer.tar && cd ../ + elif [[ ${model_name} =~ "ch_ppocr_mobile_v2.0" ]]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar --no-check-certificate cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && cd ../ @@ -485,8 +509,9 @@ if [ ${MODE} = "serving_infer" ];then cd ./inference && tar xf ch_PP-OCRv3_det_infer.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ fi # wget data + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate - cd ./inference && tar xf rec_inference.tar && cd ../ + cd ./inference && tar xf ch_det_data_50.tar && tar xf rec_inference.tar && cd ../ fi if [ ${MODE} = "paddle2onnx_infer" ];then From 8d257f2499cce9be296a313d3a2c535dd0d40571 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Jun 2022 12:05:24 +0000 Subject: [PATCH 080/129] add kl pact to serving cpp --- ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ ...ormal_normal_serving_cpp_linux_gpu_cpu.txt | 19 ++++ test_tipc/test_serving_infer_cpp.sh | 86 ++++--------------- 13 files changed, 247 insertions(+), 67 deletions(-) create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..e306b0a92a --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_kl_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..b2d929b99c --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_pact_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..34d4007b15 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_kl_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..2a174b9e31 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv2_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv2_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v2_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v2_pact_client/ +--rec_dirname:./inference/ch_PP-OCRv2_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v2_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v2_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..22b429760c --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_kl_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..7d300f4456 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_pact_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..fa6f04e48c --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_kl_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..008df50d6d --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_PP-OCRv3_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_PP-OCRv3_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_v3_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_v3_pact_client/ +--rec_dirname:./inference/ch_PP-OCRv3_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_v3_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_v3_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..d9de1cc19a --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_kl_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..1a49a10f9b --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_det_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_pact_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..ab518de55a --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_KL +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_klquant_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_kl_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_kl_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_klquant_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_kl_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_kl_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt new file mode 100644 index 0000000000..229f70cf35 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/model_linux_gpu_normal_normal_serving_cpp_linux_gpu_cpu.txt @@ -0,0 +1,19 @@ +===========================serving_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec_PACT +python:python3.7 +trans_model:-m paddle_serving_client.convert +--det_dirname:./inference/ch_ppocr_mobile_v2.0_det_pact_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--det_serving_server:./deploy/pdserving/ppocr_det_mobile_pact_serving/ +--det_serving_client:./deploy/pdserving/ppocr_det_mobile_pact_client/ +--rec_dirname:./inference/ch_ppocr_mobile_v2.0_rec_pact_infer/ +--rec_serving_server:./deploy/pdserving/ppocr_rec_mobile_pact_serving/ +--rec_serving_client:./deploy/pdserving/ppocr_rec_mobile_pact_client/ +serving_dir:./deploy/pdserving +web_service:-m paddle_serving_server.serve +--op:GeneralDetectionOp GeneralInferOp +--port:8181 +--gpu_id:"0"|null +cpp_client:ocr_cpp_client.py +--image_dir:../../doc/imgs/1.jpg diff --git a/test_tipc/test_serving_infer_cpp.sh b/test_tipc/test_serving_infer_cpp.sh index cad17506e5..45bee4b1b9 100644 --- a/test_tipc/test_serving_infer_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -65,101 +65,53 @@ function func_serving(){ # pdserving set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") - if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - # trans det - set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") - set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") - set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") - python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} - # trans rec - set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") - set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") - set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") - python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - # trans det - set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") - set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") - set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") - python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - # trans rec - set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") - set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") - set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") - python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - fi + # trans det + set_dirname=$(func_set_params "--dirname" "${det_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} + # trans rec + set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") + set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") + set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") + python_list=(${python_list}) + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" set_image_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") python_list=(${python_list}) - cd ${serving_dir_value} # cpp serving unset https_proxy unset http_proxy for gpu_id in ${gpu_value[*]}; do if [ ${gpu_id} = "null" ]; then - if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" - fi + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" eval $web_service_cpp_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cpp_cmd}" "${status_log}" "${model_name}" sleep 5s _save_log_path="${LOG_PATH}/server_infer_cpp_cpu.log" - if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} > ${_save_log_path} 2>&1" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${rec_client_value} > ${_save_log_path} 2>&1" - fi + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" eval $cpp_client_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" - # sleep 5s ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 - # ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 else - if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" - fi + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" eval $web_service_cpp_cmd sleep 5s _save_log_path="${LOG_PATH}/server_infer_cpp_gpu.log" - if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" - elif [ ${model_name} = "ch_PP-OCRv2_det" ] || [ ${model_name} = "ch_PP-OCRv3_det" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_det" ] || [ ${model_name} = "ch_ppocr_server_v2.0_det" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} > ${_save_log_path} 2>&1" - elif [ ${model_name} = "ch_PP-OCRv2_rec" ] || [ ${model_name} = "ch_PP-OCRv3_rec" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0_rec" ] || [ ${model_name} = "ch_ppocr_server_v2.0_rec" ]; then - cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${rec_client_value} > ${_save_log_path} 2>&1" - fi + cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" eval $cpp_client_cmd last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" - # sleep 5s ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 - # ps ux | grep -i ${web_service_py} | awk '{print $2}' | xargs kill -s 9 fi done } From f10c4580a87dbec84c70e8ea78b4c61e0a1246b1 Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Wed, 8 Jun 2022 14:01:21 +0800 Subject: [PATCH 081/129] update for serving (#6518) --- deploy/pdserving/README.md | 2 +- deploy/pdserving/README_CN.md | 2 +- deploy/pdserving/web_service.py | 7 ++++--- test_tipc/test_serving_infer_cpp.sh | 2 -- test_tipc/test_serving_infer_python.sh | 6 ++---- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/deploy/pdserving/README.md b/deploy/pdserving/README.md index 29c85c0826..83329a11cd 100644 --- a/deploy/pdserving/README.md +++ b/deploy/pdserving/README.md @@ -136,7 +136,7 @@ The recognition model is the same. 2. Run the following command to start the service. ``` # Start the service and save the running log in log.txt - python3 web_service.py &>log.txt & + python3 web_service.py --config=config.yml &>log.txt & ``` After the service is successfully started, a log similar to the following will be printed in log.txt ![](./imgs/start_server.png) diff --git a/deploy/pdserving/README_CN.md b/deploy/pdserving/README_CN.md index 92b1ad0c69..ab05b766e3 100644 --- a/deploy/pdserving/README_CN.md +++ b/deploy/pdserving/README_CN.md @@ -135,7 +135,7 @@ python3 -m paddle_serving_client.convert --dirname ./ch_PP-OCRv3_rec_infer/ \ 2. 启动服务可运行如下命令: ``` # 启动服务,运行日志保存在log.txt - python3 web_service.py &>log.txt & + python3 web_service.py --config=config.yml &>log.txt & ``` 成功启动服务后,log.txt中会打印类似如下日志 ![](./imgs/start_server.png) diff --git a/deploy/pdserving/web_service.py b/deploy/pdserving/web_service.py index d8491dc572..b6fadb91d5 100644 --- a/deploy/pdserving/web_service.py +++ b/deploy/pdserving/web_service.py @@ -19,7 +19,7 @@ import copy import cv2 import base64 # from paddle_serving_app.reader import OCRReader -from ocr_reader import OCRReader, DetResizeForTest +from ocr_reader import OCRReader, DetResizeForTest, ArgsParser from paddle_serving_app.reader import Sequential, ResizeByFactor from paddle_serving_app.reader import Div, Normalize, Transpose from paddle_serving_app.reader import DBPostProcess, FilterBoxes, GetRotateCropImage, SortedBoxes @@ -85,7 +85,7 @@ class RecOp(Op): dt_boxes = copy.deepcopy(self.dt_list) feed_list = [] img_list = [] - max_wh_ratio = 320/48. + max_wh_ratio = 320 / 48. ## Many mini-batchs, the type of feed_data is list. max_batch_size = 6 # len(dt_boxes) @@ -163,5 +163,6 @@ class OcrService(WebService): uci_service = OcrService(name="ocr") -uci_service.prepare_pipeline_config("config.yml") +FLAGS = ArgsParser().parse_args() +uci_service.prepare_pipeline_config(yml_dict=FLAGS.conf_dict) uci_service.run_service() diff --git a/test_tipc/test_serving_infer_cpp.sh b/test_tipc/test_serving_infer_cpp.sh index cad17506e5..6b90fe943f 100644 --- a/test_tipc/test_serving_infer_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -106,8 +106,6 @@ function func_serving(){ cd ${serving_dir_value} # cpp serving - unset https_proxy - unset http_proxy for gpu_id in ${gpu_value[*]}; do if [ ${gpu_id} = "null" ]; then if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then diff --git a/test_tipc/test_serving_infer_python.sh b/test_tipc/test_serving_infer_python.sh index 8bdb27bce7..1523f66551 100644 --- a/test_tipc/test_serving_infer_python.sh +++ b/test_tipc/test_serving_infer_python.sh @@ -107,8 +107,6 @@ function func_serving(){ python_list=(${python_list}) cd ${serving_dir_value} - unset https_proxy - unset http_proxy python=${python_list[0]} # python serving @@ -147,7 +145,7 @@ function func_serving(){ status_check $last_status "${pipeline_cmd}" "${status_log}" "${model_name}" sleep 2s done - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 + ps ux | grep -E 'web_service' | awk '{print $2}' | xargs kill -s 9 done done elif [ ${use_gpu} = "gpu" ]; then @@ -197,7 +195,7 @@ function func_serving(){ status_check $last_status "${pipeline_cmd}" "${status_log}" "${model_name}" sleep 2s done - ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 + ps ux | grep -E 'web_service' | awk '{print $2}' | xargs kill -s 9 done done else From c1510b6a295d560ebb926dcf3c16875f5a407331 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Wed, 8 Jun 2022 07:52:44 +0000 Subject: [PATCH 082/129] fix link --- doc/doc_ch/dataset/layout_datasets.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/doc_ch/dataset/layout_datasets.md b/doc/doc_ch/dataset/layout_datasets.md index e7055b4e60..728a9be5fd 100644 --- a/doc/doc_ch/dataset/layout_datasets.md +++ b/doc/doc_ch/dataset/layout_datasets.md @@ -15,8 +15,8 @@ - **数据简介**:publaynet数据集的训练集合中包含35万张图像,验证集合中包含1.1万张图像。总共包含5个类别,分别是: `text, title, list, table, figure`。部分图像以及标注框可视化如下所示。
- - + +
- **下载地址**:https://developer.ibm.com/exchanges/data/all/publaynet/ @@ -30,8 +30,8 @@ - **数据简介**:CDLA据集的训练集合中包含5000张图像,验证集合中包含1000张图像。总共包含10个类别,分别是: `Text, Title, Figure, Figure caption, Table, Table caption, Header, Footer, Reference, Equation`。部分图像以及标注框可视化如下所示。
- - + +
- **下载地址**:https://github.com/buptlihang/CDLA @@ -45,8 +45,8 @@ - **数据简介**:TableBank数据集包含Latex(训练集187199张,验证集7265张,测试集5719张)与Word(训练集73383张,验证集2735张,测试集2281张)两种类别的文档。仅包含`Table` 1个类别。部分图像以及标注框可视化如下所示。
- - + +
- **下载地址**:https://doc-analysis.github.io/tablebank-page/index.html From b821882c760c7a0ad1e058bae539804939d82a8f Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Thu, 9 Jun 2022 10:50:01 +0800 Subject: [PATCH 083/129] fix export and kie backbone (#6525) --- ppocr/modeling/backbones/kie_unet_sdmgr.py | 7 +------ tools/export_model.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ppocr/modeling/backbones/kie_unet_sdmgr.py b/ppocr/modeling/backbones/kie_unet_sdmgr.py index 793c68c6dd..4b1bd80300 100644 --- a/ppocr/modeling/backbones/kie_unet_sdmgr.py +++ b/ppocr/modeling/backbones/kie_unet_sdmgr.py @@ -176,11 +176,6 @@ class Kie_backbone(nn.Layer): x = self.img_feat(img) boxes, rois_num = self.bbox2roi(gt_bboxes) feats = paddle.vision.ops.roi_align( - x, - boxes, - spatial_scale=1.0, - pooled_height=7, - pooled_width=7, - rois_num=rois_num) + x, boxes, spatial_scale=1.0, output_size=7, boxes_num=rois_num) feats = self.maxpool(feats).squeeze(-1).squeeze(-1) return [relations, texts, feats] diff --git a/tools/export_model.py b/tools/export_model.py index c0cbcd361c..3ea0228f85 100755 --- a/tools/export_model.py +++ b/tools/export_model.py @@ -76,7 +76,7 @@ def export_single_model(model, arch_config, save_path, logger, quanter=None): else: infer_shape = [3, -1, -1] if arch_config["model_type"] == "rec": - infer_shape = [3, 32, -1] # for rec model, H must be 32 + infer_shape = [3, 48, -1] # for rec model, H must be 32 if "Transform" in arch_config and arch_config[ "Transform"] is not None and arch_config["Transform"][ "name"] == "TPS": From da944891f6de2b658ff6d6562d85b68c043875be Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 9 Jun 2022 09:20:57 +0000 Subject: [PATCH 084/129] fix_amp --- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 4 +- ..._normal_amp_infer_python_linux_gpu_cpu.txt | 2 +- ...u_fleet_amp_infer_python_linux_gpu_cpu.txt | 51 ------------------ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ------------------- 4 files changed, 3 insertions(+), 107 deletions(-) delete mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_amp_infer_python_linux_gpu_cpu.txt delete mode 100644 test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index 68888082c3..99e3c42477 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 Global.pretrained_model:null @@ -41,7 +41,7 @@ inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 ---rec_batch_num:1|6 +--rec_batch_num:6 --use_tensorrt:False --precision:fp32 --rec_model_dir: diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt index c00e6c4e4b..c93b307deb 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -41,7 +41,7 @@ inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu:True|False --enable_mkldnn:False --cpu_threads:6 ---rec_batch_num:1|6 +--rec_batch_num:6 --use_tensorrt:False --precision:fp32 --rec_model_dir: diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index bfb71b7810..0000000000 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,51 +0,0 @@ -===========================train_params=========================== -model_name:ocr_det -python:python3.7 -gpu_list:xx.xx.xx.xx,yy.yy.yy.yy;0,1 -Global.use_gpu:True -Global.auto_cast:fp32|amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=300 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 -Global.pretrained_model:null -train_model_name:latest -train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ -null:null -## -trainer:norm_train|pact_train|fpgm_train -norm_train:tools/train.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained -pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o -fpgm_train:deploy/slim/prune/sensitivity_anal.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/det_mv3_db_v2.0_train/best_accuracy -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.pretrained_model: -norm_export:tools/export_model.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o -quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o -fpgm_export:deploy/slim/prune/export_prune_model.py -c test_tipc/configs/ppocr_det_mobile/det_mv3_db.yml -o -distill_export:null -export1:null -export2:null -inference_dir:null -train_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy -infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o -infer_quant:False -inference:tools/infer/predict_det.py ---use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 ---rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ -null:null ---benchmark:True -null:null diff --git a/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index c4bf14778b..0000000000 --- a/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:en_table_structure -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 -Global.pretrained_model:./inference/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy -train_model_name:latest -train_infer_img_dir:./ppstructure/docs/table/table.jpg -null:null -## -trainer:norm_train -norm_train:tools/train.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o -pact_train:null -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:tools/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o -quant_export: -fpgm_export: -distill_export:null -export1:null -export2:null -## -infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer -infer_export:null -infer_quant:False -inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1 ---use_tensorrt:False ---precision:fp32 ---table_model_dir: ---image_dir:./ppstructure/docs/table/table.jpg -null:null ---benchmark:False -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,488,488]}] From 749728ea4ebe67039171675a3e89e2d474323d79 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Fri, 10 Jun 2022 13:55:27 +0800 Subject: [PATCH 085/129] fix fleet name (#6546) --- ...linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt} | 0 test_tipc/docs/test_train_fleet_inference_python.md | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) rename test_tipc/configs/ch_PP-OCRv3_rec/{train_fleet_infer_python.txt => train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt} (100%) diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/docs/test_train_fleet_inference_python.md b/test_tipc/docs/test_train_fleet_inference_python.md index 89cf5d5b6d..4479a47da8 100644 --- a/test_tipc/docs/test_train_fleet_inference_python.md +++ b/test_tipc/docs/test_train_fleet_inference_python.md @@ -31,10 +31,10 @@ Linux GPU/CPU 多机多卡训练推理测试的主程序为`test_train_inference #### 2.1.2 准备数据 -运行`prepare.sh`准备数据和模型,以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt`为例,数据准备命令如下所示。 +运行`prepare.sh`准备数据和模型,以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt`为例,数据准备命令如下所示。 ```shell -bash test_tipc/prepare.sh test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt lite_train_lite_infer +bash test_tipc/prepare.sh test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt lite_train_lite_infer ``` **注意:** 由于是多机训练,这里需要在所有的节点上均运行启动上述命令,准备数据。 @@ -47,10 +47,10 @@ bash test_tipc/prepare.sh test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_py export FLAGS_START_PORT=17000 ``` -以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt`为例,测试方法如下所示。 +以配置文件`test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt`为例,测试方法如下所示。 ```shell -bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec/train_fleet_infer_python.txt lite_train_lite_infer +bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt lite_train_lite_infer ``` **注意:** 由于是多机训练,这里需要在所有的节点上均运行启动上述命令进行测试。 From bd097dbe76d59221562cf23783f75fe2dfe7487d Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Fri, 10 Jun 2022 06:45:02 +0000 Subject: [PATCH 086/129] infer_python --- ...linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 6 +++--- ...linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 6 +++--- ...linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 6 +++--- .../model_linux_gpu_normal_normal_infer_python_jetson.txt | 8 ++++---- .../train_mac_cpu_normal_normal_infer_python_mac_cpu.txt | 2 +- ...ows_gpu_normal_normal_infer_python_windows_cpu_gpu.txt | 6 +++--- ...linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt | 4 ++-- test_tipc/test_inference_python.sh | 6 +++--- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index fcac6e3984..32b290a9ed 100644 --- a/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -6,10 +6,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_system.py --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index a044826501..afacdc1405 100644 --- a/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -6,10 +6,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_system.py --rec_image_shape="3,48,320" --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 4a46f0cf09..becad991ea 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -6,10 +6,10 @@ infer_export:null infer_quant:False inference:tools/infer/predict_system.py --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_python_jetson.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_python_jetson.txt index 7d3f60bd42..24bb8746ab 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_python_jetson.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/model_linux_gpu_normal_normal_infer_python_jetson.txt @@ -1,5 +1,5 @@ ===========================infer_params=========================== -model_name:ocr_det +model_name:ch_ppocr_mobile_v2.0_det python:python infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer infer_export:null @@ -7,10 +7,10 @@ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False --enable_mkldnn:False ---cpu_threads:1|6 +--cpu_threads:6 --rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp16|fp32 +--use_tensorrt:False +--precision:fp32 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ null:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_mac_cpu_normal_normal_infer_python_mac_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_mac_cpu_normal_normal_infer_python_mac_cpu.txt index 014dad5fc9..3f321a1903 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_mac_cpu_normal_normal_infer_python_mac_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_mac_cpu_normal_normal_infer_python_mac_cpu.txt @@ -4,7 +4,7 @@ python:python gpu_list:-1 Global.use_gpu:False Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_windows_gpu_normal_normal_infer_python_windows_cpu_gpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_windows_gpu_normal_normal_infer_python_windows_cpu_gpu.txt index 6a63b39d97..a3f6933a64 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_windows_gpu_normal_normal_infer_python_windows_cpu_gpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_windows_gpu_normal_normal_infer_python_windows_cpu_gpu.txt @@ -4,7 +4,7 @@ python:python gpu_list:0 Global.use_gpu:True Global.auto_cast:fp32|amp -Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=300 +Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=50 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -39,10 +39,10 @@ infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2 infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False ---enable_mkldnn:True|False +--enable_mkldnn:False --cpu_threads:1|6 --rec_batch_num:1 ---use_tensorrt:False|True +--use_tensorrt:False --precision:fp32|fp16|int8 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ diff --git a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt index 92d7031e88..b20596f7a1 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -6,8 +6,8 @@ infer_export:null infer_quant:True inference:tools/infer/predict_system.py --use_gpu:False|True ---enable_mkldnn:False|True ---cpu_threads:1|6 +--enable_mkldnn:False +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False --precision:fp32 diff --git a/test_tipc/test_inference_python.sh b/test_tipc/test_inference_python.sh index a416d623d8..2a31a468f0 100644 --- a/test_tipc/test_inference_python.sh +++ b/test_tipc/test_inference_python.sh @@ -88,7 +88,7 @@ function func_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done done @@ -119,7 +119,7 @@ function func_inference(){ eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" - status_check $last_status "${command}" "${status_log}" + status_check $last_status "${command}" "${status_log}" "${model_name}" done done @@ -153,7 +153,7 @@ if [ ${MODE} = "whole_infer" ]; then echo ${infer_run_exports[Count]} eval $export_cmd status_export=$? - status_check $status_export "${export_cmd}" "${status_log}" + status_check $status_export "${export_cmd}" "${status_log}" "${model_name}" else save_infer_dir=${infer_model} fi From 60599a1db4ff3fec972d9fef3697024f889fd5e3 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Fri, 10 Jun 2022 08:01:48 +0000 Subject: [PATCH 087/129] fix timeout tipc --- .../ch_PP-OCRv3_rec_distillation.yml | 4 +- test_tipc/prepare.sh | 40 +++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml index 4c8ba0a6fa..f704a1dfb5 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml +++ b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml @@ -153,7 +153,7 @@ Train: data_dir: ./train_data/ic15_data/ ext_op_transform_idx: 1 label_file_list: - - ./train_data/ic15_data/rec_gt_train.txt + - ./train_data/ic15_data/rec_gt_train_lite.txt transforms: - DecodeImage: img_mode: BGR @@ -183,7 +183,7 @@ Eval: name: SimpleDataSet data_dir: ./train_data/ic15_data label_file_list: - - ./train_data/ic15_data/rec_gt_test.txt + - ./train_data/ic15_data/rec_gt_test_lite.txt transforms: - DecodeImage: img_mode: BGR diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index daf6a32961..65ac2bbebb 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -52,16 +52,24 @@ if [ ${MODE} = "lite_train_lite_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi + if [ ${model_name} == "en_table_structure" ];then + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + fi cd ./pretrain_models/ && tar xf det_mv3_db_v2.0_train.tar && cd ../ rm -rf ./train_data/icdar2015 rm -rf ./train_data/ic15_data + rm -rf ./train_data/pubtabnet wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015_lite.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate + wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dataset/pubtabnet.tar --no-check-certificate wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./deploy/slim/prune https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/sen.pickle --no-check-certificate - cd ./train_data/ && tar xf icdar2015_lite.tar && tar xf ic15_data.tar + cd ./train_data/ && tar xf icdar2015_lite.tar && tar xf ic15_data.tar && tar xf pubtabnet.tar ln -s ./icdar2015_lite ./icdar2015 + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_train_lite.txt --no-check-certificate + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_test_lite.txt --no-check-certificate cd ../ cd ./inference && tar xf rec_inference.tar && cd ../ if [ ${model_name} == "ch_PP-OCRv2_det" ] || [ ${model_name} == "ch_PP-OCRv2_det_PACT" ]; then @@ -112,9 +120,14 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams --no-check-certificate rm -rf ./train_data/icdar2015 rm -rf ./train_data/ic15_data + rm -rf ./train_data/pubtabnet wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate - cd ./train_data/ && tar xf icdar2015.tar && tar xf ic15_data.tar && cd ../ + wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dataset/pubtabnet.tar --no-check-certificate + cd ./train_data/ && tar xf icdar2015.tar && tar xf ic15_data.tar && tar xf pubtabnet.tar + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_train_lite.txt --no-check-certificate + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_test_lite.txt --no-check-certificate + cd ../ if [ ${model_name} == "ch_PP-OCRv2_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv2_det_distill_train.tar && cd ../ @@ -134,14 +147,22 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/total_text_lite.tar --no-check-certificate cd ./train_data && tar xf total_text.tar && ln -s total_text_lite total_text && cd ../ fi + if [ ${model_name} == "en_table_structure" ];then + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + fi elif [ ${MODE} = "lite_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams --no-check-certificate rm -rf ./train_data/icdar2015 rm -rf ./train_data/ic15_data + rm -rf ./train_data/pubtabnet wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015_infer.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate - cd ./train_data/ && tar xf icdar2015_infer.tar && tar xf ic15_data.tar + wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dataset/pubtabnet.tar --no-check-certificate + cd ./train_data/ && tar xf icdar2015_infer.tar && tar xf ic15_data.tar && tar xf pubtabnet.tar ln -s ./icdar2015_infer ./icdar2015 + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_train_lite.txt --no-check-certificate + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_test_lite.txt --no-check-certificate cd ../ if [ ${model_name} == "ch_PP-OCRv2_det" ]; then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar --no-check-certificate @@ -151,6 +172,10 @@ elif [ ${MODE} = "lite_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi + if [ ${model_name} == "en_table_structure" ];then + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate + cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + fi elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate @@ -310,6 +335,10 @@ elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_east_v2.0_train.tar --no-check-certificate cd ./inference/ && tar xf det_r50_vd_east_v2.0_train.tar & cd ../ fi + if [ ${model_name} == "en_table_structure" ];then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_structure_infer.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_structure_infer.tar && cd ../ + fi fi if [ ${MODE} = "klquant_whole_infer" ]; then @@ -331,7 +360,10 @@ if [ ${MODE} = "klquant_whole_infer" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar --no-check-certificate wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate - cd ./train_data/ && tar xf ic15_data.tar && cd ../ + cd ./train_data/ && tar xf ic15_data.tar + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_train_lite.txt --no-check-certificate + wget -nc -P ./ic15_data/ https://paddleocr.bj.bcebos.com/dataset/rec_gt_test_lite.txt --no-check-certificate + cd ../ cd ./inference && tar xf rec_inference.tar && tar xf ch_PP-OCRv3_rec_infer.tar && cd ../ fi if [ ${model_name} = "ch_PP-OCRv2_det_KL" ]; then From 44086577ebd8fd73aa5dc7bc137ce31b9c7399b3 Mon Sep 17 00:00:00 2001 From: an1018 <614803115@qq.com> Date: Fri, 10 Jun 2022 19:56:45 +0800 Subject: [PATCH 088/129] add pcb --- applications/PCB字符识别/PCB字符识别.md | 648 ++++++++++++++++++ .../PCB字符识别/gen_data/background/bg.jpg | Bin 0 -> 2071 bytes .../PCB字符识别/gen_data/corpus/text.txt | 30 + .../PCB字符识别/gen_data/det_background/1.png | Bin 0 -> 145 bytes .../PCB字符识别/gen_data/det_background/2.png | Bin 0 -> 141 bytes applications/PCB字符识别/gen_data/gen.py | 261 +++++++ 6 files changed, 939 insertions(+) create mode 100644 applications/PCB字符识别/PCB字符识别.md create mode 100644 applications/PCB字符识别/gen_data/background/bg.jpg create mode 100644 applications/PCB字符识别/gen_data/corpus/text.txt create mode 100644 applications/PCB字符识别/gen_data/det_background/1.png create mode 100644 applications/PCB字符识别/gen_data/det_background/2.png create mode 100644 applications/PCB字符识别/gen_data/gen.py diff --git a/applications/PCB字符识别/PCB字符识别.md b/applications/PCB字符识别/PCB字符识别.md new file mode 100644 index 0000000000..a5052e2897 --- /dev/null +++ b/applications/PCB字符识别/PCB字符识别.md @@ -0,0 +1,648 @@ +# 基于PP-OCRv3的PCB字符识别 + +- [1. 项目介绍](#1-项目介绍) +- [2. 安装说明](#2-安装说明) +- [3. 数据准备](#3-数据准备) +- [4. 文本检测](#4-文本检测) + - [4.1 预训练模型直接评估](#41-预训练模型直接评估) + - [4.2 预训练模型+验证集padding直接评估](#42-预训练模型验证集padding直接评估) + - [4.3 预训练模型+fine-tune](#43-预训练模型fine-tune) +- [5. 文本识别](#5-文本识别) + - [5.1 预训练模型直接评估](#51-预训练模型直接评估) + - [5.2 三种fine-tune方案](#52-三种fine-tune方案) +- [6. 模型导出](#6-模型导出) +- [7. 端对端评测](#7-端对端评测) +- [8. Jetson部署](#8-Jetson部署) +- [9. 总结](#9-总结) +- [更多资源](#更多资源) + +# 1. 项目介绍 + +印刷电路板(PCB)是电子产品中的核心器件,对于板件质量的测试与监控是生产中必不可少的环节。在一些场景中,通过PCB中信号灯颜色和文字组合可以定位PCB局部模块质量问题,PCB文字识别中存在如下难点: + +- 裁剪出的PCB图片宽高比例较小 +- 文字区域整体面积也较小 +- 包含垂直、水平多种方向文本 + +针对本场景,PaddleOCR基于全新的PP-OCRv3通过合成数据、微调以及其他场景适配方法完成小字符文本识别任务,满足企业上线要求。PCB检测、识别效果如 **图1** 所示: + +
+
图1 PCB检测识别效果
+ +注:欢迎在AIStudio领取免费算力体验线上实训,项目链接: [基于PP-OCRv3实现PCB字符识别](https://aistudio.baidu.com/aistudio/projectdetail/4008973) + +# 2. 安装说明 + + +下载PaddleOCR源码,安装依赖环境。 + + +```python +# 如仍需安装or安装更新,可以执行以下步骤 +git clone https://github.com/PaddlePaddle/PaddleOCR.git +# git clone https://gitee.com/PaddlePaddle/PaddleOCR +``` + + +```python +# 安装依赖包 +pip install -r /home/aistudio/PaddleOCR/requirements.txt +``` + +# 3. 数据准备 + +我们通过图片合成工具生成 **图2** 所示的PCB图片,整图只有高25、宽150左右、文字区域高9、宽45左右,包含垂直和水平2种方向的文本: + +
+
图2 数据集示例
+ +暂时不开源生成的PCB数据集,但是通过更换背景,通过如下代码生成数据即可: + +``` +cd gen_data +python3 gen.py --num_img=10 +``` + +生成图片参数解释: + +``` +num_img:生成图片数量 +font_min_size、font_max_size:字体最大、最小尺寸 +bg_path:文字区域背景存放路径 +det_bg_path:整图背景存放路径 +fonts_path:字体路径 +corpus_path:语料路径 +output_dir:生成图片存储路径 +``` + +这里生成 **100张** 相同尺寸和文本的图片,如 **图3** 所示,方便大家跑通实验。通过如下代码解压数据集: + +
+
图3 案例提供数据集示例
+ + +```python +tar xf ./data/data148165/dataset.tar -C ./ +``` + +在生成数据集的时需要生成检测和识别训练需求的格式: + + +- **文本检测** + +标注文件格式如下,中间用'\t'分隔: + +``` +" 图像文件名 json.dumps编码的图像标注信息" +ch4_test_images/img_61.jpg [{"transcription": "MASA", "points": [[310, 104], [416, 141], [418, 216], [312, 179]]}, {...}] +``` + +json.dumps编码前的图像标注信息是包含多个字典的list,字典中的 `points` 表示文本框的四个点的坐标(x, y),从左上角的点开始顺时针排列。 `transcription` 表示当前文本框的文字,***当其内容为“###”时,表示该文本框无效,在训练时会跳过。*** + +- **文本识别** + +标注文件的格式如下, txt文件中默认请将图片路径和图片标签用'\t'分割,如用其他方式分割将造成训练报错。 + +``` +" 图像文件名 图像标注信息 " + +train_data/rec/train/word_001.jpg 简单可依赖 +train_data/rec/train/word_002.jpg 用科技让复杂的世界更简单 +... +``` + + +# 4. 文本检测 + +选用飞桨OCR开发套件[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)中的PP-OCRv3模型进行文本检测和识别。针对检测模型和识别模型,进行了共计9个方面的升级: + +- PP-OCRv3检测模型对PP-OCRv2中的CML协同互学习文本检测蒸馏策略进行了升级,分别针对教师模型和学生模型进行进一步效果优化。其中,在对教师模型优化时,提出了大感受野的PAN结构LK-PAN和引入了DML蒸馏策略;在对学生模型优化时,提出了残差注意力机制的FPN结构RSE-FPN。 + +- PP-OCRv3的识别模块是基于文本识别算法SVTR优化。SVTR不再采用RNN结构,通过引入Transformers结构更加有效地挖掘文本行图像的上下文信息,从而提升文本识别能力。PP-OCRv3通过轻量级文本识别网络SVTR_LCNet、Attention损失指导CTC损失训练策略、挖掘文字上下文信息的数据增广策略TextConAug、TextRotNet自监督预训练模型、UDML联合互学习策略、UIM无标注数据挖掘方案,6个方面进行模型加速和效果提升。 + +更多细节请参考PP-OCRv3[技术报告](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/PP-OCRv3_introduction.md)。 + + +我们使用 **3种方案** 进行检测模型的训练、评估: +- **PP-OCRv3英文超轻量检测预训练模型直接评估** +- PP-OCRv3英文超轻量检测预训练模型 + **验证集padding**直接评估 +- PP-OCRv3英文超轻量检测预训练模型 + **fine-tune** + +## **4.1 预训练模型直接评估** + +我们首先通过PaddleOCR提供的预训练模型在验证集上进行评估,如果评估指标能满足效果,可以直接使用预训练模型,不再需要训练。 + +使用预训练模型直接评估步骤如下: + +**1)下载预训练模型** + + +PaddleOCR已经提供了PP-OCR系列模型,部分模型展示如下表所示: + +| 模型简介 | 模型名称 | 推荐场景 | 检测模型 | 方向分类器 | 识别模型 | +| ------------------------------------- | ----------------------- | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 中英文超轻量PP-OCRv3模型(16.2M) | ch_PP-OCRv3_xx | 移动端&服务器端 | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar) | +| 英文超轻量PP-OCRv3模型(13.4M) | en_PP-OCRv3_xx | 移动端&服务器端 | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_det_distill_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_train.tar) | +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx | 移动端&服务器端 | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | +| 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx | 移动端&服务器端 | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | +| 中英文通用PP-OCR server模型(143.4M) | ch_ppocr_server_v2.0_xx | 服务器端 | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | + +更多模型下载(包括多语言),可以参[考PP-OCR系列模型下载](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/models_list.md) + +这里我们使用PP-OCRv3英文超轻量检测模型,下载并解压预训练模型: + + + + +```python +# 如果更换其他模型,更新下载链接和解压指令就可以 +cd /home/aistudio/PaddleOCR +mkdir pretrain_models +cd pretrain_models +# 下载英文预训练模型 +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_det_distill_train.tar +tar xf en_PP-OCRv3_det_distill_train.tar && rm -rf en_PP-OCRv3_det_distill_train.tar +%cd .. +``` + +**模型评估** + + +首先修改配置文件`configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml`中的以下字段: +``` +Eval.dataset.data_dir:指向验证集图片存放目录,'/home/aistudio/dataset' +Eval.dataset.label_file_list:指向验证集标注文件,'/home/aistudio/dataset/det_gt_val.txt' +Eval.dataset.transforms.DetResizeForTest: 尺寸 + limit_side_len: 48 + limit_type: 'min' +``` + +然后在验证集上进行评估,具体代码如下: + + + +```python +cd /home/aistudio/PaddleOCR +python tools/eval.py \ + -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.checkpoints="./pretrain_models/en_PP-OCRv3_det_distill_train/best_accuracy" +``` + +## **4.2 预训练模型+验证集padding直接评估** + +考虑到PCB图片比较小,宽度只有25左右、高度只有140-170左右,我们在原图的基础上进行padding,再进行检测评估,padding前后效果对比如 **图4** 所示: + +
+
图4 padding前后对比图
+ +将图片都padding到300*300大小,因为坐标信息发生了变化,我们同时要修改标注文件,在`/home/aistudio/dataset`目录里也提供了padding之后的图片,大家也可以尝试训练和评估: + +同上,我们需要修改配置文件`configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml`中的以下字段: +``` +Eval.dataset.data_dir:指向验证集图片存放目录,'/home/aistudio/dataset' +Eval.dataset.label_file_list:指向验证集标注文件,/home/aistudio/dataset/det_gt_padding_val.txt +Eval.dataset.transforms.DetResizeForTest: 尺寸 + limit_side_len: 1100 + limit_type: 'min' +``` + +然后执行评估代码 + + +```python +cd /home/aistudio/PaddleOCR +python tools/eval.py \ + -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.checkpoints="./pretrain_models/en_PP-OCRv3_det_distill_train/best_accuracy" +``` + +## **4.3 预训练模型+fine-tune** + + +基于预训练模型,在生成的1500图片上进行fine-tune训练和评估,其中train数据1200张,val数据300张,修改配置文件`configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml`中的以下字段: +``` +Global.epoch_num: 这里设置为1,方便快速跑通,实际中根据数据量调整该值 +Global.save_model_dir:模型保存路径 +Global.pretrained_model:指向预训练模型路径,'./pretrain_models/en_PP-OCRv3_det_distill_train/student.pdparams' +Optimizer.lr.learning_rate:调整学习率,本实验设置为0.0005 +Train.dataset.data_dir:指向训练集图片存放目录,'/home/aistudio/dataset' +Train.dataset.label_file_list:指向训练集标注文件,'/home/aistudio/dataset/det_gt_train.txt' +Train.dataset.transforms.EastRandomCropData.size:训练尺寸改为[480,64] +Eval.dataset.data_dir:指向验证集图片存放目录,'/home/aistudio/dataset/' +Eval.dataset.label_file_list:指向验证集标注文件,'/home/aistudio/dataset/det_gt_val.txt' +Eval.dataset.transforms.DetResizeForTest:评估尺寸,添加如下参数 + limit_side_len: 64 + limit_type:'min' +``` +执行下面命令启动训练: + + +```python +cd /home/aistudio/PaddleOCR/ +python tools/train.py \ + -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml +``` + +**模型评估** + + +使用训练好的模型进行评估,更新模型路径`Global.checkpoints`: + + +```python +cd /home/aistudio/PaddleOCR/ +python3 tools/eval.py \ + -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.checkpoints="./output/ch_PP-OCR_V3_det/latest" +``` + +使用训练好的模型进行评估,指标如下所示: + + +| 序号 | 方案 | hmean | 效果提升 | 实验分析 | +| -------- | -------- | -------- | -------- | -------- | +| 1 | PP-OCRv3英文超轻量检测预训练模型 | 64.64% | - | 提供的预训练模型具有泛化能力 | +| 2 | PP-OCRv3英文超轻量检测预训练模型 + 验证集padding | 72.13% |+7.5% | padding可以提升尺寸较小图片的检测效果| +| 3 | PP-OCRv3英文超轻量检测预训练模型 + fine-tune | 100% | +27.9% | fine-tune会提升垂类场景效果 | + + +``` +注:上述实验结果均是在1500张图片(1200张训练集,300张测试集)上训练、评估的得到,AIstudio只提供了100张数据,所以指标有所差异属于正常,只要策略有效、规律相同即可。 +``` + +# 5. 文本识别 + +我们分别使用如下4种方案进行训练、评估: + +- **方案1**:**PP-OCRv3中英文超轻量识别预训练模型直接评估** +- **方案2**:PP-OCRv3中英文超轻量检测预训练模型 + **fine-tune** +- **方案3**:PP-OCRv3中英文超轻量检测预训练模型 + fine-tune + **公开通用识别数据集** +- **方案4**:PP-OCRv3中英文超轻量检测预训练模型 + fine-tune + **增加PCB图像数量** + + +## **5.1 预训练模型直接评估** + +同检测模型,我们首先使用PaddleOCR提供的识别预训练模型在PCB验证集上进行评估。 + +使用预训练模型直接评估步骤如下: + +**1)下载预训练模型** + + +我们使用PP-OCRv3中英文超轻量文本识别模型,下载并解压预训练模型: + + +```python +# 如果更换其他模型,更新下载链接和解压指令就可以 +cd /home/aistudio/PaddleOCR/pretrain_models/ +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar +tar xf ch_PP-OCRv3_rec_train.tar && rm -rf ch_PP-OCRv3_rec_train.tar +cd .. +``` + +**模型评估** + + +首先修改配置文件`configs/det/ch_PP-OCRv3/ch_PP-OCRv2_rec_distillation.yml`中的以下字段: + +``` +Metric.ignore_space: True:忽略空格 +Eval.dataset.data_dir:指向验证集图片存放目录,'/home/aistudio/dataset' +Eval.dataset.label_file_list:指向验证集标注文件,'/home/aistudio/dataset/rec_gt_val.txt' +``` + +我们使用下载的预训练模型进行评估: + + +```python +cd /home/aistudio/PaddleOCR +python3 tools/eval.py \ + -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml \ + -o Global.checkpoints=pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy + +``` + +## **5.2 三种fine-tune方案** + +方案2、3、4训练和评估方式是相同的,因此在我们了解每个技术方案之后,再具体看修改哪些参数是相同,哪些是不同的。 + +**方案介绍:** + +1) **方案2**:预训练模型 + **fine-tune** + +- 在预训练模型的基础上进行fine-tune,使用1500张PCB进行训练和评估,其中训练集1200张,验证集300张。 + + +2) **方案3**:预训练模型 + fine-tune + **公开通用识别数据集** + +- 当识别数据比较少的情况,可以考虑添加公开通用识别数据集。在方案2的基础上,添加公开通用识别数据集,如lsvt、rctw等。 + +3)**方案4**:预训练模型 + fine-tune + **增加PCB图像数量** + +- 如果能够获取足够多真实场景,我们可以通过增加数据量提升模型效果。在方案2的基础上,增加PCB的数量到2W张左右。 + + +**参数修改:** + +接着我们看需要修改的参数,以上方案均需要修改配置文件`configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml`的参数,**修改一次即可**: + +``` +Global.pretrained_model:指向预训练模型路径,'pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy' +Optimizer.lr.values:学习率,本实验设置为0.0005 +Train.loader.batch_size_per_card: batch size,默认128,因为数据量小于128,因此我们设置为8,数据量大可以按默认的训练 +Eval.loader.batch_size_per_card: batch size,默认128,设置为4 +Metric.ignore_space: 忽略空格,本实验设置为True +``` + +**更换不同的方案**每次需要修改的参数: +``` +Global.epoch_num: 这里设置为1,方便快速跑通,实际中根据数据量调整该值 +Global.save_model_dir:指向模型保存路径 +Train.dataset.data_dir:指向训练集图片存放目录 +Train.dataset.label_file_list:指向训练集标注文件 +Eval.dataset.data_dir:指向验证集图片存放目录 +Eval.dataset.label_file_list:指向验证集标注文件 +``` + +同时**方案3**修改以下参数 +``` +Eval.dataset.label_file_list:添加公开通用识别数据标注文件 +Eval.dataset.ratio_list:数据和公开通用识别数据每次采样比例,按实际修改即可 +``` +如 **图5** 所示: +
+
图5 添加公开通用识别数据配置文件示例
+ + +我们提取Student模型的参数,在PCB数据集上进行fine-tune,可以参考如下代码: + + +```python +import paddle +# 加载预训练模型 +all_params = paddle.load("./pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 学生模型的权重提取 +s_params = {key[len("student_model."):]: all_params[key] for key in all_params if "student_model." in key} +# 查看学生模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./pretrain_models/ch_PP-OCRv3_rec_train/student.pdparams") +``` + +修改参数后,**每个方案**都执行如下命令启动训练: + + + +```python +cd /home/aistudio/PaddleOCR/ +python3 tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml +``` + + +使用训练好的模型进行评估,更新模型路径`Global.checkpoints`: + + +```python +cd /home/aistudio/PaddleOCR/ +python3 tools/eval.py \ + -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml \ + -o Global.checkpoints=./output/rec_ppocr_v3/latest +``` + +所有方案评估指标如下: + +| 序号 | 方案 | acc | 效果提升 | 实验分析 | +| -------- | -------- | -------- | -------- | -------- | +| 1 | PP-OCRv3中英文超轻量识别预训练模型直接评估 | 46.67% | - | 提供的预训练模型具有泛化能力 | +| 2 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune | 42.02% |-4.6% | 在数据量不足的情况,反而比预训练模型效果低(也可以通过调整超参数再试试)| +| 3 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune + 公开通用识别数据集 | 77% | +30% | 在数据量不足的情况下,可以考虑补充公开数据训练 | +| 4 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune + 增加PCB图像数量 | 99.99% | +23% | 如果能获取更多数据量的情况,可以通过增加数据量提升效果 | + +``` +注:上述实验结果均是在1500张图片(1200张训练集,300张测试集)、2W张图片、添加公开通用识别数据集上训练、评估的得到,AIstudio只提供了100张数据,所以指标有所差异属于正常,只要策略有效、规律相同即可。 +``` + +# 6. 模型导出 + +inference 模型(paddle.jit.save保存的模型) 一般是模型训练,把模型结构和模型参数保存在文件中的固化模型,多用于预测部署场景。 训练过程中保存的模型是checkpoints模型,保存的只有模型的参数,多用于恢复训练等。 与checkpoints模型相比,inference 模型会额外保存模型的结构信息,在预测部署、加速推理上性能优越,灵活方便,适合于实际系统集成。 + + +```python +# 导出检测模型 +python3 tools/export_model.py \ + -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.pretrained_model="./output/ch_PP-OCR_V3_det/latest" \ + Global.save_inference_dir="./inference_model/ch_PP-OCR_V3_det/" +``` + +因为上述模型只训练了1个epoch,因此我们使用训练最优的模型进行预测,存储在`/home/aistudio/best_models/`目录下,解压即可 + + +```python +cd /home/aistudio/best_models/ +wget https://paddleocr.bj.bcebos.com/fanliku/PCB/det_ppocr_v3_en_infer_PCB.tar +tar xf /home/aistudio/best_models/det_ppocr_v3_en_infer_PCB.tar -C /home/aistudio/PaddleOCR/pretrain_models/ +``` + + +```python +# 检测模型inference模型预测 +cd /home/aistudio/PaddleOCR/ +python3 tools/infer/predict_det.py \ + --image_dir="/home/aistudio/dataset/imgs/0000.jpg" \ + --det_algorithm="DB" \ + --det_model_dir="./pretrain_models/det_ppocr_v3_en_infer_PCB/" \ + --det_limit_side_len=48 \ + --det_limit_type='min' \ + --det_db_unclip_ratio=2.5 \ + --use_gpu=True +``` + +结果存储在`inference_results`目录下,检测如下图所示: +
+
图6 检测结果
+ + +同理,导出识别模型并进行推理。 + +```python +# 导出识别模型 +python3 tools/export_model.py \ + -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml \ + -o Global.pretrained_model="./output/rec_ppocr_v3/latest" \ + Global.save_inference_dir="./inference_model/rec_ppocr_v3/" + +``` + +同检测模型,识别模型也只训练了1个epoch,因此我们使用训练最优的模型进行预测,存储在`/home/aistudio/best_models/`目录下,解压即可 + + +```python +cd /home/aistudio/best_models/ +wget https://paddleocr.bj.bcebos.com/fanliku/PCB/rec_ppocr_v3_ch_infer_PCB.tar +tar xf /home/aistudio/best_models/rec_ppocr_v3_ch_infer_PCB.tar -C /home/aistudio/PaddleOCR/pretrain_models/ +``` + + +```python +# 识别模型inference模型预测 +cd /home/aistudio/PaddleOCR/ +python3 tools/infer/predict_rec.py \ + --image_dir="../test_imgs/0000_rec.jpg" \ + --rec_model_dir="./pretrain_models/rec_ppocr_v3_ch_infer_PCB" \ + --rec_image_shape="3, 48, 320" \ + --use_space_char=False \ + --use_gpu=True +``` + +```python +# 检测+识别模型inference模型预测 +cd /home/aistudio/PaddleOCR/ +python3 tools/infer/predict_system.py \ + --image_dir="../test_imgs/0000.jpg" \ + --det_model_dir="./pretrain_models/det_ppocr_v3_en_infer_PCB" \ + --det_limit_side_len=48 \ + --det_limit_type='min' \ + --det_db_unclip_ratio=2.5 \ + --rec_model_dir="./pretrain_models/rec_ppocr_v3_ch_infer_PCB" \ + --rec_image_shape="3, 48, 320" \ + --draw_img_save_dir=./det_rec_infer/ \ + --use_space_char=False \ + --use_angle_cls=False \ + --use_gpu=True + +``` + +端到端预测结果存储在`det_res_infer`文件夹内,结果如下图所示: +
+
图7 检测+识别结果
+ +# 7. 端对端评测 + +接下来介绍文本检测+文本识别的端对端指标评估方式。主要分为三步: + +1)首先运行`tools/infer/predict_system.py`,将`image_dir`改为需要评估的数据文件家,得到保存的结果: + + +```python +# 检测+识别模型inference模型预测 +python3 tools/infer/predict_system.py \ + --image_dir="../dataset/imgs/" \ + --det_model_dir="./pretrain_models/det_ppocr_v3_en_infer_PCB" \ + --det_limit_side_len=48 \ + --det_limit_type='min' \ + --det_db_unclip_ratio=2.5 \ + --rec_model_dir="./pretrain_models/rec_ppocr_v3_ch_infer_PCB" \ + --rec_image_shape="3, 48, 320" \ + --draw_img_save_dir=./det_rec_infer/ \ + --use_space_char=False \ + --use_angle_cls=False \ + --use_gpu=True +``` + +得到保存结果,文本检测识别可视化图保存在`det_rec_infer/`目录下,预测结果保存在`det_rec_infer/system_results.txt`中,格式如下:`0018.jpg [{"transcription": "E295", "points": [[88, 33], [137, 33], [137, 40], [88, 40]]}]` + +2)然后将步骤一保存的数据转换为端对端评测需要的数据格式: 修改 `tools/end2end/convert_ppocr_label.py`中的代码,convert_label函数中设置输入标签路径,Mode,保存标签路径等,对预测数据的GTlabel和预测结果的label格式进行转换。 +``` +ppocr_label_gt = "/home/aistudio/dataset/det_gt_val.txt" +convert_label(ppocr_label_gt, "gt", "./save_gt_label/") + +ppocr_label_gt = "/home/aistudio/PaddleOCR/PCB_result/det_rec_infer/system_results.txt" +convert_label(ppocr_label_gt, "pred", "./save_PPOCRV2_infer/") +``` + +运行`convert_ppocr_label.py`: + + +```python + python3 tools/end2end/convert_ppocr_label.py +``` + +得到如下结果: +``` +├── ./save_gt_label/ +├── ./save_PPOCRV2_infer/ +``` + +3) 最后,执行端对端评测,运行`tools/end2end/eval_end2end.py`计算端对端指标,运行方式如下: + + +```python +pip install editdistance +python3 tools/end2end/eval_end2end.py ./save_gt_label/ ./save_PPOCRV2_infer/ +``` + +使用`预训练模型+fine-tune'检测模型`、`预训练模型 + 2W张PCB图片funetune`识别模型,在300张PCB图片上评估得到如下结果,fmeasure为主要关注的指标: +
+
图8 端到端评估指标
+ +``` +注: 使用上述命令不能跑出该结果,因为数据集不相同,可以更换为自己训练好的模型,按上述流程运行 +``` + +# 8. Jetson部署 + +我们只需要以下步骤就可以完成Jetson nano部署模型,简单易操作: + +**1、在Jetson nano开发版上环境准备:** + +* 安装PaddlePaddle + +* 下载PaddleOCR并安装依赖 + +**2、执行预测** + +* 将推理模型下载到jetson + +* 执行检测、识别、串联预测即可 + +详细[参考流程](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/deploy/Jetson/readme_ch.md)。 + +# 9. 总结 + +检测实验分别使用PP-OCRv3预训练模型在PCB数据集上进行了直接评估、验证集padding、 fine-tune 3种方案,识别实验分别使用PP-OCRv3预训练模型在PCB数据集上进行了直接评估、 fine-tune、添加公开通用识别数据集、增加PCB图片数量4种方案,指标对比如下: + +* 检测 + + +| 序号 | 方案 | hmean | 效果提升 | 实验分析 | +| ---- | -------------------------------------------------------- | ------ | -------- | ------------------------------------- | +| 1 | PP-OCRv3英文超轻量检测预训练模型直接评估 | 64.64% | - | 提供的预训练模型具有泛化能力 | +| 2 | PP-OCRv3英文超轻量检测预训练模型 + 验证集padding直接评估 | 72.13% | +7.5% | padding可以提升尺寸较小图片的检测效果 | +| 3 | PP-OCRv3英文超轻量检测预训练模型 + fine-tune | 100% | +27.9% | fine-tune会提升垂类场景效果 | + +* 识别 + +| 序号 | 方案 | acc | 效果提升 | 实验分析 | +| ---- | ------------------------------------------------------------ | ------ | -------- | ------------------------------------------------------------ | +| 1 | PP-OCRv3中英文超轻量识别预训练模型直接评估 | 46.67% | - | 提供的预训练模型具有泛化能力 | +| 2 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune | 42.02% | -4.6% | 在数据量不足的情况,反而比预训练模型效果低(也可以通过调整超参数再试试) | +| 3 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune + 公开通用识别数据集 | 77% | +30% | 在数据量不足的情况下,可以考虑补充公开数据训练 | +| 4 | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune + 增加PCB图像数量 | 99.99% | +23% | 如果能获取更多数据量的情况,可以通过增加数据量提升效果 | + +* 端到端 + +| det | rec | fmeasure | +| --------------------------------------------- | ------------------------------------------------------------ | -------- | +| PP-OCRv3英文超轻量检测预训练模型 + fine-tune | PP-OCRv3中英文超轻量识别预训练模型 + fine-tune + 增加PCB图像数量 | 93.3% | + +*结论* + +PP-OCRv3的检测模型在未经过fine-tune的情况下,在PCB数据集上也有64.64%的精度,说明具有泛化能力。验证集padding之后,精度提升7.5%,在图片尺寸较小的情况,我们可以通过padding的方式提升检测效果。经过 fine-tune 后能够极大的提升检测效果,精度达到100%。 + +PP-OCRv3的识别模型方案1和方案2对比可以发现,当数据量不足的情况,预训练模型精度可能比fine-tune效果还要高,所以我们可以先尝试预训练模型直接评估。如果在数据量不足的情况下想进一步提升模型效果,可以通过添加公开通用识别数据集,识别效果提升30%,非常有效。最后如果我们能够采集足够多的真实场景数据集,可以通过增加数据量提升模型效果,精度达到99.99%。 + +# 更多资源 + +- 更多深度学习知识、产业案例、面试宝典等,请参考:[awesome-DeepLearning](https://github.com/paddlepaddle/awesome-DeepLearning) + +- 更多PaddleOCR使用教程,请参考:[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR/tree/dygraph) + + +- 飞桨框架相关资料,请参考:[飞桨深度学习平台](https://www.paddlepaddle.org.cn/?fr=paddleEdu_aistudio) + +# 参考 + +* 数据生成代码库:https://github.com/zcswdt/Color_OCR_image_generator diff --git a/applications/PCB字符识别/gen_data/background/bg.jpg b/applications/PCB字符识别/gen_data/background/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cb6eab819c3b7d4f68590d2cdc9d36351590197 GIT binary patch literal 2071 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!}nhriyF8_@n{%~rh(BkFq#GiWg4*me-i-S C@2wdC literal 0 HcmV?d00001 diff --git a/applications/PCB字符识别/gen_data/corpus/text.txt b/applications/PCB字符识别/gen_data/corpus/text.txt new file mode 100644 index 0000000000..8b8cb793ef --- /dev/null +++ b/applications/PCB字符识别/gen_data/corpus/text.txt @@ -0,0 +1,30 @@ +5ZQ +I4UL +PWL +SNOG +ZL02 +1C30 +O3H +YHRS +N03S +1U5Y +JTK +EN4F +YKJ +DWNH +R42W +X0V +4OF5 +08AM +Y93S +GWE2 +0KR +9U2A +DBQ +Y6J +ROZ +K06 +KIEY +NZQJ +UN1B +6X4 \ No newline at end of file diff --git a/applications/PCB字符识别/gen_data/det_background/1.png b/applications/PCB字符识别/gen_data/det_background/1.png new file mode 100644 index 0000000000000000000000000000000000000000..8a49eaa6862113044e05d17e32941a0a20911426 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^8-Q4fg9%8^2y$!$QW2gmjv*Cu-d=}dC;|Wg literal 0 HcmV?d00001 diff --git a/applications/PCB字符识别/gen_data/det_background/2.png b/applications/PCB字符识别/gen_data/det_background/2.png new file mode 100644 index 0000000000000000000000000000000000000000..c3fcc0c92826b97b5f6abd970f1a0580eede0f5d GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^-9RkC!2~2-J7>BAsSr;W$B>FSZ!bFXGAIZfFgURP zxigdhw+vC8oAYM6-uNkdpxL>U@2X|U^MJX;GGgEBG3zSK5X}Ud&*16m=d#Wzp$P!_ Caxi58 literal 0 HcmV?d00001 diff --git a/applications/PCB字符识别/gen_data/gen.py b/applications/PCB字符识别/gen_data/gen.py new file mode 100644 index 0000000000..4c768067f9 --- /dev/null +++ b/applications/PCB字符识别/gen_data/gen.py @@ -0,0 +1,261 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +""" +This code is refer from: +https://github.com/zcswdt/Color_OCR_image_generator +""" +import os +import random +from PIL import Image, ImageDraw, ImageFont +import json +import argparse + + +def get_char_lines(txt_root_path): + """ + desc:get corpus line + """ + txt_files = os.listdir(txt_root_path) + char_lines = [] + for txt in txt_files: + f = open(os.path.join(txt_root_path, txt), mode='r', encoding='utf-8') + lines = f.readlines() + f.close() + for line in lines: + char_lines.append(line.strip()) + return char_lines + + +def get_horizontal_text_picture(image_file, chars, fonts_list, cf): + """ + desc:gen horizontal text picture + """ + img = Image.open(image_file) + if img.mode != 'RGB': + img = img.convert('RGB') + img_w, img_h = img.size + + # random choice font + font_path = random.choice(fonts_list) + # random choice font size + font_size = random.randint(cf.font_min_size, cf.font_max_size) + font = ImageFont.truetype(font_path, font_size) + + ch_w = [] + ch_h = [] + for ch in chars: + wt, ht = font.getsize(ch) + ch_w.append(wt) + ch_h.append(ht) + f_w = sum(ch_w) + f_h = max(ch_h) + + # add space + char_space_width = max(ch_w) + f_w += (char_space_width * (len(chars) - 1)) + + x1 = random.randint(0, img_w - f_w) + y1 = random.randint(0, img_h - f_h) + x2 = x1 + f_w + y2 = y1 + f_h + + crop_y1 = y1 + crop_x1 = x1 + crop_y2 = y2 + crop_x2 = x2 + + best_color = (0, 0, 0) + draw = ImageDraw.Draw(img) + for i, ch in enumerate(chars): + draw.text((x1, y1), ch, best_color, font=font) + x1 += (ch_w[i] + char_space_width) + crop_img = img.crop((crop_x1, crop_y1, crop_x2, crop_y2)) + return crop_img, chars + + +def get_vertical_text_picture(image_file, chars, fonts_list, cf): + """ + desc:gen vertical text picture + """ + img = Image.open(image_file) + if img.mode != 'RGB': + img = img.convert('RGB') + img_w, img_h = img.size + # random choice font + font_path = random.choice(fonts_list) + # random choice font size + font_size = random.randint(cf.font_min_size, cf.font_max_size) + font = ImageFont.truetype(font_path, font_size) + + ch_w = [] + ch_h = [] + for ch in chars: + wt, ht = font.getsize(ch) + ch_w.append(wt) + ch_h.append(ht) + f_w = max(ch_w) + f_h = sum(ch_h) + + x1 = random.randint(0, img_w - f_w) + y1 = random.randint(0, img_h - f_h) + x2 = x1 + f_w + y2 = y1 + f_h + + crop_y1 = y1 + crop_x1 = x1 + crop_y2 = y2 + crop_x2 = x2 + + best_color = (0, 0, 0) + draw = ImageDraw.Draw(img) + i = 0 + for ch in chars: + draw.text((x1, y1), ch, best_color, font=font) + y1 = y1 + ch_h[i] + i = i + 1 + crop_img = img.crop((crop_x1, crop_y1, crop_x2, crop_y2)) + crop_img = crop_img.transpose(Image.ROTATE_90) + return crop_img, chars + + +def get_fonts(fonts_path): + """ + desc: get all fonts + """ + font_files = os.listdir(fonts_path) + fonts_list=[] + for font_file in font_files: + font_path=os.path.join(fonts_path, font_file) + fonts_list.append(font_path) + return fonts_list + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--num_img', type=int, default=30, help="Number of images to generate") + parser.add_argument('--font_min_size', type=int, default=11) + parser.add_argument('--font_max_size', type=int, default=12, + help="Help adjust the size of the generated text and the size of the picture") + parser.add_argument('--bg_path', type=str, default='./background', + help='The generated text pictures will be pasted onto the pictures of this folder') + parser.add_argument('--det_bg_path', type=str, default='./det_background', + help='The generated text pictures will use the pictures of this folder as the background') + parser.add_argument('--fonts_path', type=str, default='../../StyleText/fonts', + help='The font used to generate the picture') + parser.add_argument('--corpus_path', type=str, default='./corpus', + help='The corpus used to generate the text picture') + parser.add_argument('--output_dir', type=str, default='./output/', help='Images save dir') + + + cf = parser.parse_args() + # save path + if not os.path.exists(cf.output_dir): + os.mkdir(cf.output_dir) + + # get corpus + txt_root_path = cf.corpus_path + char_lines = get_char_lines(txt_root_path=txt_root_path) + + # get all fonts + fonts_path = cf.fonts_path + fonts_list = get_fonts(fonts_path) + + # rec bg + img_root_path = cf.bg_path + imnames=os.listdir(img_root_path) + + # det bg + det_bg_path = cf.det_bg_path + bg_pics = os.listdir(det_bg_path) + + # OCR det files + det_val_file = open(cf.output_dir + 'det_gt_val.txt', 'w', encoding='utf-8') + det_train_file = open(cf.output_dir + 'det_gt_train.txt', 'w', encoding='utf-8') + # det imgs + det_save_dir = 'imgs/' + if not os.path.exists(cf.output_dir + det_save_dir): + os.mkdir(cf.output_dir + det_save_dir) + det_val_save_dir = 'imgs_val/' + if not os.path.exists(cf.output_dir + det_val_save_dir): + os.mkdir(cf.output_dir + det_val_save_dir) + + # OCR rec files + rec_val_file = open(cf.output_dir + 'rec_gt_val.txt', 'w', encoding='utf-8') + rec_train_file = open(cf.output_dir + 'rec_gt_train.txt', 'w', encoding='utf-8') + # rec imgs + rec_save_dir = 'rec_imgs/' + if not os.path.exists(cf.output_dir + rec_save_dir): + os.mkdir(cf.output_dir + rec_save_dir) + rec_val_save_dir = 'rec_imgs_val/' + if not os.path.exists(cf.output_dir + rec_val_save_dir): + os.mkdir(cf.output_dir + rec_val_save_dir) + + + val_ratio = cf.num_img * 0.2 # val dataset ratio + + print('start generating...') + for i in range(0, cf.num_img): + imname = random.choice(imnames) + img_path = os.path.join(img_root_path, imname) + + rnd = random.random() + # gen horizontal text picture + if rnd < 0.5: + gen_img, chars = get_horizontal_text_picture(img_path, char_lines[i], fonts_list, cf) + ori_w, ori_h = gen_img.size + gen_img = gen_img.crop((0, 3, ori_w, ori_h)) + # gen vertical text picture + else: + gen_img, chars = get_vertical_text_picture(img_path, char_lines[i], fonts_list, cf) + ori_w, ori_h = gen_img.size + gen_img = gen_img.crop((3, 0, ori_w, ori_h)) + + ori_w, ori_h = gen_img.size + + # rec imgs + save_img_name = str(i).zfill(4) + '.jpg' + if i < val_ratio: + save_dir = os.path.join(rec_val_save_dir, save_img_name) + line = save_dir + '\t' + char_lines[i] + '\n' + rec_val_file.write(line) + else: + save_dir = os.path.join(rec_save_dir, save_img_name) + line = save_dir + '\t' + char_lines[i] + '\n' + rec_train_file.write(line) + gen_img.save(cf.output_dir + save_dir, quality = 95, subsampling=0) + + # det img + # random choice bg + bg_pic = random.sample(bg_pics, 1)[0] + det_img = Image.open(os.path.join(det_bg_path, bg_pic)) + # the PCB position is fixed, modify it according to your own scenario + if bg_pic == '1.png': + x1 = 38 + y1 = 3 + else: + x1 = 34 + y1 = 1 + + det_img.paste(gen_img, (x1, y1)) + # text pos + chars_pos = [[x1, y1], [x1 + ori_w, y1], [x1 + ori_w, y1 + ori_h], [x1, y1 + ori_h]] + label = [{"transcription":char_lines[i], "points":chars_pos}] + if i < val_ratio: + save_dir = os.path.join(det_val_save_dir, save_img_name) + det_val_file.write(save_dir + '\t' + json.dumps( + label, ensure_ascii=False) + '\n') + else: + save_dir = os.path.join(det_save_dir, save_img_name) + det_train_file.write(save_dir + '\t' + json.dumps( + label, ensure_ascii=False) + '\n') + det_img.save(cf.output_dir + save_dir, quality = 95, subsampling=0) From c71f53ad5f3cf4e0cb997a6ee715fd8cceaad89c Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Tue, 14 Jun 2022 10:57:40 +0800 Subject: [PATCH 089/129] rm infer fleet (#6577) --- ...leet_normal_infer_python_linux_gpu_cpu.txt | 28 ++++++------ .../docs/test_train_fleet_inference_python.md | 44 +------------------ 2 files changed, 15 insertions(+), 57 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 08e1fe9ba0..698f1e9849 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -25,29 +25,29 @@ eval:null null:null ## ===========================infer_params=========================== -Global.save_inference_dir:./output/ +Global.save_inference_dir:null Global.checkpoints: -norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o +norm_export:null quant_export: fpgm_export: distill_export:null export1:null export2:null -inference_dir:Student -infer_model:./inference/ch_PP-OCRv3_rec_infer +inference_dir:null +infer_model:null infer_export:null -infer_quant:False -inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1|6 ---use_tensorrt:False ---precision:fp32 +infer_quant: +inference: +--use_gpu: +--enable_mkldnn: +--cpu_threads: +--rec_batch_num: +--use_tensorrt: +--precision: --rec_model_dir: ---image_dir:./inference/rec_inference +--image_dir: null:null ---benchmark:True +--benchmark: null:null ===========================infer_benchmark_params========================== random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/docs/test_train_fleet_inference_python.md b/test_tipc/docs/test_train_fleet_inference_python.md index 4479a47da8..2da1170554 100644 --- a/test_tipc/docs/test_train_fleet_inference_python.md +++ b/test_tipc/docs/test_train_fleet_inference_python.md @@ -11,12 +11,6 @@ Linux GPU/CPU 多机多卡训练推理测试的主程序为`test_train_inference | PP-OCRv3 | ch_PP-OCRv3_rec | 分布式训练 | -- 推理相关: - -| 算法名称 | 模型名称 | device_CPU | device_GPU | batchsize | -| :----: | :----: | :----: | :----: | :----: | -| PP-OCRv3 | ch_PP-OCRv3_rec | 支持 | 支持 | 1 | - ## 2. 测试流程 @@ -62,46 +56,10 @@ bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec ```bash Run successfully with command - ch_PP-OCRv3_rec - python3.7 -m paddle.distributed.launch --ips=192.168.0.1,192.168.0.2 --gpus=0,1 tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o Global.use_gpu=True Global.save_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2 Global.epoch_num=3 Global.auto_cast=fp32 Train.loader.batch_size_per_card=16 ! - ...... - Run successfully with command - ch_PP-OCRv3_rec - python3.7 tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu=False --enable_mkldnn=False --cpu_threads=6 --rec_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2/Student --rec_batch_num=1 --image_dir=./inference/rec_inference --benchmark=True --precision=fp32 > ./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/python_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_1.log 2>&1 ! -``` - -在开启benchmark参数时,可以得到测试的详细数据,包含运行环境信息(系统版本、CUDA版本、CUDNN版本、驱动版本),Paddle版本信息,参数设置信息(运行设备、线程数、是否开启内存优化等),模型信息(模型名称、精度),数据信息(batchsize、是否为动态shape等),性能信息(CPU,GPU的占用、运行耗时、预处理耗时、推理耗时、后处理耗时),内容如下所示: - -``` -[2022/06/02 22:53:35] ppocr INFO: - -[2022/06/02 22:53:35] ppocr INFO: ---------------------- Env info ---------------------- -[2022/06/02 22:53:35] ppocr INFO: OS_version: Ubuntu 16.04 -[2022/06/02 22:53:35] ppocr INFO: CUDA_version: 10.1.243 -[2022/06/02 22:53:35] ppocr INFO: CUDNN_version: 7.6.5 -[2022/06/02 22:53:35] ppocr INFO: drivier_version: 460.32.03 -[2022/06/02 22:53:35] ppocr INFO: ---------------------- Paddle info ---------------------- -[2022/06/02 22:53:35] ppocr INFO: paddle_version: 2.3.0-rc0 -[2022/06/02 22:53:35] ppocr INFO: paddle_commit: 5d4980c052583fec022812d9c29460aff7cdc18b -[2022/06/02 22:53:35] ppocr INFO: log_api_version: 1.0 -[2022/06/02 22:53:35] ppocr INFO: ----------------------- Conf info ----------------------- -[2022/06/02 22:53:35] ppocr INFO: runtime_device: cpu -[2022/06/02 22:53:35] ppocr INFO: ir_optim: True -[2022/06/02 22:53:35] ppocr INFO: enable_memory_optim: True -[2022/06/02 22:53:35] ppocr INFO: enable_tensorrt: False -[2022/06/02 22:53:35] ppocr INFO: enable_mkldnn: False -[2022/06/02 22:53:35] ppocr INFO: cpu_math_library_num_threads: 6 -[2022/06/02 22:53:35] ppocr INFO: ----------------------- Model info ---------------------- -[2022/06/02 22:53:35] ppocr INFO: model_name: rec -[2022/06/02 22:53:35] ppocr INFO: precision: fp32 -[2022/06/02 22:53:35] ppocr INFO: ----------------------- Data info ----------------------- -[2022/06/02 22:53:35] ppocr INFO: batch_size: 1 -[2022/06/02 22:53:35] ppocr INFO: input_shape: dynamic -[2022/06/02 22:53:35] ppocr INFO: data_num: 6 -[2022/06/02 22:53:35] ppocr INFO: ----------------------- Perf info ----------------------- -[2022/06/02 22:53:35] ppocr INFO: cpu_rss(MB): 288.957, gpu_rss(MB): None, gpu_util: None% -[2022/06/02 22:53:35] ppocr INFO: total time spent(s): 0.4824 -[2022/06/02 22:53:35] ppocr INFO: preprocess_time(ms): 0.1136, inference_time(ms): 79.5877, postprocess_time(ms): 0.6945 ``` 该信息可以在运行log中查看,以上面的`ch_PP-OCRv3_rec`为例,log位置在`./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/results_python.log`。 如果运行失败,也会在终端中输出运行失败的日志信息以及对应的运行命令。可以基于该命令,分析运行失败的原因。 -**注意:** 由于分布式训练时,仅在`trainer_id=0`所在的节点中保存模型,因此其他的节点中在运行模型导出与推理时会报错,为正常现象。 +**注意:** 由于分布式训练时,仅在`trainer_id=0`所在的节点中保存模型,因此如果测试多机的推理过程,其他的节点中在运行模型导出与推理时会报错,为正常现象。 From 6437875ba37c978a6c3f0fe4dcdf448016743dc7 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Tue, 14 Jun 2022 12:49:48 +0800 Subject: [PATCH 090/129] Revert "rm infer fleet" (#6579) * Revert "rm infer fleet (#6577)" This reverts commit c71f53ad5f3cf4e0cb997a6ee715fd8cceaad89c. * Update train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt * Update test_train_fleet_inference_python.md * Update test_train_fleet_inference_python.md --- ...leet_normal_infer_python_linux_gpu_cpu.txt | 28 ++++++------ .../docs/test_train_fleet_inference_python.md | 44 ++++++++++++++++++- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 698f1e9849..7fcc8b4418 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -25,29 +25,29 @@ eval:null null:null ## ===========================infer_params=========================== -Global.save_inference_dir:null +Global.save_inference_dir:./output/ Global.checkpoints: -norm_export:null +norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o quant_export: fpgm_export: distill_export:null export1:null export2:null -inference_dir:null -infer_model:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_rec_infer infer_export:null -infer_quant: -inference: ---use_gpu: ---enable_mkldnn: ---cpu_threads: ---rec_batch_num: ---use_tensorrt: ---precision: +infer_quant:False +inference:tools/infer/predict_rec.py --rec_image_shape="3,48,320" +--use_gpu:False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 --rec_model_dir: ---image_dir: +--image_dir:./inference/rec_inference null:null ---benchmark: +--benchmark:True null:null ===========================infer_benchmark_params========================== random_infer_input:[{float32,[3,48,320]}] diff --git a/test_tipc/docs/test_train_fleet_inference_python.md b/test_tipc/docs/test_train_fleet_inference_python.md index 2da1170554..9fddb5d163 100644 --- a/test_tipc/docs/test_train_fleet_inference_python.md +++ b/test_tipc/docs/test_train_fleet_inference_python.md @@ -11,6 +11,12 @@ Linux GPU/CPU 多机多卡训练推理测试的主程序为`test_train_inference | PP-OCRv3 | ch_PP-OCRv3_rec | 分布式训练 | +- 推理相关: + +| 算法名称 | 模型名称 | device_CPU | device_GPU | batchsize | +| :----: | :----: | :----: | :----: | :----: | +| PP-OCRv3 | ch_PP-OCRv3_rec | 支持 | - | 1/6 | + ## 2. 测试流程 @@ -56,10 +62,46 @@ bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec ```bash Run successfully with command - ch_PP-OCRv3_rec - python3.7 -m paddle.distributed.launch --ips=192.168.0.1,192.168.0.2 --gpus=0,1 tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o Global.use_gpu=True Global.save_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2 Global.epoch_num=3 Global.auto_cast=fp32 Train.loader.batch_size_per_card=16 ! + ...... + Run successfully with command - ch_PP-OCRv3_rec - python3.7 tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu=False --enable_mkldnn=False --cpu_threads=6 --rec_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2/Student --rec_batch_num=1 --image_dir=./inference/rec_inference --benchmark=True --precision=fp32 > ./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/python_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_1.log 2>&1 ! +``` + +在开启benchmark参数时,可以得到测试的详细数据,包含运行环境信息(系统版本、CUDA版本、CUDNN版本、驱动版本),Paddle版本信息,参数设置信息(运行设备、线程数、是否开启内存优化等),模型信息(模型名称、精度),数据信息(batchsize、是否为动态shape等),性能信息(CPU,GPU的占用、运行耗时、预处理耗时、推理耗时、后处理耗时),内容如下所示: + +``` +[2022/06/02 22:53:35] ppocr INFO: + +[2022/06/02 22:53:35] ppocr INFO: ---------------------- Env info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: OS_version: Ubuntu 16.04 +[2022/06/02 22:53:35] ppocr INFO: CUDA_version: 10.1.243 +[2022/06/02 22:53:35] ppocr INFO: CUDNN_version: 7.6.5 +[2022/06/02 22:53:35] ppocr INFO: drivier_version: 460.32.03 +[2022/06/02 22:53:35] ppocr INFO: ---------------------- Paddle info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: paddle_version: 2.3.0-rc0 +[2022/06/02 22:53:35] ppocr INFO: paddle_commit: 5d4980c052583fec022812d9c29460aff7cdc18b +[2022/06/02 22:53:35] ppocr INFO: log_api_version: 1.0 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Conf info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: runtime_device: cpu +[2022/06/02 22:53:35] ppocr INFO: ir_optim: True +[2022/06/02 22:53:35] ppocr INFO: enable_memory_optim: True +[2022/06/02 22:53:35] ppocr INFO: enable_tensorrt: False +[2022/06/02 22:53:35] ppocr INFO: enable_mkldnn: False +[2022/06/02 22:53:35] ppocr INFO: cpu_math_library_num_threads: 6 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Model info ---------------------- +[2022/06/02 22:53:35] ppocr INFO: model_name: rec +[2022/06/02 22:53:35] ppocr INFO: precision: fp32 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Data info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: batch_size: 1 +[2022/06/02 22:53:35] ppocr INFO: input_shape: dynamic +[2022/06/02 22:53:35] ppocr INFO: data_num: 6 +[2022/06/02 22:53:35] ppocr INFO: ----------------------- Perf info ----------------------- +[2022/06/02 22:53:35] ppocr INFO: cpu_rss(MB): 288.957, gpu_rss(MB): None, gpu_util: None% +[2022/06/02 22:53:35] ppocr INFO: total time spent(s): 0.4824 +[2022/06/02 22:53:35] ppocr INFO: preprocess_time(ms): 0.1136, inference_time(ms): 79.5877, postprocess_time(ms): 0.6945 ``` 该信息可以在运行log中查看,以上面的`ch_PP-OCRv3_rec`为例,log位置在`./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/results_python.log`。 如果运行失败,也会在终端中输出运行失败的日志信息以及对应的运行命令。可以基于该命令,分析运行失败的原因。 -**注意:** 由于分布式训练时,仅在`trainer_id=0`所在的节点中保存模型,因此如果测试多机的推理过程,其他的节点中在运行模型导出与推理时会报错,为正常现象。 +**注意:** 由于分布式训练时,仅在`trainer_id=0`所在的节点中保存模型,因此其他的节点中在运行模型导出与推理时会报错,为正常现象。 From dee5305b7212744f62edddf86465b7f57f35878b Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 14 Jun 2022 08:33:43 +0000 Subject: [PATCH 091/129] add tabel tipc --- .../train_infer_python.txt | 4 +- .../configs/en_table_structure/table_mv3.yml | 117 ++++++++++++++++++ .../en_table_structure/train_infer_python.txt | 53 ++++++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ++++++++ ...rmal_normal_infer_python_linux_gpu_cpu.txt | 21 ++++ .../train_infer_python.txt | 53 ++++++++ ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ++++++++ test_tipc/prepare.sh | 29 ++++- 8 files changed, 376 insertions(+), 7 deletions(-) create mode 100755 test_tipc/configs/en_table_structure/table_mv3.yml create mode 100644 test_tipc/configs/en_table_structure/train_infer_python.txt create mode 100644 test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/en_table_structure_PACT/train_infer_python.txt create mode 100644 test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt index 11444a3ac1..de9e336332 100644 --- a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt @@ -4,7 +4,7 @@ python:python3.7 gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=5000 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 Global.pretrained_model:null @@ -45,7 +45,7 @@ inference:tools/infer/predict_det.py --use_tensorrt:False --precision:fp32 --det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ +--image_dir:./inference/ch_det_data_50/all-sum-510/00008790.jpg null:null --benchmark:True --det_algorithm:SAST diff --git a/test_tipc/configs/en_table_structure/table_mv3.yml b/test_tipc/configs/en_table_structure/table_mv3.yml new file mode 100755 index 0000000000..adf326bd02 --- /dev/null +++ b/test_tipc/configs/en_table_structure/table_mv3.yml @@ -0,0 +1,117 @@ +Global: + use_gpu: true + epoch_num: 10 + log_smooth_window: 20 + print_batch_step: 5 + save_model_dir: ./output/table_mv3/ + save_epoch_step: 3 + # evaluation is run every 400 iterations after the 0th iteration + eval_batch_step: [0, 400] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/table/table.jpg + # for data or label process + character_dict_path: ppocr/utils/dict/table_structure_dict.txt + character_type: en + max_text_length: 100 + max_elem_length: 800 + max_cell_num: 500 + infer_mode: False + process_total_num: 0 + process_cut_num: 0 + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.999 + clip_norm: 5.0 + lr: + learning_rate: 0.001 + regularizer: + name: 'L2' + factor: 0.00000 + +Architecture: + model_type: table + algorithm: TableAttn + Backbone: + name: MobileNetV3 + scale: 1.0 + model_name: large + Head: + name: TableAttentionHead + hidden_size: 256 + l2_decay: 0.00001 + loc_type: 2 + max_text_length: 100 + max_elem_length: 800 + max_cell_num: 500 + +Loss: + name: TableAttentionLoss + structure_weight: 100.0 + loc_weight: 10000.0 + +PostProcess: + name: TableLabelDecode + +Metric: + name: TableMetric + main_indicator: acc + +Train: + dataset: + name: PubTabDataSet + data_dir: ./train_data/pubtabnet/train + label_file_path: ./train_data/pubtabnet/train.jsonl + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ResizeTableImage: + max_len: 488 + - TableLabelEncode: + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - PaddingTableImage: + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'structure', 'bbox_list', 'sp_tokens', 'bbox_list_mask'] + loader: + shuffle: True + batch_size_per_card: 32 + drop_last: True + num_workers: 1 + +Eval: + dataset: + name: PubTabDataSet + data_dir: ./train_data/pubtabnet/test/ + label_file_path: ./train_data/pubtabnet/test.jsonl + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ResizeTableImage: + max_len: 488 + - TableLabelEncode: + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - PaddingTableImage: + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'structure', 'bbox_list', 'sp_tokens', 'bbox_list_mask'] + loader: + shuffle: False + drop_last: False + batch_size_per_card: 16 + num_workers: 1 diff --git a/test_tipc/configs/en_table_structure/train_infer_python.txt b/test_tipc/configs/en_table_structure/train_infer_python.txt new file mode 100644 index 0000000000..d9f3b30e16 --- /dev/null +++ b/test_tipc/configs/en_table_structure/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:False +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] diff --git a/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..31ac1ed53f --- /dev/null +++ b/test_tipc/configs/en_table_structure/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:False +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] diff --git a/test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..e8f7bbaa50 --- /dev/null +++ b/test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,21 @@ +===========================train_params=========================== +model_name:en_table_structure_KL +python:python3.7 +Global.pretrained_model: +Global.save_inference_dir:null +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer/ +infer_export:deploy/slim/quantization/quant_kl.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +infer_quant:True +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:int8 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +null:null diff --git a/test_tipc/configs/en_table_structure_PACT/train_infer_python.txt b/test_tipc/configs/en_table_structure_PACT/train_infer_python.txt new file mode 100644 index 0000000000..f62e8b68bc --- /dev/null +++ b/test_tipc/configs/en_table_structure_PACT/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:True +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] diff --git a/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..d7c847fcdc --- /dev/null +++ b/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure_PACT +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:amp +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:pact_train +norm_train:null +pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:null +quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:True +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 65ac2bbebb..8c9e12511d 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -55,6 +55,9 @@ if [ ${MODE} = "lite_train_lite_infer" ];then if [ ${model_name} == "en_table_structure" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_rec_infer.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_det_infer.tar && tar xf en_ppocr_mobile_v2.0_table_rec_infer.tar && cd ../ fi cd ./pretrain_models/ && tar xf det_mv3_db_v2.0_train.tar && cd ../ rm -rf ./train_data/icdar2015 @@ -147,9 +150,12 @@ elif [ ${MODE} = "whole_train_whole_infer" ];then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/total_text_lite.tar --no-check-certificate cd ./train_data && tar xf total_text.tar && ln -s total_text_lite total_text && cd ../ fi - if [ ${model_name} == "en_table_structure" ];then + if [[ ${model_name} =~ "en_table_structure" ]];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_rec_infer.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_det_infer.tar && tar xf en_ppocr_mobile_v2.0_table_rec_infer.tar && cd ../ fi elif [ ${MODE} = "lite_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams --no-check-certificate @@ -172,9 +178,12 @@ elif [ ${MODE} = "lite_train_whole_infer" ];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf ch_PP-OCRv3_det_distill_train.tar && cd ../ fi - if [ ${model_name} == "en_table_structure" ];then + if [[ ${model_name} =~ "en_table_structure" ]];then wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.1/table/en_ppocr_mobile_v2.0_table_structure_train.tar --no-check-certificate cd ./pretrain_models/ && tar xf en_ppocr_mobile_v2.0_table_structure_train.tar && cd ../ + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_rec_infer.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_det_infer.tar && tar xf en_ppocr_mobile_v2.0_table_rec_infer.tar && cd ../ fi elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar --no-check-certificate @@ -335,9 +344,11 @@ elif [ ${MODE} = "whole_infer" ];then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_east_v2.0_train.tar --no-check-certificate cd ./inference/ && tar xf det_r50_vd_east_v2.0_train.tar & cd ../ fi - if [ ${model_name} == "en_table_structure" ];then + if [[ ${model_name} =~ "en_table_structure" ]];then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_structure_infer.tar --no-check-certificate - cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_structure_infer.tar && cd ../ + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_rec_infer.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_structure_infer.tar && tar xf en_ppocr_mobile_v2.0_table_det_infer.tar && tar xf en_ppocr_mobile_v2.0_table_rec_infer.tar && cd ../ fi fi @@ -382,7 +393,15 @@ if [ ${MODE} = "klquant_whole_infer" ]; then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar --no-check-certificate cd ./train_data/ && tar xf ic15_data.tar && cd ../ cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf rec_inference.tar && cd ../ - fi + fi + if [ ${model_name} = "en_table_structure_KL" ];then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_structure_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_det_infer.tar --no-check-certificate + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/table/en_ppocr_mobile_v2.0_table_rec_infer.tar --no-check-certificate + wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dataset/pubtabnet.tar --no-check-certificate + cd ./inference/ && tar xf en_ppocr_mobile_v2.0_table_structure_infer.tar && tar xf en_ppocr_mobile_v2.0_table_det_infer.tar && tar xf en_ppocr_mobile_v2.0_table_rec_infer.tar && cd ../ + cd ./train_data/ && tar xf pubtabnet.tar && cd ../ + fi fi if [ ${MODE} = "cpp_infer" ];then From b215b786d4a545ee84ee477509469933f1b0dac1 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 15 Jun 2022 17:50:29 +0800 Subject: [PATCH 092/129] =?UTF-8?q?Update=20=E8=BD=BB=E9=87=8F=E7=BA=A7?= =?UTF-8?q?=E8=BD=A6=E7=89=8C=E8=AF=86=E5=88=AB.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/轻量级车牌识别.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 31b1b427db..7a3d7b238e 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -787,12 +787,12 @@ python tools/infer/predict_system.py \ - 端侧部署 -端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../dygraph/deploy/lite/readme_ch.md) +端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../deploy/lite/readme_ch.md) ### 4.5 实验总结 -我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于[PaddleOCR lite教程](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: +我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)进行了速度测试,指标对比如下: - 检测 From 08cdc9e2091354958868e3bb697a92bcee0a8ce9 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 15 Jun 2022 17:56:39 +0800 Subject: [PATCH 093/129] Update README.md --- ppstructure/table/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppstructure/table/README.md b/ppstructure/table/README.md index d21ef4aa38..b6804c6f09 100644 --- a/ppstructure/table/README.md +++ b/ppstructure/table/README.md @@ -18,7 +18,7 @@ The table recognition mainly contains three models The table recognition flow chart is as follows -![tableocr_pipeline](../../doc/table/tableocr_pipeline_en.jpg) +![tableocr_pipeline](../docs/table/tableocr_pipeline_en.jpg) 1. The coordinates of single-line text is detected by DB model, and then sends it to the recognition model to get the recognition result. 2. The table structure and cell coordinates is predicted by RARE model. From 10a3f2573d8e875c69683a71dc067d9060fb6875 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 15 Jun 2022 18:13:01 +0800 Subject: [PATCH 094/129] =?UTF-8?q?Update=20=E8=BD=BB=E9=87=8F=E7=BA=A7?= =?UTF-8?q?=E8=BD=A6=E7=89=8C=E8=AF=86=E5=88=AB.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/轻量级车牌识别.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 7a3d7b238e..7012c7f4bb 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -249,7 +249,7 @@ tar -xf ch_PP-OCRv3_det_distill_train.tar cd /home/aistudio/PaddleOCR ``` -预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student.yml](../configs/chepai/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: +预训练模型下载完成后,我们使用[ch_PP-OCRv3_det_student.yml](../configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml) 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下: 1. 模型存储和训练相关: 1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址 From 995a6d03e14c1cd9466533d1cec03578f84ccc7a Mon Sep 17 00:00:00 2001 From: tink2123 Date: Thu, 16 Jun 2022 11:07:06 +0800 Subject: [PATCH 095/129] add digital doc --- applications/corpus/digital.txt | 43 +++ applications/fonts/DS-DIGI.TTF | Bin 0 -> 24448 bytes applications/fonts/DS-DIGIB.TTF | Bin 0 -> 24896 bytes applications/光功率计数码管字符识别.md | 454 +++++++++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 applications/corpus/digital.txt create mode 100644 applications/fonts/DS-DIGI.TTF create mode 100644 applications/fonts/DS-DIGIB.TTF create mode 100644 applications/光功率计数码管字符识别.md diff --git a/applications/corpus/digital.txt b/applications/corpus/digital.txt new file mode 100644 index 0000000000..26b06e784e --- /dev/null +++ b/applications/corpus/digital.txt @@ -0,0 +1,43 @@ +46.39 +40.08 +89.52 +-71.93 +23.19 +-81.02 +-34.09 +05.87 +-67.80 +-51.56 +-34.58 +37.91 +56.98 +29.01 +-90.13 +35.55 +66.07 +-90.35 +-50.93 +42.42 +21.40 +-30.99 +-71.78 +25.60 +-48.69 +-72.28 +-17.55 +-99.93 +-47.35 +-64.89 +-31.28 +-90.01 +05.17 +30.91 +30.56 +-06.90 +79.05 +67.74 +-32.31 +94.22 +28.75 +51.03 +-58.96 diff --git a/applications/fonts/DS-DIGI.TTF b/applications/fonts/DS-DIGI.TTF new file mode 100644 index 0000000000000000000000000000000000000000..09258773c7219ad9e60b92b918e3c50b58f43c9e GIT binary patch literal 24448 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 + +目前光功率计缺少将数据直接输出的功能,需要人工读数。这一项工作单调重复,如果可以使用机器替代人工,将节约大量成本。针对上述问题,希望通过摄像头拍照->智能读数的方式高效地完成此任务。 + +为实现智能读数,通常会采取文本检测+文本识别的方案: + +第一步,使用文本检测模型定位出光功率计中的数字部分; + +第二步,使用文本识别模型获得准确的数字和单位信息。 + +本项目主要介绍如何完成第二步文本识别部分。 + +## 2. PaddleOCR 快速使用 + +PaddleOCR 旨在打造一套丰富、领先、且实用的OCR工具库,助力开发者训练出更好的模型,并应用落地。 + +![](https://github.com/PaddlePaddle/PaddleOCR/raw/release/2.5/doc/imgs_results/ch_ppocr_mobile_v2.0/test_add_91.jpg) + + +官方提供了适用于通用场景的高精轻量模型,首先使用官方提供的 PP-OCRv3 模型预测图片,验证下当前模型在光功率计场景上的效果。 + +- 准备环境 + +``` +python3 -m pip install -U pip +python3 -m pip install paddleocr +``` + + +- 测试效果 + +测试图: + +![](https://ai-studio-static-online.cdn.bcebos.com/8dca91f016884e16ad9216d416da72ea08190f97d87b4be883f15079b7ebab9a) + + +``` +paddleocr --lang=ch --det=Fase --image_dir=data +``` + +得到如下测试结果: + +``` +('.7000', 0.6885431408882141) +``` + +发现数字识别较准,然而对负号和小数点识别不准确。 由于PP-OCRv3的训练数据大多为通用场景数据,在特定的场景上效果可能不够好。因此需要基于场景数据进行微调。 + +下面就主要介绍如何在光功率计(数码管)场景上微调训练。 + + +## 3. 开始训练 + +### 3.1 数据准备 + +特定的工业场景往往很难获取开源的真实数据集,光功率计也是如此。在实际工业场景中,可以通过摄像头采集的方法收集大量真实数据,本例中重点介绍数据合成方法和真实数据挖掘方法,如何利用有限的数据优化模型精度。 + +数据集分为两个部分:合成数据,真实数据, 其中合成数据由 text_renderer 工具批量生成得到, 真实数据通过爬虫等方式在百度图片中搜索并使用 PPOCRLabel 标注得到。 + + +- 合成数据 + +本例中数据合成工具使用的是 [text_renderer](https://github.com/Sanster/text_renderer), 该工具可以合成用于文本识别训练的文本行数据: + +![](https://github.com/oh-my-ocr/text_renderer/raw/master/example_data/effect_layout_image/char_spacing_compact.jpg) + +![](https://github.com/oh-my-ocr/text_renderer/raw/master/example_data/effect_layout_image/color_image.jpg) + + +``` +export https_proxy=http://172.19.57.45:3128 +git clone https://github.com/oh-my-ocr/text_renderer +``` + +``` +import os +python3 setup.py develop +python3 -m pip install -r docker/requirements.txt +python3 main.py \ + --config example_data/example.py \ + --dataset img \ + --num_processes 2 \ + --log_period 10 +``` + +给定字体和语料,就可以合成较为丰富样式的文本行数据。 光功率计识别场景,目标是正确识别数码管文本,因此需要收集部分数码管字体,训练语料,用于合成文本识别数据。 + +将收集好的语料存放在 example_data 路径下: + +``` +ln -s ./fonts/DS* text_renderer/example_data/font/ +ln -s ./corpus/digital.txt text_renderer/example_data/text/ +``` + +修改 text_renderer/example_data/font_list/font_list.txt ,选择需要的字体开始合成: + +``` +python3 main.py \ + --config example_data/digital_example.py \ + --dataset img \ + --num_processes 2 \ + --log_period 10 +``` + +合成图片会被存在目录 text_renderer/example_data/digital/chn_data 下 + +查看合成的数据样例: + +![](https://ai-studio-static-online.cdn.bcebos.com/7d5774a273f84efba5b9ce7fd3f86e9ef24b6473e046444db69fa3ca20ac0986) + + +- 真实数据挖掘 + +模型训练需要使用真实数据作为评价指标,否则很容易过拟合到简单的合成数据中。没有开源数据的情况下,可以利用部分无标注数据+标注工具获得真实数据。 + + +1. 数据搜集 + +使用[爬虫工具](https://github.com/Joeclinton1/google-images-download.git)获得无标注数据 + +2. [PPOCRLabel](https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.5/PPOCRLabel) 完成半自动标注 + +PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置PP-OCR模型对数据自动标注和重新识别。使用Python3和PyQT5编写,支持矩形框标注、表格标注、不规则文本标注、关键信息标注模式,导出格式可直接用于PaddleOCR检测和识别模型的训练。 + +![](https://github.com/PaddlePaddle/PaddleOCR/raw/release/2.5/PPOCRLabel/data/gif/steps_en.gif) + + +收集完数据后就可以进行分配了,验证集中一般都是真实数据,训练集中包含合成数据+真实数据。本例中标注了155张图片,其中训练集和验证集的数目为100和55。 + + +最终 `data` 文件夹应包含以下几部分: + +``` +|-data + |- synth_train.txt + |- real_train.txt + |- real_eval.txt + |- synthetic_data + |- word_001.png + |- word_002.jpg + |- word_003.jpg + | ... + |- real_data + |- word_001.png + |- word_002.jpg + |- word_003.jpg + | ... + ... +``` + +### 3.2 模型选择 + +本案例提供了2种文本识别模型:PP-OCRv3 识别模型 和 SVTR_Tiny: + +[PP-OCRv3 识别模型](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/PP-OCRv3_introduction.md):PP-OCRv3的识别模块是基于文本识别算法SVTR优化。SVTR不再采用RNN结构,通过引入Transformers结构更加有效地挖掘文本行图像的上下文信息,从而提升文本识别能力。并进行了一系列结构改进加速模型预测。 + +[SVTR_Tiny](https://arxiv.org/abs/2205.00159):SVTR提出了一种用于场景文本识别的单视觉模型,该模型在patch-wise image tokenization框架内,完全摒弃了序列建模,在精度具有竞争力的前提下,模型参数量更少,速度更快。 + +以上两个策略在自建中文数据集上的精度和速度对比如下: + +| ID | 策略 | 模型大小 | 精度 | 预测耗时(CPU + MKLDNN)| +|-----|-----|--------|----| --- | +| 01 | PP-OCRv2 | 8M | 74.8% | 8.54ms | +| 02 | SVTR_Tiny | 21M | 80.1% | 97ms | +| 03 | SVTR_LCNet(h32) | 12M | 71.9% | 6.6ms | +| 04 | SVTR_LCNet(h48) | 12M | 73.98% | 7.6ms | +| 05 | + GTC | 12M | 75.8% | 7.6ms | +| 06 | + TextConAug | 12M | 76.3% | 7.6ms | +| 07 | + TextRotNet | 12M | 76.9% | 7.6ms | +| 08 | + UDML | 12M | 78.4% | 7.6ms | +| 09 | + UIM | 12M | 79.4% | 7.6ms | + + +### 3.3 开始训练 + +首先下载 PaddleOCR 代码库 + +``` +git clone -b release/2.5 https://github.com/PaddlePaddle/PaddleOCR.git +``` + +PaddleOCR提供了训练脚本、评估脚本和预测脚本,本节将以 PP-OCRv3 中文识别模型为例: + +**Step1:下载预训练模型** + +首先下载 pretrain model,您可以下载训练好的模型在自定义数据上进行finetune + +``` +cd PaddleOCR/ +# 下载PP-OCRv3 中文预训练模型 +wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar +# 解压模型参数 +cd pretrain_models +tar -xf ch_PP-OCRv3_rec_train.tar && rm -rf ch_PP-OCRv3_rec_train.tar +``` + +**Step2:自定义字典文件** + +接下来需要提供一个字典({word_dict_name}.txt),使模型在训练时,可以将所有出现的字符映射为字典的索引。 + +因此字典需要包含所有希望被正确识别的字符,{word_dict_name}.txt需要写成如下格式,并以 `utf-8` 编码格式保存: + +``` +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +- +. +``` + +word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,“3.14” 将被映射成 [3, 11, 1, 4] + +* 内置字典 + +PaddleOCR内置了一部分字典,可以按需使用。 + +`ppocr/utils/ppocr_keys_v1.txt` 是一个包含6623个字符的中文字典 + +`ppocr/utils/ic15_dict.txt` 是一个包含36个字符的英文字典 + +* 自定义字典 + +内置字典面向通用场景,具体的工业场景中,可能需要识别特殊字符,或者只需识别某几个字符,此时自定义字典会更提升模型精度。例如在光功率计场景中,需要识别数字和单位。 + +遍历真实数据标签中的字符,制作字典`digital_dict.txt`如下所示: + +``` +- +. +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +B +E +F +H +L +N +T +W +d +k +m +n +o +z +``` + + + + +**Step3:修改配置文件** + +为了更好的使用预训练模型,训练推荐使用[ch_PP-OCRv3_rec_distillation.yml](../../configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml)配置文件,并参考下列说明修改配置文件: + +以 `ch_PP-OCRv3_rec_distillation.yml` 为例: +``` +Global: + ... + # 添加自定义字典,如修改字典请将路径指向新字典 + character_dict_path: ppocr/utils/dict/digital_dict.txt + ... + # 识别空格 + use_space_char: True + + +Optimizer: + ... + # 添加学习率衰减策略 + lr: + name: Cosine + learning_rate: 0.001 + ... + +... + +Train: + dataset: + # 数据集格式,支持LMDBDataSet以及SimpleDataSet + name: SimpleDataSet + # 数据集路径 + data_dir: ./data/ + # 训练集标签文件 + label_file_list: + - ./train_data/digital_img/digital_train.txt #11w + - ./train_data/digital_img/real_train.txt #100 + - ./train_data/digital_img/dbm_img/dbm.txt #3w + ratio_list: + - 0.3 + - 1.0 + - 1.0 + transforms: + ... + - RecResizeImg: + # 修改 image_shape 以适应长文本 + image_shape: [3, 48, 320] + ... + loader: + ... + # 单卡训练的batch_size + batch_size_per_card: 256 + ... + +Eval: + dataset: + # 数据集格式,支持LMDBDataSet以及SimpleDataSet + name: SimpleDataSet + # 数据集路径 + data_dir: ./data + # 验证集标签文件 + label_file_list: + - ./train_data/digital_img/real_val.txt + transforms: + ... + - RecResizeImg: + # 修改 image_shape 以适应长文本 + image_shape: [3, 48, 320] + ... + loader: + # 单卡验证的batch_size + batch_size_per_card: 256 + ... +``` +**注意,训练/预测/评估时的配置文件请务必与训练一致。** + +**Step4:启动训练** + +*如果您安装的是cpu版本,请将配置文件中的 `use_gpu` 字段修改为false* + +``` +# GPU训练 支持单卡,多卡训练 +# 训练数码管数据 训练日志会自动保存为 "{save_model_dir}" 下的train.log + +#单卡训练(训练周期长,不建议) +python3 tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.pretrained_model=./pretrain_models/ch_PP-OCRv3_rec_train/best_accuracy + +#多卡训练,通过--gpus参数指定卡号 +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.pretrained_model=./pretrain_models/en_PP-OCRv3_rec_train/best_accuracy +``` + + +PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml` 中修改 `eval_batch_step` 设置评估频率,默认每500个iter评估一次。评估过程中默认将最佳acc模型,保存为 `output/ch_PP-OCRv3_rec_distill/best_accuracy` 。 + +如果验证集很大,测试将会比较耗时,建议减少评估次数,或训练完再进行评估。 + +### SVTR_Tiny 训练 + +SVTR_Tiny 训练步骤与上面一致,SVTR支持的配置和模型训练权重可以参考[算法介绍文档](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/algorithm_rec_svtr.md) + +**Step1:下载预训练模型** + +``` +# 下载 SVTR_Tiny 中文识别预训练模型和配置文件 +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/rec_svtr_tiny_none_ctc_ch_train.tar +# 解压模型参数 +tar -xf rec_svtr_tiny_none_ctc_ch_train.tar && rm -rf rec_svtr_tiny_none_ctc_ch_train.tar +``` +**Step2:自定义字典文件** + +字典依然使用自定义的 digital_dict.txt + +**Step3:修改配置文件** + +配置文件中对应修改字典路径和数据路径 + +**Step4:启动训练** + +``` +## 单卡训练 +python tools/train.py -c rec_svtr_tiny_none_ctc_ch_train/rec_svtr_tiny_6local_6global_stn_ch.yml \ + -o Global.pretrained_model=./rec_svtr_tiny_none_ctc_ch_train/best_accuracy +``` + +### 3.4 验证效果 + +**本例中的评估集和模型路径,可通过填写[问卷](todo:add link)获得** + +* 指标评估 + +训练中模型参数默认保存在`Global.save_model_dir`目录下。在评估指标时,需要设置`Global.checkpoints`指向保存的参数文件。评估数据集可以通过 `configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml` 修改Eval中的 `label_file_path` 设置。 + +``` +# GPU 评估, Global.checkpoints 为待测权重 +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.checkpoints={path/to/weights}/best_accuracy +``` + +* 测试识别效果 + +使用 PaddleOCR 训练好的模型,可以通过以下脚本进行快速预测。 + +默认预测图片存储在 `infer_img` 里,通过 `-o Global.checkpoints` 加载训练好的参数文件: + +根据配置文件中设置的 `save_model_dir` 和 `save_epoch_step` 字段,会有以下几种参数被保存下来: + +``` +output/rec/ +├── best_accuracy.pdopt +├── best_accuracy.pdparams +├── best_accuracy.states +├── config.yml +├── iter_epoch_3.pdopt +├── iter_epoch_3.pdparams +├── iter_epoch_3.states +├── latest.pdopt +├── latest.pdparams +├── latest.states +└── train.log +``` + +其中 best_accuracy.* 是评估集上的最优模型;iter_epoch_x.* 是以 `save_epoch_step` 为间隔保存下来的模型;latest.* 是最后一个epoch的模型。 + +``` +# 预测英文结果 +python3 tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml -o Global.pretrained_model={path/to/weights}/best_accuracy Global.infer_img=test_digital.png +``` + +预测图片: + +![](https://ai-studio-static-online.cdn.bcebos.com/8dca91f016884e16ad9216d416da72ea08190f97d87b4be883f15079b7ebab9a) + + +得到输入图像的预测结果: + +``` +infer_img: test_digital.png + result: ('-70.00', 0.9998967) +``` From ee22ebb49ff73934cef94ac9fda6ba6b3ef3ca4b Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 16 Jun 2022 12:10:12 +0000 Subject: [PATCH 096/129] add fleet tipc --- ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ 7 files changed, 371 insertions(+) create mode 100644 test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt create mode 100644 test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..5fb87fae18 --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PP-OCRv2_det +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml -o +quant_export:null +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv2_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..4af814036a --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PP-OCRv2_rec +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv2_rec_infer +infer_export:null +infer_quant:False +inference:tools/infer/predict_rec.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,32,320]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..8275254f3f --- /dev/null +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_PP-OCRv3_det +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o +quant_export:null +fpgm_export: +distill_export:null +export1:null +export2:null +inference_dir:Student +infer_model:./inference/ch_PP-OCRv3_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..b76048813e --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_ppocr_mobile_v2.0_det +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=100|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +inference_dir:null +train_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy +infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +null:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..3a7c487173 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_ppocr_mobile_v2.0_rec +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c configs/rec/rec_icdar15_train.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c configs/rec/rec_icdar15_train.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c configs/rec/rec_icdar15_train.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/ch_ppocr_mobile_v2.0_rec_train/best_accuracy +infer_export:tools/export_model.py -c configs/rec/rec_icdar15_train.yml -o +infer_quant:False +inference:tools/infer/predict_rec.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,32,100]}] diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..77b69f6c3a --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_ppocr_server_v2.0_det +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_lite_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_ppocr_server_v2.0_det/det_r50_vd_db.yml -o +quant_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c test_tipc/configs/ch_ppocr_server_v2.0_det/det_r50_vd_db.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_det/det_r50_vd_db.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/ch_ppocr_server_v2.0_det_train/best_accuracy +infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml -o +infer_quant:False +inference:tools/infer/predict_det.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] \ No newline at end of file diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..d486d37668 --- /dev/null +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:ch_ppocr_server_v2.0_rec +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=5|whole_train_whole_infer=100 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec/rec_icdar15_train.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec/rec_icdar15_train.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec/rec_icdar15_train.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/ch_ppocr_server_v2.0_rec_train/best_accuracy +infer_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec/rec_icdar15_train.yml -o +infer_quant:False +inference:tools/infer/predict_rec.py +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,32,100]}] From 5d8c9f47cd2e4a14aa367e4725e986489fa26da2 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Fri, 17 Jun 2022 15:47:49 +0800 Subject: [PATCH 097/129] Update ppocr_introduction_en.md --- doc/doc_en/ppocr_introduction_en.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/doc_en/ppocr_introduction_en.md b/doc/doc_en/ppocr_introduction_en.md index b13d7f9bf1..d28ccb3529 100644 --- a/doc/doc_en/ppocr_introduction_en.md +++ b/doc/doc_en/ppocr_introduction_en.md @@ -29,10 +29,10 @@ PP-OCR pipeline is as follows: PP-OCR system is in continuous optimization. At present, PP-OCR and PP-OCRv2 have been released: -PP-OCR adopts 19 effective strategies from 8 aspects including backbone network selection and adjustment, prediction head design, data augmentation, learning rate transformation strategy, regularization parameter selection, pre-training model use, and automatic model tailoring and quantization to optimize and slim down the models of each module (as shown in the green box above). The final results are an ultra-lightweight Chinese and English OCR model with an overall size of 3.5M and a 2.8M English digital OCR model. For more details, please refer to the PP-OCR technical article (https://arxiv.org/abs/2009.09941). +PP-OCR adopts 19 effective strategies from 8 aspects including backbone network selection and adjustment, prediction head design, data augmentation, learning rate transformation strategy, regularization parameter selection, pre-training model use, and automatic model tailoring and quantization to optimize and slim down the models of each module (as shown in the green box above). The final results are an ultra-lightweight Chinese and English OCR model with an overall size of 3.5M and a 2.8M English digital OCR model. For more details, please refer to [PP-OCR technical report](https://arxiv.org/abs/2009.09941). #### PP-OCRv2 -On the basis of PP-OCR, PP-OCRv2 is further optimized in five aspects. The detection model adopts CML(Collaborative Mutual Learning) knowledge distillation strategy and CopyPaste data expansion strategy. The recognition model adopts LCNet lightweight backbone network, U-DML knowledge distillation strategy and enhanced CTC loss function improvement (as shown in the red box above), which further improves the inference speed and prediction effect. For more details, please refer to the technical report of PP-OCRv2 (https://arxiv.org/abs/2109.03144). +On the basis of PP-OCR, PP-OCRv2 is further optimized in five aspects. The detection model adopts CML(Collaborative Mutual Learning) knowledge distillation strategy and CopyPaste data expansion strategy. The recognition model adopts LCNet lightweight backbone network, U-DML knowledge distillation strategy and enhanced CTC loss function improvement (as shown in the red box above), which further improves the inference speed and prediction effect. For more details, please refer to [PP-OCRv2 technical report](https://arxiv.org/abs/2109.03144). #### PP-OCRv3 @@ -46,7 +46,7 @@ PP-OCRv3 pipeline is as follows:
-For more details, please refer to [PP-OCRv3 technical report](./PP-OCRv3_introduction_en.md). +For more details, please refer to [PP-OCRv3 technical report](https://arxiv.org/abs/2206.03001v2). ## 2. Features From 94d5d00a53da017a933b9d58e1ceccc00881df06 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Fri, 17 Jun 2022 15:51:57 +0800 Subject: [PATCH 098/129] Update ppocr_introduction.md --- doc/doc_ch/ppocr_introduction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/doc_ch/ppocr_introduction.md b/doc/doc_ch/ppocr_introduction.md index 59de124e2a..bd62087c8b 100644 --- a/doc/doc_ch/ppocr_introduction.md +++ b/doc/doc_ch/ppocr_introduction.md @@ -30,11 +30,11 @@ PP-OCR系统pipeline如下: PP-OCR系统在持续迭代优化,目前已发布PP-OCR和PP-OCRv2两个版本: -PP-OCR从骨干网络选择和调整、预测头部的设计、数据增强、学习率变换策略、正则化参数选择、预训练模型使用以及模型自动裁剪量化8个方面,采用19个有效策略,对各个模块的模型进行效果调优和瘦身(如绿框所示),最终得到整体大小为3.5M的超轻量中英文OCR和2.8M的英文数字OCR。更多细节请参考PP-OCR技术方案 https://arxiv.org/abs/2009.09941 +PP-OCR从骨干网络选择和调整、预测头部的设计、数据增强、学习率变换策略、正则化参数选择、预训练模型使用以及模型自动裁剪量化8个方面,采用19个有效策略,对各个模块的模型进行效果调优和瘦身(如绿框所示),最终得到整体大小为3.5M的超轻量中英文OCR和2.8M的英文数字OCR。更多细节请参考[PP-OCR技术报告](https://arxiv.org/abs/2009.09941)。 #### PP-OCRv2 -PP-OCRv2在PP-OCR的基础上,进一步在5个方面重点优化,检测模型采用CML协同互学习知识蒸馏策略和CopyPaste数据增广策略;识别模型采用LCNet轻量级骨干网络、UDML 改进知识蒸馏策略和[Enhanced CTC loss](./enhanced_ctc_loss.md)损失函数改进(如上图红框所示),进一步在推理速度和预测效果上取得明显提升。更多细节请参考PP-OCRv2[技术报告](https://arxiv.org/abs/2109.03144)。 +PP-OCRv2在PP-OCR的基础上,进一步在5个方面重点优化,检测模型采用CML协同互学习知识蒸馏策略和CopyPaste数据增广策略;识别模型采用LCNet轻量级骨干网络、UDML 改进知识蒸馏策略和[Enhanced CTC loss](./enhanced_ctc_loss.md)损失函数改进(如上图红框所示),进一步在推理速度和预测效果上取得明显提升。更多细节请参考[PP-OCRv2技术报告](https://arxiv.org/abs/2109.03144)。 #### PP-OCRv3 @@ -48,7 +48,7 @@ PP-OCRv3系统pipeline如下:
-更多细节请参考PP-OCRv3[技术报告](./PP-OCRv3_introduction.md)。 +更多细节请参考[PP-OCRv3技术报告](https://arxiv.org/abs/2206.03001v2) 👉[中文简洁版](./PP-OCRv3_introduction.md) From b473e92d092e9ae1bb362bc3191fdc512cb71c0c Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Fri, 17 Jun 2022 09:12:46 +0000 Subject: [PATCH 099/129] add tvm --- deploy/tvm/.gitignore | 5 + deploy/tvm/Makefile | 129 +++++++++++ deploy/tvm/README.md | 100 +++++++++ deploy/tvm/arm-none-eabi-gcc.cmake | 79 +++++++ deploy/tvm/convert_image.py | 102 +++++++++ deploy/tvm/corstone300.ld | 295 ++++++++++++++++++++++++++ deploy/tvm/imgs_words_en/word_10.png | Bin 0 -> 5738 bytes deploy/tvm/imgs_words_en/word_116.png | Bin 0 -> 74135 bytes deploy/tvm/include/crt_config.h | 26 +++ deploy/tvm/include/tvm_runtime.h | 55 +++++ deploy/tvm/requirements.txt | 3 + deploy/tvm/run_demo.sh | 152 +++++++++++++ deploy/tvm/src/demo_bare_metal.c | 78 +++++++ 13 files changed, 1024 insertions(+) create mode 100644 deploy/tvm/.gitignore create mode 100644 deploy/tvm/Makefile create mode 100644 deploy/tvm/README.md create mode 100644 deploy/tvm/arm-none-eabi-gcc.cmake create mode 100755 deploy/tvm/convert_image.py create mode 100644 deploy/tvm/corstone300.ld create mode 100644 deploy/tvm/imgs_words_en/word_10.png create mode 100644 deploy/tvm/imgs_words_en/word_116.png create mode 100644 deploy/tvm/include/crt_config.h create mode 100644 deploy/tvm/include/tvm_runtime.h create mode 100644 deploy/tvm/requirements.txt create mode 100755 deploy/tvm/run_demo.sh create mode 100644 deploy/tvm/src/demo_bare_metal.c diff --git a/deploy/tvm/.gitignore b/deploy/tvm/.gitignore new file mode 100644 index 0000000000..faeba235a6 --- /dev/null +++ b/deploy/tvm/.gitignore @@ -0,0 +1,5 @@ +include/inputs.h +include/outputs.h + +__pycache__/ +build/ \ No newline at end of file diff --git a/deploy/tvm/Makefile b/deploy/tvm/Makefile new file mode 100644 index 0000000000..cf7d375b7e --- /dev/null +++ b/deploy/tvm/Makefile @@ -0,0 +1,129 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# Makefile to build demo + +# Setup build environment +BUILD_DIR := build + +ARM_CPU = ARMCM55 +ETHOSU_PATH = /opt/arm/ethosu +CMSIS_PATH ?= ${ETHOSU_PATH}/cmsis +ETHOSU_PLATFORM_PATH ?= ${ETHOSU_PATH}/core_platform +STANDALONE_CRT_PATH := $(abspath $(BUILD_DIR))/runtime +CORSTONE_300_PATH = ${ETHOSU_PLATFORM_PATH}/targets/corstone-300 +PKG_COMPILE_OPTS = -g -Wall -O2 -Wno-incompatible-pointer-types -Wno-format -mcpu=cortex-m55 -mthumb -mfloat-abi=hard -std=gnu99 +CMAKE ?= cmake +CC = arm-none-eabi-gcc +AR = arm-none-eabi-ar +RANLIB = arm-none-eabi-ranlib +PKG_CFLAGS = ${PKG_COMPILE_OPTS} \ + -I${STANDALONE_CRT_PATH}/include \ + -I${STANDALONE_CRT_PATH}/src/runtime/crt/include \ + -I${PWD}/include \ + -I${CORSTONE_300_PATH} \ + -I${CMSIS_PATH}/Device/ARM/${ARM_CPU}/Include/ \ + -I${CMSIS_PATH}/CMSIS/Core/Include \ + -I${CMSIS_PATH}/CMSIS/NN/Include \ + -I${CMSIS_PATH}/CMSIS/DSP/Include \ + -I$(abspath $(BUILD_DIR))/codegen/host/include +CMSIS_NN_CMAKE_FLAGS = -DCMAKE_TOOLCHAIN_FILE=$(abspath $(BUILD_DIR))/../arm-none-eabi-gcc.cmake \ + -DTARGET_CPU=cortex-m55 \ + -DBUILD_CMSIS_NN_FUNCTIONS=YES +PKG_LDFLAGS = -lm -specs=nosys.specs -static -T corstone300.ld + +$(ifeq VERBOSE,1) +QUIET ?= +$(else) +QUIET ?= @ +$(endif) + +DEMO_MAIN = src/demo_bare_metal.c +CODEGEN_SRCS = $(wildcard $(abspath $(BUILD_DIR))/codegen/host/src/*.c) +CODEGEN_OBJS = $(subst .c,.o,$(CODEGEN_SRCS)) +CMSIS_STARTUP_SRCS = $(wildcard ${CMSIS_PATH}/Device/ARM/${ARM_CPU}/Source/*.c) +UART_SRCS = $(wildcard ${CORSTONE_300_PATH}/*.c) + +demo: $(BUILD_DIR)/demo + +$(BUILD_DIR)/stack_allocator.o: $(STANDALONE_CRT_PATH)/src/runtime/crt/memory/stack_allocator.c + $(QUIET)mkdir -p $(@D) + $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^ + +$(BUILD_DIR)/crt_backend_api.o: $(STANDALONE_CRT_PATH)/src/runtime/crt/common/crt_backend_api.c + $(QUIET)mkdir -p $(@D) + $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^ + +# Build generated code +$(BUILD_DIR)/libcodegen.a: $(CODEGEN_SRCS) + $(QUIET)cd $(abspath $(BUILD_DIR)/codegen/host/src) && $(CC) -c $(PKG_CFLAGS) $(CODEGEN_SRCS) + $(QUIET)$(AR) -cr $(abspath $(BUILD_DIR)/libcodegen.a) $(CODEGEN_OBJS) + $(QUIET)$(RANLIB) $(abspath $(BUILD_DIR)/libcodegen.a) + +# Build CMSIS startup code +${BUILD_DIR}/libcmsis_startup.a: $(CMSIS_STARTUP_SRCS) + $(QUIET)mkdir -p $(abspath $(BUILD_DIR)/libcmsis_startup) + $(QUIET)cd $(abspath $(BUILD_DIR)/libcmsis_startup) && $(CC) -c $(PKG_CFLAGS) -D${ARM_CPU} $^ + $(QUIET)$(AR) -cr $(abspath $(BUILD_DIR)/libcmsis_startup.a) $(abspath $(BUILD_DIR))/libcmsis_startup/*.o + $(QUIET)$(RANLIB) $(abspath $(BUILD_DIR)/libcmsis_startup.a) + +CMSIS_SHA_FILE=${CMSIS_PATH}/977abe9849781a2e788b02282986480ff4e25ea6.sha +ifneq ("$(wildcard $(CMSIS_SHA_FILE))","") +${BUILD_DIR}/cmsis_nn/Source/libcmsis-nn.a: + $(QUIET)mkdir -p $(@D) + $(QUIET)cd $(CMSIS_PATH)/CMSIS/NN && $(CMAKE) -B $(abspath $(BUILD_DIR)/cmsis_nn) $(CMSIS_NN_CMAKE_FLAGS) + $(QUIET)cd $(abspath $(BUILD_DIR)/cmsis_nn) && $(MAKE) all +else +# Build CMSIS-NN +${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a: + $(QUIET)mkdir -p $(@D) + $(QUIET)cd $(CMSIS_PATH)/CMSIS/NN && $(CMAKE) -B $(abspath $(BUILD_DIR)/cmsis_nn) $(CMSIS_NN_CMAKE_FLAGS) + $(QUIET)cd $(abspath $(BUILD_DIR)/cmsis_nn) && $(MAKE) all +endif + +# Build demo application +ifneq ("$(wildcard $(CMSIS_SHA_FILE))","") +$(BUILD_DIR)/demo: $(DEMO_MAIN) $(UART_SRCS) $(BUILD_DIR)/stack_allocator.o $(BUILD_DIR)/crt_backend_api.o \ + ${BUILD_DIR}/libcodegen.a ${BUILD_DIR}/libcmsis_startup.a ${BUILD_DIR}/cmsis_nn/Source/libcmsis-nn.a + $(QUIET)mkdir -p $(@D) + $(QUIET)$(CC) $(PKG_CFLAGS) $(FREERTOS_FLAGS) -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive $(PKG_LDFLAGS) +else +$(BUILD_DIR)/demo: $(DEMO_MAIN) $(UART_SRCS) $(BUILD_DIR)/stack_allocator.o $(BUILD_DIR)/crt_backend_api.o \ + ${BUILD_DIR}/libcodegen.a ${BUILD_DIR}/libcmsis_startup.a \ + ${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a \ + ${BUILD_DIR}/cmsis_nn/Source/FullyConnectedFunctions/libCMSISNNFullyConnected.a \ + ${BUILD_DIR}/cmsis_nn/Source/SVDFunctions/libCMSISNNSVDF.a \ + ${BUILD_DIR}/cmsis_nn/Source/ReshapeFunctions/libCMSISNNReshape.a \ + ${BUILD_DIR}/cmsis_nn/Source/ActivationFunctions/libCMSISNNActivation.a \ + ${BUILD_DIR}/cmsis_nn/Source/NNSupportFunctions/libCMSISNNSupport.a \ + ${BUILD_DIR}/cmsis_nn/Source/ConcatenationFunctions/libCMSISNNConcatenation.a \ + ${BUILD_DIR}/cmsis_nn/Source/BasicMathFunctions/libCMSISNNBasicMaths.a \ + ${BUILD_DIR}/cmsis_nn/Source/ConvolutionFunctions/libCMSISNNConvolutions.a \ + ${BUILD_DIR}/cmsis_nn/Source/PoolingFunctions/libCMSISNNPooling.a + $(QUIET)mkdir -p $(@D) + $(QUIET)$(CC) $(PKG_CFLAGS) $(FREERTOS_FLAGS) -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive $(PKG_LDFLAGS) +endif + +clean: + $(QUIET)rm -rf $(BUILD_DIR)/codegen + +cleanall: + $(QUIET)rm -rf $(BUILD_DIR) + +.SUFFIXES: + +.DEFAULT: demo diff --git a/deploy/tvm/README.md b/deploy/tvm/README.md new file mode 100644 index 0000000000..ecd635cc42 --- /dev/null +++ b/deploy/tvm/README.md @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + +Running PaddleOCR text recognition model via TVM on bare metal Arm(R) Cortex(R)-M55 CPU and CMSIS-NN +=============================================================== + +This folder contains an example of how to use TVM to run a PaddleOCR model +on bare metal Cortex(R)-M55 CPU and CMSIS-NN. + +Prerequisites +------------- +If the demo is run in the ci_cpu Docker container provided with TVM, then the following +software will already be installed. + +If the demo is not run in the ci_cpu Docker container, then you will need the following: +- Software required to build and run the demo (These can all be installed by running + tvm/docker/install/ubuntu_install_ethosu_driver_stack.sh.) + - [Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps) + - [cmake 3.19.5](https://github.com/Kitware/CMake/releases/) + - [GCC toolchain from Arm(R)](https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2) + - [Arm(R) Ethos(TM)-U NPU driver stack](https://review.mlplatform.org) + - [CMSIS](https://github.com/ARM-software/CMSIS_5) +- The python libraries listed in the requirements.txt of this directory + - These can be installed by running the following from the current directory: + ```bash + pip install -r ./requirements.txt + ``` + +You will also need TVM which can either be: + - Built from source (see [Install from Source](https://tvm.apache.org/docs/install/from_source.html)) + - When building from source, the following need to be set in config.cmake: + - set(USE_CMSISNN ON) + - set(USE_MICRO ON) + - set(USE_LLVM ON) + - Installed from TLCPack nightly(see [TLCPack](https://tlcpack.ai/)) + +You will need to update your PATH environment variable to include the path to cmake 3.19.5 and the FVP. +For example if you've installed these in ```/opt/arm``` , then you would do the following: +```bash +export PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4:/opt/arm/cmake/bin:$PATH +``` + +Running the demo application +---------------------------- +Type the following command to run the bare metal text recognition application ([src/demo_bare_metal.c](./src/demo_bare_metal.c)): + +```bash +./run_demo.sh +``` + +If the Ethos(TM)-U platform and/or CMSIS have not been installed in /opt/arm/ethosu then +the locations for these can be specified as arguments to run_demo.sh, for example: + +```bash +./run_demo.sh --cmsis_path /home/tvm-user/cmsis \ +--ethosu_platform_path /home/tvm-user/ethosu/core_platform +``` + +This will: +- Download a PaddleOCR text recognition model +- Use tvmc to compile the text recognition model for Cortex(R)-M55 CPU and CMSIS-NN +- Create a C header file inputs.c containing the image data as a C array +- Create a C header file outputs.c containing a C array where the output of inference will be stored +- Build the demo application +- Run the demo application on a Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software +- The application will report the text on the image and the corresponding score. + +Using your own image +-------------------- +The create_image.py script takes a single argument on the command line which is the path of the +image to be converted into an array of bytes for consumption by the model. + +The demo can be modified to use an image of your choice by changing the following line in run_demo.sh + +```bash +python3 ./convert_image.py path/to/image +``` + +Model description +----------------- +In this demo, the model we use is an English recognition model based on [PP-OCRv3](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/PP-OCRv3_introduction.md). PP-OCRv3 is the third version of the PP-OCR series model released by [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR). This series of models has the following features: + - PP-OCRv3: ultra-lightweight OCR system: detection (3.6M) + direction classifier (1.4M) + recognition (12M) = 17.0M + - Support more than 80 kinds of multi-language recognition models, including English, Chinese, French, German, Arabic, Korean, Japanese and so on. For details + - Support vertical text recognition, and long text recognition + +The text recognition model in PP-OCRv3 supports more than 80 languages. In the process of model development, since Arm(R) Cortex(R)-M55 CPU does not support rnn operator, we delete the unsupported operator based on the PP-OCRv3 text recognition model to obtain the current model. \ No newline at end of file diff --git a/deploy/tvm/arm-none-eabi-gcc.cmake b/deploy/tvm/arm-none-eabi-gcc.cmake new file mode 100644 index 0000000000..415b3139be --- /dev/null +++ b/deploy/tvm/arm-none-eabi-gcc.cmake @@ -0,0 +1,79 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +if (__TOOLCHAIN_LOADED) + return() +endif() +set(__TOOLCHAIN_LOADED TRUE) + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_C_COMPILER "arm-none-eabi-gcc") +set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") +set(CMAKE_SYSTEM_PROCESSOR "cortex-m55" CACHE STRING "Select Arm(R) Cortex(R)-M architecture. (cortex-m0, cortex-m3, cortex-m33, cortex-m4, cortex-m55, cortex-m7, etc)") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 14) + +# The system processor could for example be set to cortex-m33+nodsp+nofp. +set(__CPU_COMPILE_TARGET ${CMAKE_SYSTEM_PROCESSOR}) +string(REPLACE "+" ";" __CPU_FEATURES ${__CPU_COMPILE_TARGET}) +list(POP_FRONT __CPU_FEATURES CMAKE_SYSTEM_PROCESSOR) + +string(FIND ${__CPU_COMPILE_TARGET} "+" __OFFSET) +if(__OFFSET GREATER_EQUAL 0) + string(SUBSTRING ${__CPU_COMPILE_TARGET} ${__OFFSET} -1 CPU_FEATURES) +endif() + +# Add -mcpu to the compile options to override the -mcpu the CMake toolchain adds +add_compile_options(-mcpu=${__CPU_COMPILE_TARGET}) + +# Set floating point unit +if("${__CPU_COMPILE_TARGET}" MATCHES "\\+fp") + set(FLOAT hard) +elseif("${__CPU_COMPILE_TARGET}" MATCHES "\\+nofp") + set(FLOAT soft) +elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "cortex-m33" OR + "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "cortex-m55") + set(FLOAT hard) +else() + set(FLOAT soft) +endif() + +add_compile_options(-mfloat-abi=${FLOAT}) +add_link_options(-mfloat-abi=${FLOAT}) + +# Link target +add_link_options(-mcpu=${__CPU_COMPILE_TARGET}) +add_link_options(-Xlinker -Map=output.map) + +# +# Compile options +# +set(cxx_flags "-fno-unwind-tables;-fno-rtti;-fno-exceptions") + +add_compile_options("-Wall;-Wextra;-Wsign-compare;-Wunused;-Wswitch-default;\ +-Wdouble-promotion;-Wredundant-decls;-Wshadow;-Wnull-dereference;\ +-Wno-format-extra-args;-Wno-unused-function;-Wno-unused-label;\ +-Wno-missing-field-initializers;-Wno-return-type;-Wno-format;-Wno-int-conversion" + "$<$:${cxx_flags}>" +) diff --git a/deploy/tvm/convert_image.py b/deploy/tvm/convert_image.py new file mode 100755 index 0000000000..747ab29e4a --- /dev/null +++ b/deploy/tvm/convert_image.py @@ -0,0 +1,102 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 os +import pathlib +import re +import sys +import cv2 +import math +from PIL import Image +import numpy as np + +def resize_norm_img(img, image_shape, padding=True): + imgC, imgH, imgW = image_shape + h = img.shape[0] + w = img.shape[1] + if not padding: + resized_image = cv2.resize( + img, (imgW, imgH), interpolation=cv2.INTER_LINEAR) + resized_w = imgW + else: + ratio = w / float(h) + if math.ceil(imgH * ratio) > imgW: + resized_w = imgW + else: + resized_w = int(math.ceil(imgH * ratio)) + resized_image = cv2.resize(img, (resized_w, imgH)) + resized_image = resized_image.astype('float32') + if image_shape[0] == 1: + resized_image = resized_image / 255 + resized_image = resized_image[np.newaxis, :] + else: + resized_image = resized_image.transpose((2, 0, 1)) / 255 + resized_image -= 0.5 + resized_image /= 0.5 + padding_im = np.zeros((imgC, imgH, imgW), dtype=np.float32) + padding_im[:, :, 0:resized_w] = resized_image + return padding_im + + +def create_header_file(name, tensor_name, tensor_data, output_path): + """ + This function generates a header file containing the data from the numpy array provided. + """ + file_path = pathlib.Path(f"{output_path}/" + name).resolve() + # Create header file with npy_data as a C array + raw_path = file_path.with_suffix(".h").resolve() + with open(raw_path, "w") as header_file: + header_file.write( + "\n" + + f"const size_t {tensor_name}_len = {tensor_data.size};\n" + + f'__attribute__((section(".data.tvm"), aligned(16))) float {tensor_name}[] = ' + ) + + header_file.write("{") + for i in np.ndindex(tensor_data.shape): + header_file.write(f"{tensor_data[i]}, ") + header_file.write("};\n\n") + + +def create_headers(image_name): + """ + This function generates C header files for the input and output arrays required to run inferences + """ + img_path = os.path.join("./", f"{image_name}") + + # Resize image to 32x320 + img = cv2.imread(img_path) + img = resize_norm_img(img, [3,32,320]) + img_data = img.astype("float32") + + # # Add the batch dimension, as we are expecting 4-dimensional input: NCHW. + img_data = np.expand_dims(img_data, axis=0) + + # Create input header file + create_header_file("inputs", "input", img_data, "./include") + # Create output header file + output_data = np.zeros([7760], np.float) + create_header_file( + "outputs", + "output", + output_data, + "./include", + ) + + +if __name__ == "__main__": + create_headers(sys.argv[1]) diff --git a/deploy/tvm/corstone300.ld b/deploy/tvm/corstone300.ld new file mode 100644 index 0000000000..e52b23da33 --- /dev/null +++ b/deploy/tvm/corstone300.ld @@ -0,0 +1,295 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/*------------------ Reference System Memories ------------- + +===================+============+=======+============+============+ + | Memory | Address | Size | CPU Access | NPU Access | + +===================+============+=======+============+============+ + | ITCM | 0x00000000 | 512KB | Yes (RO) | No | + +-------------------+------------+-------+------------+------------+ + | DTCM | 0x20000000 | 512KB | Yes (R/W) | No | + +-------------------+------------+-------+------------+------------+ + | SSE-300 SRAM | 0x21000000 | 2MB | Yes (R/W) | Yes (R/W) | + +-------------------+------------+-------+------------+------------+ + | Data SRAM | 0x01000000 | 2MB | Yes (R/W) | Yes (R/W) | + +-------------------+------------+-------+------------+------------+ + | DDR | 0x60000000 | 32MB | Yes (R/W) | Yes (R/W) | + +-------------------+------------+-------+------------+------------+ */ + +/*---------------------- ITCM Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__ROM_BASE = 0x00000000; +__ROM_SIZE = 0x00080000; + +/*--------------------- DTCM RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__RAM_BASE = 0x20000000; +__RAM_SIZE = 0x00080000; + +/*----------------------- Data SRAM Configuration ------------------------------ + Data SRAM Configuration + DATA_SRAM Base Address <0x0-0xFFFFFFFF:8> + DATA_SRAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__DATA_SRAM_BASE = 0x01000000; +__DATA_SRAM_SIZE = 0x00200000; + +/*--------------------- Embedded SRAM Configuration ---------------------------- + SRAM Configuration + SRAM Base Address <0x0-0xFFFFFFFF:8> + SRAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__SRAM_BASE = 0x21000000; +__SRAM_SIZE = 0x00200000; + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x00008000; +__HEAP_SIZE = 0x00008000; + +/*--------------------- Embedded RAM Configuration ---------------------------- + DDR Configuration + DDR Base Address <0x0-0xFFFFFFFF:8> + DDR Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__DDR_BASE = 0x60000000; +__DDR_SIZE = 0x02000000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + ITCM (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + DTCM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE + DATA_SRAM (rwx) : ORIGIN = __DATA_SRAM_BASE, LENGTH = __DATA_SRAM_SIZE + SRAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + DDR (rwx) : ORIGIN = __DDR_BASE, LENGTH = __DDR_SIZE +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions ITCM and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + /* .ddr is placed before .text so that .rodata.tvm is encountered before .rodata* */ + .ddr : + { + . = ALIGN (16); + *(.rodata.tvm) + . = ALIGN (16); + *(.data.tvm); + . = ALIGN(16); + } > DDR + + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ITCM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ITCM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ITCM + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + /* Add each additional data section here */ + __copy_table_end__ = .; + } > ITCM + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + __zero_table_end__ = .; + } > ITCM + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in DTCM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .sram : + { + . = ALIGN(16); + } > SRAM AT > SRAM + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > DTCM + + .bss.noinit (NOLOAD): + { + . = ALIGN(16); + *(.bss.noinit.*) + . = ALIGN(16); + } > SRAM AT > SRAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > DTCM AT > DTCM + + .data_sram : + { + . = ALIGN(16); + } > DATA_SRAM + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > DTCM + + .stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > DTCM + PROVIDE(__stack = __StackTop); + + /* Check if data + stack exceeds DTCM limit */ + ASSERT(__StackLimit >= __bss_end__, "region DTCM overflowed with stack") +} diff --git a/deploy/tvm/imgs_words_en/word_10.png b/deploy/tvm/imgs_words_en/word_10.png new file mode 100644 index 0000000000000000000000000000000000000000..07370f757ea83d5e3c5b1f7498b1f95d3aec2d18 GIT binary patch literal 5738 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 literal 0 HcmV?d00001 diff --git a/deploy/tvm/imgs_words_en/word_116.png b/deploy/tvm/imgs_words_en/word_116.png new file mode 100644 index 0000000000000000000000000000000000000000..fd000ff60b0a7a87c8c16eb1409aa0548228e3f9 GIT binary patch literal 74135 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�}bF4*@Oy3CHa5NB!fD2gDqM1;rc>jy(|+dv8F}IeYTC{|_{!Wp;12Z-)Q? N002ovPDHLkV1m!NmvR6A literal 0 HcmV?d00001 diff --git a/deploy/tvm/include/crt_config.h b/deploy/tvm/include/crt_config.h new file mode 100644 index 0000000000..4b9ccca02b --- /dev/null +++ b/deploy/tvm/include/crt_config.h @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef TVM_RUNTIME_CRT_CONFIG_H_ +#define TVM_RUNTIME_CRT_CONFIG_H_ + +/*! Log level of the CRT runtime */ +#define TVM_CRT_LOG_LEVEL TVM_CRT_LOG_LEVEL_DEBUG + +#endif // TVM_RUNTIME_CRT_CONFIG_H_ diff --git a/deploy/tvm/include/tvm_runtime.h b/deploy/tvm/include/tvm_runtime.h new file mode 100644 index 0000000000..2b59d93470 --- /dev/null +++ b/deploy/tvm/include/tvm_runtime.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __attribute__((noreturn)) TVMPlatformAbort(tvm_crt_error_t error_code) { + printf("TVMPlatformAbort: %d\n", error_code); + printf("EXITTHESIM\n"); + exit(-1); +} + +tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) { + return kTvmErrorFunctionCallNotImplemented; +} + +tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) { + return kTvmErrorFunctionCallNotImplemented; +} + +void TVMLogf(const char* msg, ...) { + va_list args; + va_start(args, msg); + vfprintf(stdout, msg, args); + va_end(args); +} + +TVM_DLL int TVMFuncRegisterGlobal(const char* name, TVMFunctionHandle f, int override) { return 0; } + +#ifdef __cplusplus +} +#endif diff --git a/deploy/tvm/requirements.txt b/deploy/tvm/requirements.txt new file mode 100644 index 0000000000..1bf86ed110 --- /dev/null +++ b/deploy/tvm/requirements.txt @@ -0,0 +1,3 @@ +paddlepaddle +numpy +opencv-python \ No newline at end of file diff --git a/deploy/tvm/run_demo.sh b/deploy/tvm/run_demo.sh new file mode 100755 index 0000000000..dd8e8f163d --- /dev/null +++ b/deploy/tvm/run_demo.sh @@ -0,0 +1,152 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +set -e +set -u +set -o pipefail + +# Show usage +function show_usage() { + cat <&2 + show_usage >&2 + exit 1 + fi + ;; + + --ethosu_platform_path) + if [ $# -gt 1 ] + then + export ETHOSU_PLATFORM_PATH="$2" + shift 2 + else + echo 'ERROR: --ethosu_platform_path requires a non-empty argument' >&2 + show_usage >&2 + exit 1 + fi + ;; + + --fvp_path) + if [ $# -gt 1 ] + then + export PATH="$2/models/Linux64_GCC-6.4:$PATH" + shift 2 + else + echo 'ERROR: --fvp_path requires a non-empty argument' >&2 + show_usage >&2 + exit 1 + fi + ;; + + --cmake_path) + if [ $# -gt 1 ] + then + export CMAKE="$2" + shift 2 + else + echo 'ERROR: --cmake_path requires a non-empty argument' >&2 + show_usage >&2 + exit 1 + fi + ;; + + -*|--*) + echo "Error: Unknown flag: $1" >&2 + show_usage >&2 + exit 1 + ;; + esac +done + + +# Directories +script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + + +# Make build directory +rm -rf build +make cleanall +mkdir -p build +cd build + +wget https://paddleocr.bj.bcebos.com/tvm/ocr_en.tar +tar -xf ocr_en.tar + +# Compile model for Arm(R) Cortex(R)-M55 CPU and CMSIS-NN +# An alternative to using "python3 -m tvm.driver.tvmc" is to call +# "tvmc" directly once TVM has been pip installed. +python3 -m tvm.driver.tvmc compile --target=cmsis-nn,c \ + --target-cmsis-nn-mcpu=cortex-m55 \ + --target-c-mcpu=cortex-m55 \ + --runtime=crt \ + --executor=aot \ + --executor-aot-interface-api=c \ + --executor-aot-unpacked-api=1 \ + --pass-config tir.usmp.enable=1 \ + --pass-config tir.usmp.algorithm=hill_climb \ + --pass-config tir.disable_storage_rewrite=1 \ + --pass-config tir.disable_vectorize=1 ocr_en/inference.pdmodel \ + --output-format=mlf \ + --model-format=paddle \ + --module-name=rec \ + --input-shapes x:[1,3,32,320] \ + --output=rec.tar +tar -xf rec.tar + +# Create C header files +cd .. +python3 ./convert_image.py imgs_words_en/word_116.png + +# Build demo executable +cd ${script_dir} +echo ${script_dir} +make + +# Run demo executable on the FVP +FVP_Corstone_SSE-300_Ethos-U55 -C cpu0.CFGDTCMSZ=15 \ +-C cpu0.CFGITCMSZ=15 -C mps3_board.uart0.out_file=\"-\" -C mps3_board.uart0.shutdown_tag=\"EXITTHESIM\" \ +-C mps3_board.visualisation.disable-visualisation=1 -C mps3_board.telnetterminal0.start_telnet=0 \ +-C mps3_board.telnetterminal1.start_telnet=0 -C mps3_board.telnetterminal2.start_telnet=0 -C mps3_board.telnetterminal5.start_telnet=0 \ +./build/demo \ No newline at end of file diff --git a/deploy/tvm/src/demo_bare_metal.c b/deploy/tvm/src/demo_bare_metal.c new file mode 100644 index 0000000000..3f5f1bc4b0 --- /dev/null +++ b/deploy/tvm/src/demo_bare_metal.c @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include + +#include "uart.h" + +// Header files generated by convert_image.py +#include "inputs.h" +#include "outputs.h" + + +int main(int argc, char** argv) { + char dict[]={"#0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./ "}; + int char_dict_nums = 97; + uart_init(); + printf("Starting ocr rec inference\n"); + struct tvmgen_rec_outputs rec_outputs = { + .output = output, + }; + struct tvmgen_rec_inputs rec_inputs = { + .x = input, + }; + + tvmgen_rec_run(&rec_inputs, &rec_outputs); + + // post process + int char_nums = output_len / char_dict_nums; + + int last_index = 0; + float score = 0.f; + int count = 0; + + printf("text: "); + for (int i = 0; i < char_nums; i++) { + int argmax_idx = 0; + float max_value = 0.0f; + for (int j = 0; j < char_dict_nums; j++){ + if (output[i * char_dict_nums + j] > max_value){ + max_value = output[i * char_dict_nums + j]; + argmax_idx = j; + } + } + if (argmax_idx > 0 && (!(i > 0 && argmax_idx == last_index))) { + score += max_value; + count += 1; + // printf("%d,%f,%c\n", argmax_idx, max_value, dict[argmax_idx]); + printf("%c", dict[argmax_idx]); + } + last_index = argmax_idx; + } + score /= count; + printf(", score: %f\n", score); + + // The FVP will shut down when it receives "EXITTHESIM" on the UART + printf("EXITTHESIM\n"); + while (1 == 1) + ; + return 0; +} From cdb0804746a797a4520f5d75319d8838e00d9a51 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 20 Jun 2022 02:10:22 +0000 Subject: [PATCH 100/129] fix fleet tipc --- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- .../train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 5fb87fae18..91a6288eb0 100644 --- a/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ infer_model:./inference/ch_PP-OCRv2_det_infer/ infer_export:null infer_quant:False inference:tools/infer/predict_det.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1 diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 4af814036a..5795bc27e6 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv2_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ infer_model:./inference/ch_PP-OCRv2_rec_infer infer_export:null infer_quant:False inference:tools/infer/predict_rec.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1|6 diff --git a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 8275254f3f..7e987125a6 100644 --- a/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_PP-OCRv3_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ infer_model:./inference/ch_PP-OCRv3_det_infer/ infer_export:null infer_quant:False inference:tools/infer/predict_det.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1 diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index b76048813e..5271f78bb7 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ train_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o infer_quant:False inference:tools/infer/predict_det.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1 diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 3a7c487173..631118c0a9 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ train_model:./inference/ch_ppocr_mobile_v2.0_rec_train/best_accuracy infer_export:tools/export_model.py -c configs/rec/rec_icdar15_train.yml -o infer_quant:False inference:tools/infer/predict_rec.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1|6 diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index 77b69f6c3a..12388d9677 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_det/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ train_model:./inference/ch_ppocr_server_v2.0_det_train/best_accuracy infer_export:tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml -o infer_quant:False inference:tools/infer/predict_det.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1 diff --git a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt index d486d37668..9884ab247b 100644 --- a/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt +++ b/test_tipc/configs/ch_ppocr_server_v2.0_rec/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -38,7 +38,7 @@ train_model:./inference/ch_ppocr_server_v2.0_rec_train/best_accuracy infer_export:tools/export_model.py -c test_tipc/configs/ch_ppocr_server_v2.0_rec/rec_icdar15_train.yml -o infer_quant:False inference:tools/infer/predict_rec.py ---use_gpu:True|False +--use_gpu:False --enable_mkldnn:False --cpu_threads:6 --rec_batch_num:1|6 From 49215a1afeffb6ca1a61d14c60ed87440a865a7a Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Mon, 20 Jun 2022 04:00:47 +0000 Subject: [PATCH 101/129] rename to avh --- deploy/{tvm => avh}/.gitignore | 0 deploy/{tvm => avh}/Makefile | 0 deploy/{tvm => avh}/README.md | 0 deploy/{tvm => avh}/arm-none-eabi-gcc.cmake | 0 deploy/{tvm => avh}/convert_image.py | 0 deploy/{tvm => avh}/corstone300.ld | 0 deploy/{tvm => avh}/imgs_words_en/word_10.png | Bin deploy/{tvm => avh}/imgs_words_en/word_116.png | Bin deploy/{tvm => avh}/include/crt_config.h | 0 deploy/{tvm => avh}/include/tvm_runtime.h | 0 deploy/{tvm => avh}/requirements.txt | 0 deploy/{tvm => avh}/run_demo.sh | 0 deploy/{tvm => avh}/src/demo_bare_metal.c | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename deploy/{tvm => avh}/.gitignore (100%) rename deploy/{tvm => avh}/Makefile (100%) rename deploy/{tvm => avh}/README.md (100%) rename deploy/{tvm => avh}/arm-none-eabi-gcc.cmake (100%) rename deploy/{tvm => avh}/convert_image.py (100%) rename deploy/{tvm => avh}/corstone300.ld (100%) rename deploy/{tvm => avh}/imgs_words_en/word_10.png (100%) rename deploy/{tvm => avh}/imgs_words_en/word_116.png (100%) rename deploy/{tvm => avh}/include/crt_config.h (100%) rename deploy/{tvm => avh}/include/tvm_runtime.h (100%) rename deploy/{tvm => avh}/requirements.txt (100%) rename deploy/{tvm => avh}/run_demo.sh (100%) rename deploy/{tvm => avh}/src/demo_bare_metal.c (100%) diff --git a/deploy/tvm/.gitignore b/deploy/avh/.gitignore similarity index 100% rename from deploy/tvm/.gitignore rename to deploy/avh/.gitignore diff --git a/deploy/tvm/Makefile b/deploy/avh/Makefile similarity index 100% rename from deploy/tvm/Makefile rename to deploy/avh/Makefile diff --git a/deploy/tvm/README.md b/deploy/avh/README.md similarity index 100% rename from deploy/tvm/README.md rename to deploy/avh/README.md diff --git a/deploy/tvm/arm-none-eabi-gcc.cmake b/deploy/avh/arm-none-eabi-gcc.cmake similarity index 100% rename from deploy/tvm/arm-none-eabi-gcc.cmake rename to deploy/avh/arm-none-eabi-gcc.cmake diff --git a/deploy/tvm/convert_image.py b/deploy/avh/convert_image.py similarity index 100% rename from deploy/tvm/convert_image.py rename to deploy/avh/convert_image.py diff --git a/deploy/tvm/corstone300.ld b/deploy/avh/corstone300.ld similarity index 100% rename from deploy/tvm/corstone300.ld rename to deploy/avh/corstone300.ld diff --git a/deploy/tvm/imgs_words_en/word_10.png b/deploy/avh/imgs_words_en/word_10.png similarity index 100% rename from deploy/tvm/imgs_words_en/word_10.png rename to deploy/avh/imgs_words_en/word_10.png diff --git a/deploy/tvm/imgs_words_en/word_116.png b/deploy/avh/imgs_words_en/word_116.png similarity index 100% rename from deploy/tvm/imgs_words_en/word_116.png rename to deploy/avh/imgs_words_en/word_116.png diff --git a/deploy/tvm/include/crt_config.h b/deploy/avh/include/crt_config.h similarity index 100% rename from deploy/tvm/include/crt_config.h rename to deploy/avh/include/crt_config.h diff --git a/deploy/tvm/include/tvm_runtime.h b/deploy/avh/include/tvm_runtime.h similarity index 100% rename from deploy/tvm/include/tvm_runtime.h rename to deploy/avh/include/tvm_runtime.h diff --git a/deploy/tvm/requirements.txt b/deploy/avh/requirements.txt similarity index 100% rename from deploy/tvm/requirements.txt rename to deploy/avh/requirements.txt diff --git a/deploy/tvm/run_demo.sh b/deploy/avh/run_demo.sh similarity index 100% rename from deploy/tvm/run_demo.sh rename to deploy/avh/run_demo.sh diff --git a/deploy/tvm/src/demo_bare_metal.c b/deploy/avh/src/demo_bare_metal.c similarity index 100% rename from deploy/tvm/src/demo_bare_metal.c rename to deploy/avh/src/demo_bare_metal.c From bdc43081771e0a63803026d177f56ab2ef60f50c Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Mon, 20 Jun 2022 11:40:35 +0000 Subject: [PATCH 102/129] fix timeout --- .../det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt | 4 ++-- test_tipc/prepare.sh | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt index de9e336332..b70ef46b4a 100644 --- a/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt +++ b/test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/train_infer_python.txt @@ -7,13 +7,13 @@ Global.auto_cast:null Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=500 Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 -Global.pretrained_model:null +Global.pretrained_model:./pretrain_models/det_r50_vd_sast_icdar15_v2.0_train/best_accuracy train_model_name:latest train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ null:null ## trainer:norm_train -norm_train:tools/train.py -c test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/det_r50_vd_sast_icdar2015.yml -o Global.pretrained_model=./pretrain_models/ResNet50_vd_ssld_pretrained +norm_train:tools/train.py -c test_tipc/configs/det_r50_vd_sast_icdar15_v2.0/det_r50_vd_sast_icdar2015.yml -o pact_train:null fpgm_train:null distill_train:null diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index 8c9e12511d..cac373dedc 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -98,8 +98,9 @@ if [ ${MODE} = "lite_train_lite_infer" ];then fi if [ ${model_name} == "det_r50_vd_sast_icdar15_v2.0" ] || [ ${model_name} == "det_r50_vd_sast_totaltext_v2.0" ]; then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_ssld_pretrained.pdparams --no-check-certificate + wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/total_text_lite.tar --no-check-certificate - cd ./train_data && tar xf total_text_lite.tar && ln -s total_text_lite total_text && cd ../ + cd ./train_data && tar xf total_text_lite.tar && ln -s total_text_lite total_text && tar xf det_r50_vd_sast_icdar15_v2.0_train.tar && cd ../ fi if [ ${model_name} == "det_mv3_db_v2_0" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_db_v2.0_train.tar --no-check-certificate From 89567ae300e6cd827d225a1dd1f7888904fdb51f Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:21:58 +0800 Subject: [PATCH 103/129] fix --- tools/infer/predict_det.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index 5f2675d667..73387aef59 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -24,6 +24,7 @@ import cv2 import numpy as np import time import sys +from scipy.spatial import distance as dist import tools.infer.utility as utility from ppocr.utils.logging import get_logger @@ -150,14 +151,22 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="float32") - s = pts.sum(axis=1) - rect[0] = pts[np.argmin(s)] - rect[2] = pts[np.argmax(s)] - diff = np.diff(pts, axis=1) - rect[1] = pts[np.argmin(diff)] - rect[3] = pts[np.argmax(diff)] - return rect + """ + refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 + """ + # sort the points based on their x-coordinates + xSorted = pts[np.argsort(pts[:, 0]), :] + + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + + D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] + (br, tr) = rightMost[np.argsort(D)[::-1], :] + + return np.array([tl, tr, br, bl], dtype="float32") def clip_det_res(self, points, img_height, img_width): for pno in range(points.shape[0]): From 4b85f7e3e4b0c10b7d0f76e181e30ab56d80c6ce Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:24:47 +0800 Subject: [PATCH 104/129] fix --- applications/轻量级车牌识别.md | 2831 -------------------------------- 1 file changed, 2831 deletions(-) delete mode 100644 applications/轻量级车牌识别.md diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md deleted file mode 100644 index b6c3847d14..0000000000 --- a/applications/轻量级车牌识别.md +++ /dev/null @@ -1,2831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - - - -
- -
- - - - - - - -
- - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - -
- - - - - - -
- - -
- - - - - - - - -Permalink - -
- -
-
- - - dygraph - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - Go to file - - -
- - - - - -
-
-
- - - - - - - - - -
- -
-
-
 
-
- -
-
 
- Cannot retrieve contributors at this time -
-
- - - - - - - - - -
- - - - -
-

一种基于PaddleOCR的轻量级车牌识别模型

- -

1. 项目介绍

-

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

-

本项目难点如下:

-
    -
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. -
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. -
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. -
-

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

-

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

-

2. 环境搭建

-

本任务基于Aistudio完成, 具体环境如下:

-
    -
  • 操作系统: Linux
  • -
  • PaddlePaddle: 2.3
  • -
  • paddleslim: 2.2.2
  • -
  • PaddleOCR: Release/2.5
  • -
-

下载 PaddleOCR代码

-
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
-

安装依赖库

-
pip install -r PaddleOCR/requirements.txt
-

3. 数据集准备

-

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

-

该数据集分布如下:

- - - - - - - - - - - - - - - - - - - - - -
数据集类型数量
训练集5769
验证集1001
测试集5006
-

数据集图片示例如下: -

-

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

-

下载好数据集后对数据集进行解压

-
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
-

3.1 数据集标注规则

-

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

-

具体规则如下:

-

例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg

-

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

-
    -
  • -

    025:车牌面积与整个图片区域的面积比。025 (25%)

    -
  • -
  • -

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    -
  • -
  • -

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    -
  • -
  • -

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    -
  • -
  • -

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    -
  • -
  • -

    37:牌照区域的亮度。 37 (37%)

    -
  • -
  • -

    15:车牌区域的模糊度。15 (15%)

    -
  • -
-
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', 'O']
-ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
-

3.2 制作符合PP-OCR训练格式的标注文件

-

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

-
import cv2
-import os
-import json
-from tqdm import tqdm
-import numpy as np
-
-provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O']
-ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
-
-def make_label(img_dir, save_gt_folder, phase):
-    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
-    os.makedirs(crop_img_save_dir, exist_ok=True)
-
-    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
-    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
-
-    i = 0
-    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
-        str_list = filename.split('-')
-        if len(str_list) < 5:
-            continue
-        coord_list = str_list[3].split('_')
-        txt_list = str_list[4].split('_')
-        boxes = []
-        for coord in coord_list:
-            boxes.append([int(x) for x in coord.split("&")])
-        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
-        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
-
-        # det
-        det_info = [{'points':boxes, 'transcription':lp_number}]
-        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
-
-        # rec
-        boxes = np.float32(boxes)
-        img = cv2.imread(os.path.join(img_dir, phase, filename))
-        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
-        crop_img = get_rotate_crop_image(img, boxes)
-        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
-        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
-        cv2.imwrite(crop_img_save_path, crop_img)
-        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
-        i+=1
-    f_det.close()
-    f_rec.close()
-
-def get_rotate_crop_image(img, points):
-    '''
-    img_height, img_width = img.shape[0:2]
-    left = int(np.min(points[:, 0]))
-    right = int(np.max(points[:, 0]))
-    top = int(np.min(points[:, 1]))
-    bottom = int(np.max(points[:, 1]))
-    img_crop = img[top:bottom, left:right, :].copy()
-    points[:, 0] = points[:, 0] - left
-    points[:, 1] = points[:, 1] - top
-    '''
-    assert len(points) == 4, "shape of points must be 4*2"
-    img_crop_width = int(
-        max(
-            np.linalg.norm(points[0] - points[1]),
-            np.linalg.norm(points[2] - points[3])))
-    img_crop_height = int(
-        max(
-            np.linalg.norm(points[0] - points[3]),
-            np.linalg.norm(points[1] - points[2])))
-    pts_std = np.float32([[0, 0], [img_crop_width, 0],
-                          [img_crop_width, img_crop_height],
-                          [0, img_crop_height]])
-    M = cv2.getPerspectiveTransform(points, pts_std)
-    dst_img = cv2.warpPerspective(
-        img,
-        M, (img_crop_width, img_crop_height),
-        borderMode=cv2.BORDER_REPLICATE,
-        flags=cv2.INTER_CUBIC)
-    dst_img_height, dst_img_width = dst_img.shape[0:2]
-    if dst_img_height * 1.0 / dst_img_width >= 1.5:
-        dst_img = np.rot90(dst_img)
-    return dst_img
-
-img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
-save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
-# phase = 'train' # change to val and test to make val dataset and test dataset
-for phase in ['train','val','test']:
-    make_label(img_dir, save_gt_folder, phase)
-

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
-

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

-

4. 实验

-

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

-

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

-

因此,本实验中对于车牌检测和识别有如下3种方案:

-
    -
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. -
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. -
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. -
-

4.1 检测

-

4.1.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本检测预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
-tar -xf ch_PP-OCRv3_det_distill_train.tar
-cd /home/aistudio/PaddleOCR
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
-

4.1.2 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关: -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关: -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

-
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/det \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

在上述命令中,通过-o的方式修改了配置文件中的参数。

-

训练好的模型地址为: det_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
-

可以看到进行fine-tune能显著提升车牌检测的效果。

-

4.1.3 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/det_quant \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

训练好的模型地址为: det_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
-

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

-

速度测试基于PaddleOCR lite教程完成。

-

4.1.4 模型导出

-

使用如下命令可以将训练好的模型进行导出

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-

4.2 识别

-

4.2.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本识别预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
-tar -xf ch_PP-OCRv3_rec_train.tar
-cd /home/aistudio/PaddleOCR
-

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

-
import paddle
-# 加载预训练模型
-all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
-# 查看权重参数的keys
-print(all_params.keys())
-# 学生模型的权重提取
-s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
-# 查看学生模型权重参数的keys
-print(s_params.keys())
-# 保存
-paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

评估部分日志如下:

-
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
-eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
-[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
-[2022/05/12 19:52:17] ppocr INFO: acc:0.0
-[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
-[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
-[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
-[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
-
-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
-

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

-
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
-

输出部分日志如下:

-
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
-W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
-W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
-[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
-[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
-[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
-[2022/05/01 08:52:00] ppocr INFO: success!
-

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

-
    -
  1. 直接通过后处理去掉多识别的·。
  2. -
  3. 进行 fine-tune。
  4. -
-

4.2.2 预训练模型直接预测+改动后处理

-

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

-
text = text.replace('·','')
-

改动前后指标对比:

- - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
-

可以看到,去掉多余的·能大幅提高精度。

-

4.2.3 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关 -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关 -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下命令启动 fine-tune

-
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/rec/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
-

可以看到进行fine-tune能显著提升车牌识别的效果。

-

4.2.4 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/rec_quant/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

-

速度测试基于PaddleOCR lite教程完成。

-

4.2.5 模型导出

-

使用如下命令可以将训练好的模型进行导出。

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer
-

4.3 计算End2End指标

-

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

-
    -
  1. 导出模型
  2. -
-

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

-
# 检测模型
-
-# 预训练模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
-    Eval.loader.num_workers=0
-
-# 识别模型
-
-# 预训练模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-
    -
  1. 用导出的模型对测试集进行预测
  2. -
-

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

-
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
-python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
-
-# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
-
    -
  1. 转换label并计算指标
  2. -
-

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

-
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
-# 需手动修改后处理函数
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
-

日志如下:

-
The convert label saved in end2end/gt
-The convert label saved in end2end/pretrain
-start testing...
-hit, dt_count, gt_count 2 5988 5006
-character_acc: 70.42%
-avg_edit_dist_field: 2.37
-avg_edit_dist_img: 2.37
-precision: 0.03%
-recall: 0.04%
-fmeasure: 0.04%
-The convert label saved in end2end/post
-start testing...
-hit, dt_count, gt_count 4224 5988 5006
-character_acc: 81.59%
-avg_edit_dist_field: 1.47
-avg_edit_dist_img: 1.47
-precision: 70.54%
-recall: 84.38%
-fmeasure: 76.84%
-The convert label saved in end2end/fine-tune
-start testing...
-hit, dt_count, gt_count 4286 4898 5006
-character_acc: 94.16%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.51%
-recall: 85.62%
-fmeasure: 86.55%
-The convert label saved in end2end/quant
-start testing...
-hit, dt_count, gt_count 4349 4951 5006
-character_acc: 94.13%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.84%
-recall: 86.88%
-fmeasure: 87.36%
-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

-

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

-

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

-
if len(txt) != 8: # 车牌字符串长度为8
-    continue
-

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

-

-

修改前后个方案指标对比如下:

-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

-

4.4 部署

-
    -
  • 基于 Paddle Inference 的python推理
  • -
-

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

-
python tools/infer/predict_system.py \
-    --det_model_dir=output/CCPD/det/infer/ \
-    --rec_model_dir=output/CCPD/rec/infer/ \
-    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
-    --rec_image_shape=3,48,320
-

推理结果如下

-

-
    -
  • 端侧部署
  • -
-

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

-

4.5 实验总结

-

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

-
    -
  • 检测
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
-
    -
  • 识别
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-
    -
  • 端到端指标如下:
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
-

结论

-

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

-

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

-

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

-
-
- -
- -
- - - -
- - -
- - -
-
- - - - -
- -
- - -
- - -
-
- -
- - - - - - - - - - - - - - - - - - - - From 1ad3ba3ee6ba7debb4b4970faf3ce9fc3245f56c Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 21 Jun 2022 07:27:24 +0000 Subject: [PATCH 105/129] update kl pact config --- .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 .../train_ptq_infer_python.txt} | 0 ...python.txt => train_pact_infer_python.txt} | 0 test_tipc/prepare.sh | 5 +- test_tipc/test_ptq_inference_python.sh | 157 ++++++++++++++++++ 16 files changed, 160 insertions(+), 2 deletions(-) rename test_tipc/configs/{ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_PP-OCRv2_det/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_PP-OCRv2_det_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_PP-OCRv2_rec/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_PP-OCRv2_rec_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_PP-OCRv3_det/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_PP-OCRv3_det_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_PP-OCRv3_rec/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_PP-OCRv3_rec_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_ppocr_mobile_v2.0_det/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => ch_ppocr_mobile_v2.0_rec/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) rename test_tipc/configs/{en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt => en_table_structure/train_ptq_infer_python.txt} (100%) rename test_tipc/configs/en_table_structure_PACT/{train_infer_python.txt => train_pact_infer_python.txt} (100%) create mode 100644 test_tipc/test_ptq_inference_python.sh diff --git a/test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_PP-OCRv2_det/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_det_PACT/train_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv2_det_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_PP-OCRv2_rec/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_PP-OCRv3_det/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_det_PACT/train_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv3_det_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_PP-OCRv3_rec/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_det_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_infer_python.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_rec_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_ptq_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_infer_python.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_pact_infer_python.txt diff --git a/test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure/train_ptq_infer_python.txt similarity index 100% rename from test_tipc/configs/en_table_structure_KL/model_linux_gpu_normal_normal_infer_python_linux_gpu_cpu.txt rename to test_tipc/configs/en_table_structure/train_ptq_infer_python.txt diff --git a/test_tipc/configs/en_table_structure_PACT/train_infer_python.txt b/test_tipc/configs/en_table_structure_PACT/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/en_table_structure_PACT/train_infer_python.txt rename to test_tipc/configs/en_table_structure_PACT/train_pact_infer_python.txt diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh index cac373dedc..2c9bd2901b 100644 --- a/test_tipc/prepare.sh +++ b/test_tipc/prepare.sh @@ -100,7 +100,8 @@ if [ ${MODE} = "lite_train_lite_infer" ];then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_ssld_pretrained.pdparams --no-check-certificate wget -nc -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar --no-check-certificate wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/total_text_lite.tar --no-check-certificate - cd ./train_data && tar xf total_text_lite.tar && ln -s total_text_lite total_text && tar xf det_r50_vd_sast_icdar15_v2.0_train.tar && cd ../ + cd ./train_data && tar xf total_text_lite.tar && ln -s total_text_lite total_text && cd ../ + cd ./pretrain_models && tar xf det_r50_vd_sast_icdar15_v2.0_train.tar && cd ../ fi if [ ${model_name} == "det_mv3_db_v2_0" ]; then wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_db_v2.0_train.tar --no-check-certificate @@ -353,7 +354,7 @@ elif [ ${MODE} = "whole_infer" ];then fi fi -if [ ${MODE} = "klquant_whole_infer" ]; then +if [[ ${model_name} =~ "KL" ]]; then wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015_lite.tar --no-check-certificate cd ./train_data/ && tar xf icdar2015_lite.tar && rm -rf ./icdar2015 && ln -s ./icdar2015_lite ./icdar2015 && cd ../ if [ ${model_name} = "ch_ppocr_mobile_v2.0_det_KL" ]; then diff --git a/test_tipc/test_ptq_inference_python.sh b/test_tipc/test_ptq_inference_python.sh new file mode 100644 index 0000000000..2454c0b50a --- /dev/null +++ b/test_tipc/test_ptq_inference_python.sh @@ -0,0 +1,157 @@ +#!/bin/bash +source test_tipc/common_func.sh + +FILENAME=$1 +# MODE be one of [''whole_infer'] +MODE=$2 + +IFS=$'\n' +# parser klquant_infer params + +dataline=$(awk 'NR==1, NR==17{print}' $FILENAME) +lines=(${dataline}) +model_name=$(func_parser_value "${lines[1]}") +python=$(func_parser_value "${lines[2]}") +export_weight=$(func_parser_key "${lines[3]}") +save_infer_key=$(func_parser_key "${lines[4]}") +# parser inference model +infer_model_dir_list=$(func_parser_value "${lines[5]}") +infer_export_list=$(func_parser_value "${lines[6]}") +infer_is_quant=$(func_parser_value "${lines[7]}") +# parser inference +inference_py=$(func_parser_value "${lines[8]}") +use_gpu_key=$(func_parser_key "${lines[9]}") +use_gpu_list=$(func_parser_value "${lines[9]}") +use_mkldnn_key=$(func_parser_key "${lines[10]}") +use_mkldnn_list=$(func_parser_value "${lines[10]}") +cpu_threads_key=$(func_parser_key "${lines[11]}") +cpu_threads_list=$(func_parser_value "${lines[11]}") +batch_size_key=$(func_parser_key "${lines[12]}") +batch_size_list=$(func_parser_value "${lines[12]}") +use_trt_key=$(func_parser_key "${lines[13]}") +use_trt_list=$(func_parser_value "${lines[13]}") +precision_key=$(func_parser_key "${lines[14]}") +precision_list=$(func_parser_value "${lines[14]}") +infer_model_key=$(func_parser_key "${lines[15]}") +image_dir_key=$(func_parser_key "${lines[16]}") +infer_img_dir=$(func_parser_value "${lines[16]}") +save_log_key=$(func_parser_key "${lines[17]}") +save_log_value=$(func_parser_value "${lines[17]}") +benchmark_key=$(func_parser_key "${lines[18]}") +benchmark_value=$(func_parser_value "${lines[18]}") +infer_key1=$(func_parser_key "${lines[19]}") +infer_value1=$(func_parser_value "${lines[19]}") + + +LOG_PATH="./test_tipc/output/${model_name}/${MODE}" +mkdir -p ${LOG_PATH} +status_log="${LOG_PATH}/results_python.log" + + +function func_inference(){ + IFS='|' + _python=$1 + _script=$2 + _model_dir=$3 + _log_path=$4 + _img_dir=$5 + _flag_quant=$6 + # inference + for use_gpu in ${use_gpu_list[*]}; do + if [ ${use_gpu} = "False" ] || [ ${use_gpu} = "cpu" ]; then + for use_mkldnn in ${use_mkldnn_list[*]}; do + for threads in ${cpu_threads_list[*]}; do + for batch_size in ${batch_size_list[*]}; do + for precision in ${precision_list[*]}; do + if [ ${use_mkldnn} = "False" ] && [ ${precision} = "fp16" ]; then + continue + fi # skip when enable fp16 but disable mkldnn + if [ ${_flag_quant} = "True" ] && [ ${precision} != "int8" ]; then + continue + fi # skip when quant model inference but precision is not int8 + set_precision=$(func_set_params "${precision_key}" "${precision}") + + _save_log_path="${_log_path}/python_infer_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_precision_${precision}_batchsize_${batch_size}.log" + set_infer_data=$(func_set_params "${image_dir_key}" "${_img_dir}") + set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}") + set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}") + set_mkldnn=$(func_set_params "${use_mkldnn_key}" "${use_mkldnn}") + set_cpu_threads=$(func_set_params "${cpu_threads_key}" "${threads}") + set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}") + set_infer_params0=$(func_set_params "${save_log_key}" "${save_log_value}") + set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}") + command="${_python} ${_script} ${use_gpu_key}=${use_gpu} ${set_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_infer_params0} ${set_infer_data} ${set_benchmark} ${set_precision} ${set_infer_params1} > ${_save_log_path} 2>&1 " + eval $command + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${command}" "${status_log}" "${model_name}" + done + done + done + done + elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then + for use_trt in ${use_trt_list[*]}; do + for precision in ${precision_list[*]}; do + if [ ${_flag_quant} = "True" ] && [ ${precision} != "int8" ]; then + continue + fi # skip when quant model inference but precision is not int8 + for batch_size in ${batch_size_list[*]}; do + _save_log_path="${_log_path}/python_infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_${batch_size}.log" + set_infer_data=$(func_set_params "${image_dir_key}" "${_img_dir}") + set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}") + set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}") + set_tensorrt=$(func_set_params "${use_trt_key}" "${use_trt}") + set_precision=$(func_set_params "${precision_key}" "${precision}") + set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}") + set_infer_params0=$(func_set_params "${save_log_key}" "${save_log_value}") + set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}") + command="${_python} ${_script} ${use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} ${set_infer_params0} > ${_save_log_path} 2>&1 " + eval $command + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${command}" "${status_log}" "${model_name}" + + done + done + done + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done +} + +if [ ${MODE} = "whole_infer" ]; then + GPUID=$3 + if [ ${#GPUID} -le 0 ];then + env=" " + else + env="export CUDA_VISIBLE_DEVICES=${GPUID}" + fi + # set CUDA_VISIBLE_DEVICES + eval $env + export Count=0 + IFS="|" + infer_run_exports=(${infer_export_list}) + infer_quant_flag=(${infer_is_quant}) + for infer_model in ${infer_model_dir_list[*]}; do + # run export + if [ ${infer_run_exports[Count]} != "null" ];then + save_infer_dir="${infer_model}_klquant" + set_export_weight=$(func_set_params "${export_weight}" "${infer_model}") + set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_dir}") + export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key}" + echo ${infer_run_exports[Count]} + echo $export_cmd + eval $export_cmd + status_export=$? + status_check $status_export "${export_cmd}" "${status_log}" "${model_name}" + else + save_infer_dir=${infer_model} + fi + #run inference + is_quant="True" + func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${LOG_PATH}" "${infer_img_dir}" ${is_quant} + Count=$(($Count + 1)) + done +fi + From 8b0b5d1ee56bdef51bb0e1d9897d9051df291d4f Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:36:36 +0800 Subject: [PATCH 106/129] pre-commit --- applications/轻量级车牌识别.md | 2902 ++++++++++++++++++++++++++++++++ 1 file changed, 2902 insertions(+) create mode 100644 applications/轻量级车牌识别.md diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md new file mode 100644 index 0000000000..e0f4706f14 --- /dev/null +++ b/applications/轻量级车牌识别.md @@ -0,0 +1,2902 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + +
+ + + + + + + + +Permalink + +
+ +
+
+ + + dygraph + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + Go to file + + +
+ + + + + +
+
+
+ + + + + + + + + +
+ +
+
+ + @MissPenguin + +
+ + + + + + +
+
+ + Latest commit + 10a3f25 + Jun 15, 2022 + + + + + + History + + +
+
+ +
+ +
+
+ + + 2 + + contributors + + +
+ +

+ Users who have contributed to this file +

+
+ + + + + + +
+
+ + + @WenmuZhou + + @MissPenguin + + + +
+
+ + + + + + + + + +
+ + + + +
+

一种基于PaddleOCR的轻量级车牌识别模型

+ +

1. 项目介绍

+

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

+

本项目难点如下:

+
    +
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. +
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. +
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. +
+

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

+

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

+

2. 环境搭建

+

本任务基于Aistudio完成, 具体环境如下:

+
    +
  • 操作系统: Linux
  • +
  • PaddlePaddle: 2.3
  • +
  • paddleslim: 2.2.2
  • +
  • PaddleOCR: Release/2.5
  • +
+

下载 PaddleOCR代码

+
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
+

安装依赖库

+
pip install -r PaddleOCR/requirements.txt
+

3. 数据集准备

+

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

+

该数据集分布如下:

+ + + + + + + + + + + + + + + + + + + + + +
数据集类型数量
训练集5769
验证集1001
测试集5006
+

数据集图片示例如下: +

+

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

+

下载好数据集后对数据集进行解压

+
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
+

3.1 数据集标注规则

+

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

+

具体规则如下:

+

例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg

+

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

+
    +
  • +

    025:车牌面积与整个图片区域的面积比。025 (25%)

    +
  • +
  • +

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    +
  • +
  • +

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    +
  • +
  • +

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    +
  • +
  • +

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    +
  • +
  • +

    37:牌照区域的亮度。 37 (37%)

    +
  • +
  • +

    15:车牌区域的模糊度。15 (15%)

    +
  • +
+
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
+alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', 'O']
+ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
+

3.2 制作符合PP-OCR训练格式的标注文件

+

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

+
import cv2
+import os
+import json
+from tqdm import tqdm
+import numpy as np
+
+provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
+alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O']
+ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
+
+def make_label(img_dir, save_gt_folder, phase):
+    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
+    os.makedirs(crop_img_save_dir, exist_ok=True)
+
+    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
+    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
+
+    i = 0
+    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
+        str_list = filename.split('-')
+        if len(str_list) < 5:
+            continue
+        coord_list = str_list[3].split('_')
+        txt_list = str_list[4].split('_')
+        boxes = []
+        for coord in coord_list:
+            boxes.append([int(x) for x in coord.split("&")])
+        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
+        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
+
+        # det
+        det_info = [{'points':boxes, 'transcription':lp_number}]
+        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
+
+        # rec
+        boxes = np.float32(boxes)
+        img = cv2.imread(os.path.join(img_dir, phase, filename))
+        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
+        crop_img = get_rotate_crop_image(img, boxes)
+        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
+        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
+        cv2.imwrite(crop_img_save_path, crop_img)
+        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
+        i+=1
+    f_det.close()
+    f_rec.close()
+
+def get_rotate_crop_image(img, points):
+    '''
+    img_height, img_width = img.shape[0:2]
+    left = int(np.min(points[:, 0]))
+    right = int(np.max(points[:, 0]))
+    top = int(np.min(points[:, 1]))
+    bottom = int(np.max(points[:, 1]))
+    img_crop = img[top:bottom, left:right, :].copy()
+    points[:, 0] = points[:, 0] - left
+    points[:, 1] = points[:, 1] - top
+    '''
+    assert len(points) == 4, "shape of points must be 4*2"
+    img_crop_width = int(
+        max(
+            np.linalg.norm(points[0] - points[1]),
+            np.linalg.norm(points[2] - points[3])))
+    img_crop_height = int(
+        max(
+            np.linalg.norm(points[0] - points[3]),
+            np.linalg.norm(points[1] - points[2])))
+    pts_std = np.float32([[0, 0], [img_crop_width, 0],
+                          [img_crop_width, img_crop_height],
+                          [0, img_crop_height]])
+    M = cv2.getPerspectiveTransform(points, pts_std)
+    dst_img = cv2.warpPerspective(
+        img,
+        M, (img_crop_width, img_crop_height),
+        borderMode=cv2.BORDER_REPLICATE,
+        flags=cv2.INTER_CUBIC)
+    dst_img_height, dst_img_width = dst_img.shape[0:2]
+    if dst_img_height * 1.0 / dst_img_width >= 1.5:
+        dst_img = np.rot90(dst_img)
+    return dst_img
+
+img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
+save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
+# phase = 'train' # change to val and test to make val dataset and test dataset
+for phase in ['train','val','test']:
+    make_label(img_dir, save_gt_folder, phase)
+

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
+

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

+

4. 实验

+

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

+

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

+

因此,本实验中对于车牌检测和识别有如下3种方案:

+
    +
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. +
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. +
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. +
+

4.1 检测

+

4.1.1 预训练模型直接预测

+

从下表中下载PP-OCRv3文本检测预训练模型

+ + + + + + + + + + + + + + + + + + + +
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
+

使用如下命令下载预训练模型

+
mkdir models
+cd models
+wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
+tar -xf ch_PP-OCRv3_det_distill_train.tar
+cd /home/aistudio/PaddleOCR
+

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. +
    +
  2. +
  3. 数据集相关 +
      +
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. +
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. +
    +
  4. +
+

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

+
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

+

使用预训练模型进行评估,指标如下所示:

+ + + + + + + + + + + + + +
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
+

4.1.2 CCPD车牌数据集fine-tune

+

训练

+

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. +
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. +
    +
  2. +
  3. 优化器相关: +
      +
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. +
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. +
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. +
    +
  4. +
  5. 数据集相关: +
      +
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. +
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. +
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. +
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. +
    +
  6. +
+

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

+
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Global.save_model_dir=output/CCPD/det \
+    Global.eval_batch_step="[0, 772]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

在上述命令中,通过-o的方式修改了配置文件中的参数。

+

训练好的模型地址为: det_ppocr_v3_finetune.tar

+

评估

+

训练完成后使用如下命令进行评估

+
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

+ + + + + + + + + + + + + + + + + +
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
+

可以看到进行fine-tune能显著提升车牌检测的效果。

+

4.1.3 CCPD车牌数据集fine-tune+量化训练

+

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

+

量化训练可通过如下命令启动:

+
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_model_dir=output/CCPD/det_quant \
+    Global.eval_batch_step="[0, 772]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

训练好的模型地址为: det_ppocr_v3_quant.tar

+

量化后指标对比如下

+ + + + + + + + + + + + + + + + + + + + + + + +
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
+

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

+

速度测试基于PaddleOCR lite教程完成。

+

4.1.4 模型导出

+

使用如下命令可以将训练好的模型进行导出

+
    +
  • 非量化模型
  • +
+
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_inference_dir=output/det/infer
+
    +
  • 量化模型
  • +
+
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/det/infer
+

4.2 识别

+

4.2.1 预训练模型直接预测

+

从下表中下载PP-OCRv3文本识别预训练模型

+ + + + + + + + + + + + + + + + + + + +
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
+

使用如下命令下载预训练模型

+
mkdir models
+cd models
+wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
+tar -xf ch_PP-OCRv3_rec_train.tar
+cd /home/aistudio/PaddleOCR
+

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

+
import paddle
+# 加载预训练模型
+all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
+# 查看权重参数的keys
+print(all_params.keys())
+# 学生模型的权重提取
+s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
+# 查看学生模型权重参数的keys
+print(s_params.keys())
+# 保存
+paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
+

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. +
    +
  2. +
  3. 数据集相关 +
      +
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. +
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. +
    +
  4. +
+

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

+
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

评估部分日志如下:

+
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
+eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
+[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
+[2022/05/12 19:52:17] ppocr INFO: acc:0.0
+[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
+[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
+[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
+[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
+
+

使用预训练模型进行评估,指标如下所示:

+ + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
+

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

+
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
+

输出部分日志如下:

+
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
+W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
+W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
+[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
+[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
+[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
+[2022/05/01 08:52:00] ppocr INFO: success!
+

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

+
    +
  1. 直接通过后处理去掉多识别的·。
  2. +
  3. 进行 fine-tune。
  4. +
+

4.2.2 预训练模型直接预测+改动后处理

+

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

+
text = text.replace('·','')
+

改动前后指标对比:

+ + + + + + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
+

可以看到,去掉多余的·能大幅提高精度。

+

4.2.3 CCPD车牌数据集fine-tune

+

训练

+

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. +
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. +
    +
  2. +
  3. 优化器相关 +
      +
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. +
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. +
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. +
    +
  4. +
  5. 数据集相关 +
      +
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. +
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. +
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. +
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. +
    +
  6. +
+

使用如下命令启动 fine-tune

+
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.save_model_dir=output/CCPD/rec/ \
+    Global.eval_batch_step="[0, 90]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

训练好的模型地址为: rec_ppocr_v3_finetune.tar

+

评估

+

训练完成后使用如下命令进行评估

+
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

+ + + + + + + + + + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
+

可以看到进行fine-tune能显著提升车牌识别的效果。

+

4.2.4 CCPD车牌数据集fine-tune+量化训练

+

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

+

量化训练可通过如下命令启动:

+
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_model_dir=output/CCPD/rec_quant/ \
+    Global.eval_batch_step="[0, 90]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

训练好的模型地址为: rec_ppocr_v3_quant.tar

+

量化后指标对比如下

+ + + + + + + + + + + + + + + + + + + + + + + +
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
+

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

+

速度测试基于PaddleOCR lite教程完成。

+

4.2.5 模型导出

+

使用如下命令可以将训练好的模型进行导出。

+
    +
  • 非量化模型
  • +
+
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec/infer
+
    +
  • 量化模型
  • +
+
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec_quant/infer
+

4.3 计算End2End指标

+

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

+
    +
  1. 导出模型
  2. +
+

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

+
# 检测模型
+
+# 预训练模型
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
+
+# 非量化模型
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/det/infer
+
+# 量化模型
+python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/det_quant/infer \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
+    Eval.loader.num_workers=0
+
+# 识别模型
+
+# 预训练模型
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
+
+# 非量化模型
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec/infer
+
+# 量化模型
+python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec_quant/infer \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+
    +
  1. 用导出的模型对测试集进行预测
  2. +
+

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

+
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
+python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
+
+# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
+
    +
  1. 转换label并计算指标
  2. +
+

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

+
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
+
+# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
+
+# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
+# 需手动修改后处理函数
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
+

日志如下:

+
The convert label saved in end2end/gt
+The convert label saved in end2end/pretrain
+start testing...
+hit, dt_count, gt_count 2 5988 5006
+character_acc: 70.42%
+avg_edit_dist_field: 2.37
+avg_edit_dist_img: 2.37
+precision: 0.03%
+recall: 0.04%
+fmeasure: 0.04%
+The convert label saved in end2end/post
+start testing...
+hit, dt_count, gt_count 4224 5988 5006
+character_acc: 81.59%
+avg_edit_dist_field: 1.47
+avg_edit_dist_img: 1.47
+precision: 70.54%
+recall: 84.38%
+fmeasure: 76.84%
+The convert label saved in end2end/fine-tune
+start testing...
+hit, dt_count, gt_count 4286 4898 5006
+character_acc: 94.16%
+avg_edit_dist_field: 0.47
+avg_edit_dist_img: 0.47
+precision: 87.51%
+recall: 85.62%
+fmeasure: 86.55%
+The convert label saved in end2end/quant
+start testing...
+hit, dt_count, gt_count 4349 4951 5006
+character_acc: 94.13%
+avg_edit_dist_field: 0.47
+avg_edit_dist_img: 0.47
+precision: 87.84%
+recall: 86.88%
+fmeasure: 87.36%
+

各个方案端到端指标如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
+

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

+

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

+

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

+
if len(txt) != 8: # 车牌字符串长度为8
+    continue
+

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

+

+

修改前后个方案指标对比如下:

+

各个方案端到端指标如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
+

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

+

4.4 部署

+
    +
  • 基于 Paddle Inference 的python推理
  • +
+

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

+
python tools/infer/predict_system.py \
+    --det_model_dir=output/CCPD/det/infer/ \
+    --rec_model_dir=output/CCPD/rec/infer/ \
+    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
+    --rec_image_shape=3,48,320
+

推理结果如下

+

+
    +
  • 端侧部署
  • +
+

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

+

4.5 实验总结

+

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

+
    +
  • 检测
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
+
    +
  • 识别
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
+
    +
  • 端到端指标如下:
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
+

结论

+

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

+

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

+

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

+
+
+ +
+ +
+ + + +
+ + +
+ + +
+
+ + + + +
+ +
+ + +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + From aba127fe595773f7f2f3554c6bee5300e3c27a03 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:50:39 +0800 Subject: [PATCH 107/129] fix --- applications/轻量级车牌识别.md | 3113 ++++++-------------------------- 1 file changed, 521 insertions(+), 2592 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index e0f4706f14..7012c7f4bb 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -1,1571 +1,129 @@ +# 一种基于PaddleOCR的轻量级车牌识别模型 +- [1. 项目介绍](#1-项目介绍) +- [2. 环境搭建](#2-环境搭建) +- [3. 数据集准备](#3-数据集准备) + - [3.1 数据集标注规则](#31-数据集标注规则) + - [3.2 制作符合PP-OCR训练格式的标注文件](#32-制作符合pp-ocr训练格式的标注文件) +- [4. 实验](#4-实验) + - [4.1 检测](#41-检测) + - [4.1.1 预训练模型直接预测](#411-预训练模型直接预测) + - [4.1.2 CCPD车牌数据集fine-tune](#412-ccpd车牌数据集fine-tune) + - [4.1.3 CCPD车牌数据集fine-tune+量化训练](#413-ccpd车牌数据集fine-tune量化训练) + - [4.1.4 模型导出](#414-模型导出) + - [4.2 识别](#42-识别) + - [4.2.1 预训练模型直接预测](#421-预训练模型直接预测) + - [4.2.2 预训练模型直接预测+改动后处理](#422-预训练模型直接预测改动后处理) + - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) + - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) + - [4.2.5 模型导出](#425-模型导出) + - [4.3 计算End2End指标](#43-计算End2End指标) + - [4.4 部署](#44-部署) + - [4.5 实验总结](#45-实验总结) +## 1. 项目介绍 +车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。 +本项目难点如下: +1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 +2. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 +3. 边缘和端测场景应用对模型大小有限制,推理速度有要求 +针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 - - - - - - - - - - +aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) - +## 2. 环境搭建 - - - - +本任务基于Aistudio完成, 具体环境如下: - +- 操作系统: Linux +- PaddlePaddle: 2.3 +- paddleslim: 2.2.2 +- PaddleOCR: Release/2.5 +下载 PaddleOCR代码 - - - - - - - - - - - - - - - - - - - - - - - - - - - - +```bash +git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR +``` +安装依赖库 - PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub +```bash +pip install -r PaddleOCR/requirements.txt +``` +## 3. 数据集准备 +所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为 +该数据集分布如下: +|数据集类型|数量| +|---|---| +|训练集| 5769| +|验证集| 1001| +|测试集| 5006| - +数据集图片示例如下: +![](https://ai-studio-static-online.cdn.bcebos.com/3bce057a8e0c40a0acbd26b2e29e4e2590a31bc412764be7b9e49799c69cb91c) - +数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595 +下载好数据集后对数据集进行解压 - +```bash +unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip +``` +### 3.1 数据集标注规则 - +CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD - - - - +具体规则如下: - +例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg - +每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。 +- 025:车牌面积与整个图片区域的面积比。025 (25%) +- 95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度 +- 154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473) +- 386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402) +- 0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S +- 37:牌照区域的亮度。 37 (37%) +- 15:车牌区域的模糊度。15 (15%) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - - - -
- -
- - - - - - - -
- - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - -
- - - - - - -
- - -
- - - - - - - - -Permalink - -
- -
-
- - - dygraph - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - Go to file - - -
- - - - - -
-
-
- - - - - - - - - -
- -
-
- - @MissPenguin - -
- - - - - - -
-
- - Latest commit - 10a3f25 - Jun 15, 2022 - - - - - - History - - -
-
- -
- -
-
- - - 2 - - contributors - - -
- -

- Users who have contributed to this file -

-
- - - - - - -
-
- - - @WenmuZhou - - @MissPenguin - - - -
-
- - - - - - - - - -
- - - - -
-

一种基于PaddleOCR的轻量级车牌识别模型

- -

1. 项目介绍

-

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

-

本项目难点如下:

-
    -
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. -
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. -
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. -
-

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

-

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

-

2. 环境搭建

-

本任务基于Aistudio完成, 具体环境如下:

-
    -
  • 操作系统: Linux
  • -
  • PaddlePaddle: 2.3
  • -
  • paddleslim: 2.2.2
  • -
  • PaddleOCR: Release/2.5
  • -
-

下载 PaddleOCR代码

-
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
-

安装依赖库

-
pip install -r PaddleOCR/requirements.txt
-

3. 数据集准备

-

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

-

该数据集分布如下:

- - - - - - - - - - - - - - - - - - - - - -
数据集类型数量
训练集5769
验证集1001
测试集5006
-

数据集图片示例如下: -

-

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

-

下载好数据集后对数据集进行解压

-
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
-

3.1 数据集标注规则

-

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

-

具体规则如下:

-

例如: 025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg

-

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

-
    -
  • -

    025:车牌面积与整个图片区域的面积比。025 (25%)

    -
  • -
  • -

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    -
  • -
  • -

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    -
  • -
  • -

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    -
  • -
  • -

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    -
  • -
  • -

    37:牌照区域的亮度。 37 (37%)

    -
  • -
  • -

    15:车牌区域的模糊度。15 (15%)

    -
  • -
-
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', 'O']
-ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
-

3.2 制作符合PP-OCR训练格式的标注文件

-

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

-
= 1.5: dst_img = np.rot90(dst_img) return dst_img @@ -1644,695 +202,414 @@ img_dir = '/home/aistudio/data/CCPD2020/ccpd_green' save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR' # phase = 'train' # change to val and test to make val dataset and test dataset for phase in ['train','val','test']: - make_label(img_dir, save_gt_folder, phase)">
import cv2
-import os
-import json
-from tqdm import tqdm
-import numpy as np
+    make_label(img_dir, save_gt_folder, phase)
+```
 
-provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O']
-ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
+通过上述命令可以完成了`训练集`,`验证集`和`测试集`的制作,制作完成的数据集信息如下:
 
-def make_label(img_dir, save_gt_folder, phase):
-    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
-    os.makedirs(crop_img_save_dir, exist_ok=True)
+| 类型 | 数据集 | 图片地址 | 标签地址 | 图片数量 |
+| --- | --- | --- | --- | --- |
+| 检测 | 训练集 | /home/aistudio/data/CCPD2020/ccpd_green/train | /home/aistudio/data/CCPD2020/PPOCR/train/det.txt | 5769 |
+| 检测 | 验证集 | /home/aistudio/data/CCPD2020/ccpd_green/val | /home/aistudio/data/CCPD2020/PPOCR/val/det.txt | 1001 |
+| 检测 | 测试集 | /home/aistudio/data/CCPD2020/ccpd_green/test | /home/aistudio/data/CCPD2020/PPOCR/test/det.txt | 5006 |
+| 识别 | 训练集 | /home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/train/rec.txt | 5769 |
+| 识别 | 验证集 | /home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/val/rec.txt | 1001 |
+| 识别 | 测试集 | /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/test/rec.txt | 5006 |
 
-    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
-    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
+在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。
 
-    i = 0
-    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
-        str_list = filename.split('-')
-        if len(str_list) < 5:
-            continue
-        coord_list = str_list[3].split('_')
-        txt_list = str_list[4].split('_')
-        boxes = []
-        for coord in coord_list:
-            boxes.append([int(x) for x in coord.split("&")])
-        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
-        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
+## 4. 实验
 
-        # det
-        det_info = [{'points':boxes, 'transcription':lp_number}]
-        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
+由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。
 
-        # rec
-        boxes = np.float32(boxes)
-        img = cv2.imread(os.path.join(img_dir, phase, filename))
-        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
-        crop_img = get_rotate_crop_image(img, boxes)
-        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
-        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
-        cv2.imwrite(crop_img_save_path, crop_img)
-        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
-        i+=1
-    f_det.close()
-    f_rec.close()
+由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。
 
-def get_rotate_crop_image(img, points):
-    '''
-    img_height, img_width = img.shape[0:2]
-    left = int(np.min(points[:, 0]))
-    right = int(np.max(points[:, 0]))
-    top = int(np.min(points[:, 1]))
-    bottom = int(np.max(points[:, 1]))
-    img_crop = img[top:bottom, left:right, :].copy()
-    points[:, 0] = points[:, 0] - left
-    points[:, 1] = points[:, 1] - top
-    '''
-    assert len(points) == 4, "shape of points must be 4*2"
-    img_crop_width = int(
-        max(
-            np.linalg.norm(points[0] - points[1]),
-            np.linalg.norm(points[2] - points[3])))
-    img_crop_height = int(
-        max(
-            np.linalg.norm(points[0] - points[3]),
-            np.linalg.norm(points[1] - points[2])))
-    pts_std = np.float32([[0, 0], [img_crop_width, 0],
-                          [img_crop_width, img_crop_height],
-                          [0, img_crop_height]])
-    M = cv2.getPerspectiveTransform(points, pts_std)
-    dst_img = cv2.warpPerspective(
-        img,
-        M, (img_crop_width, img_crop_height),
-        borderMode=cv2.BORDER_REPLICATE,
-        flags=cv2.INTER_CUBIC)
-    dst_img_height, dst_img_width = dst_img.shape[0:2]
-    if dst_img_height * 1.0 / dst_img_width >= 1.5:
-        dst_img = np.rot90(dst_img)
-    return dst_img
+因此,本实验中对于车牌检测和识别有如下3种方案:
 
-img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
-save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
-# phase = 'train' # change to val and test to make val dataset and test dataset
-for phase in ['train','val','test']:
-    make_label(img_dir, save_gt_folder, phase)
-

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
-

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

-

4. 实验

-

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

-

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

-

因此,本实验中对于车牌检测和识别有如下3种方案:

-
    -
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. -
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. -
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. -
-

4.1 检测

-

4.1.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本检测预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
-tar -xf ch_PP-OCRv3_det_distill_train.tar
-cd /home/aistudio/PaddleOCR
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
-

4.1.2 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关: -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关: -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

-
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/det \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

在上述命令中,通过-o的方式修改了配置文件中的参数。

-

训练好的模型地址为: det_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
-

可以看到进行fine-tune能显著提升车牌检测的效果。

-

4.1.3 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+```
+
+训练好的模型地址为: [det_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_quant.tar)
+
+量化后指标对比如下
+
+|方案|hmeans| 模型大小 | 预测速度(lite) |
+|---|---|------|------------|
+|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms      |
+|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M   | 189ms      |
+
+可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。
+
+速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。
+
+#### 4.1.4 模型导出
+
+使用如下命令可以将训练好的模型进行导出
+
+* 非量化模型
+```bash
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
     Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/det_quant \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

训练好的模型地址为: det_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
-

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

-

速度测试基于PaddleOCR lite教程完成。

-

4.1.4 模型导出

-

使用如下命令可以将训练好的模型进行导出

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-

4.2 识别

-

4.2.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本识别预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
-tar -xf ch_PP-OCRv3_rec_train.tar
-cd /home/aistudio/PaddleOCR
-

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

-
import paddle
-# 加载预训练模型
-all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
-# 查看权重参数的keys
-print(all_params.keys())
-# 学生模型的权重提取
-s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
-# 查看学生模型权重参数的keys
-print(s_params.keys())
-# 保存
-paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

评估部分日志如下:

-
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
-eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
-[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
-[2022/05/12 19:52:17] ppocr INFO: acc:0.0
-[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
-[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
-[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
-[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
-
-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
-

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

-
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
-

输出部分日志如下:

-
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
-W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
-W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
-[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
-[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
-[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
-[2022/05/01 08:52:00] ppocr INFO: success!
-

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

-
    -
  1. 直接通过后处理去掉多识别的·。
  2. -
  3. 进行 fine-tune。
  4. -
-

4.2.2 预训练模型直接预测+改动后处理

-

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

-
text = text.replace('·','')
-

改动前后指标对比:

- - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
-

可以看到,去掉多余的·能大幅提高精度。

-

4.2.3 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关 -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关 -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下命令启动 fine-tune

-
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/rec/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
-

可以看到进行fine-tune能显著提升车牌识别的效果。

-

4.2.4 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+```
+训练好的模型地址为: [rec_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_quant.tar)
+
+量化后指标对比如下
+
+|方案| acc    | 模型大小  | 预测速度(lite) |
+|---|--------|-------|------------|
+|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms      |
+|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4%  | 4.8M  | 1.8ms      |
+
+可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。
+
+速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。
+
+#### 4.2.5 模型导出
+
+使用如下命令可以将训练好的模型进行导出。
+
+* 非量化模型
+```bash
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
     Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/rec_quant/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

-

速度测试基于PaddleOCR lite教程完成。

-

4.2.5 模型导出

-

使用如下命令可以将训练好的模型进行导出。

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer
-

4.3 计算End2End指标

-

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

-
    -
  1. 导出模型
  2. -
-

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

-
# 检测模型
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+```
 
-# 预训练模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
+2. 用导出的模型对测试集进行预测
 
-# 非量化模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det/infer
+此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:
 
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
-    Eval.loader.num_workers=0
-
-# 识别模型
-
-# 预训练模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-
    -
  1. 用导出的模型对测试集进行预测
  2. -
-

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

-
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
-python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
+```
 
-# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
+3. 转换label并计算指标
 
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
-
    -
  1. 转换label并计算指标
  2. -
-

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

-
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
+```
 
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
-# 需手动修改后处理函数
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
-

日志如下:

-
The convert label saved in end2end/gt
-The convert label saved in end2end/pretrain
-start testing...
-hit, dt_count, gt_count 2 5988 5006
-character_acc: 70.42%
-avg_edit_dist_field: 2.37
-avg_edit_dist_img: 2.37
-precision: 0.03%
-recall: 0.04%
-fmeasure: 0.04%
-The convert label saved in end2end/post
-start testing...
-hit, dt_count, gt_count 4224 5988 5006
-character_acc: 81.59%
-avg_edit_dist_field: 1.47
-avg_edit_dist_img: 1.47
-precision: 70.54%
-recall: 84.38%
-fmeasure: 76.84%
-The convert label saved in end2end/fine-tune
-start testing...
-hit, dt_count, gt_count 4286 4898 5006
-character_acc: 94.16%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.51%
-recall: 85.62%
-fmeasure: 86.55%
-The convert label saved in end2end/quant
-start testing...
-hit, dt_count, gt_count 4349 4951 5006
-character_acc: 94.13%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.84%
-recall: 86.88%
-fmeasure: 87.36%
-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

-

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

-

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

-
if len(txt) != 8: # 车牌字符串长度为8
-    continue
-

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

-

-

修改前后个方案指标对比如下:

-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

-

4.4 部署

-
    -
  • 基于 Paddle Inference 的python推理
  • -
-

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

-
python tools/infer/predict_system.py \
-    --det_model_dir=output/CCPD/det/infer/ \
-    --rec_model_dir=output/CCPD/rec/infer/ \
-    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
-    --rec_image_shape=3,48,320
-

推理结果如下

-

-
    -
  • 端侧部署
  • -
-

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

-

4.5 实验总结

-

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

-
    -
  • 检测
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
-
    -
  • 识别
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-
    -
  • 端到端指标如下:
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
-

结论

-

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

-

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

-

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

-
-
+ --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ + --rec_image_shape=3,48,320 +``` +推理结果如下 -
+![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) -
+- 端侧部署 + +端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../deploy/lite/readme_ch.md) +### 4.5 实验总结 -
- - -
- - -
-
+- 检测 - +- 识别 + +|方案| acc | 模型大小 | 预测速度(lite) | +|---|--------|-------|------------| +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4,2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms | -
+- 端到端指标如下: -
+|方案|fmeasure|模型大小|预测速度(lite) | +|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型|0.08%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的`·`|91.66%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune|92.5%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|92.02%|5.8M|224ms| -
+**结论** +PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 -
-
+PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 -
- - - - - - - - - - - - - - - - - - - - +从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。 From 4957a923fb8ccfbfdaf2255572953ed28062e960 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 17:55:49 +0800 Subject: [PATCH 108/129] fix training --- ppocr/data/imaug/label_ops.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 8b017b3219..44c871d9ef 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -70,14 +70,22 @@ class DetLabelEncode(object): return data def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="float32") - s = pts.sum(axis=1) - rect[0] = pts[np.argmin(s)] - rect[2] = pts[np.argmax(s)] - diff = np.diff(pts, axis=1) - rect[1] = pts[np.argmin(diff)] - rect[3] = pts[np.argmax(diff)] - return rect + """ + refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 + """ + # sort the points based on their x-coordinates + xSorted = pts[np.argsort(pts[:, 0]), :] + + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + + D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] + (br, tr) = rightMost[np.argsort(D)[::-1], :] + + return np.array([tl, tr, br, bl], dtype="float32") def expand_points_num(self, boxes): max_points_num = 0 @@ -443,7 +451,9 @@ class KieLabelEncode(object): elif 'key_cls' in ann.keys(): labels.append(ann['key_cls']) else: - raise ValueError("Cannot found 'key_cls' in ann.keys(), please check your training annotation.") + raise ValueError( + "Cannot found 'key_cls' in ann.keys(), please check your training annotation." + ) edges.append(ann.get('edge', 0)) ann_infos = dict( image=data['image'], From 114d3399b89e3ed762b79286de508420c5ec8a65 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 17:59:44 +0800 Subject: [PATCH 109/129] fix training --- ppocr/data/imaug/label_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 44c871d9ef..36017a823e 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -23,7 +23,7 @@ import string from shapely.geometry import LineString, Point, Polygon import json import copy - +from scipy.spatial import distance as dist from ppocr.utils.logging import get_logger From 3ef6f1bff98c5f0038db39db0fbde8e6da7e85af Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 21 Jun 2022 12:10:09 +0000 Subject: [PATCH 110/129] add table fleet --- ...leet_normal_infer_python_linux_gpu_cpu.txt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 test_tipc/configs/en_table_structure/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/en_table_structure/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt new file mode 100644 index 0000000000..41d236c376 --- /dev/null +++ b/test_tipc/configs/en_table_structure/train_linux_gpu_fleet_normal_infer_python_linux_gpu_cpu.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:en_table_structure +python:python3.7 +gpu_list:192.168.0.1,192.168.0.2;0,1 +Global.use_gpu:True +Global.auto_cast:fp32 +Global.epoch_num:lite_train_lite_infer=3|whole_train_whole_infer=50 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 +Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy +train_model_name:latest +train_infer_img_dir:./ppstructure/docs/table/table.jpg +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o +quant_export: +fpgm_export: +distill_export:null +export1:null +export2:null +## +infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer +infer_export:null +infer_quant:False +inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table +--use_gpu:False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1 +--use_tensorrt:False +--precision:fp32 +--table_model_dir: +--image_dir:./ppstructure/docs/table/table.jpg +null:null +--benchmark:False +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,488,488]}] From 32c65b0dfd9114e055173d0fd23db9609a226c5e Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Wed, 22 Jun 2022 12:26:12 +0800 Subject: [PATCH 111/129] opt points order --- tools/infer/predict_det.py | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index 73387aef59..b9fab7dd0d 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -24,7 +24,6 @@ import cv2 import numpy as np import time import sys -from scipy.spatial import distance as dist import tools.infer.utility as utility from ppocr.utils.logging import get_logger @@ -151,22 +150,15 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - """ - refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 - """ - # sort the points based on their x-coordinates - xSorted = pts[np.argsort(pts[:, 0]), :] - - leftMost = xSorted[:2, :] - rightMost = xSorted[2:, :] - - leftMost = leftMost[np.argsort(leftMost[:, 1]), :] - (tl, bl) = leftMost - - D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] - (br, tr) = rightMost[np.argsort(D)[::-1], :] - - return np.array([tl, tr, br, bl], dtype="float32") + rect = np.zeros((4, 2), dtype="int32") + s = pts.sum(axis=1) + rect[0] = pts[np.argmin(s)] + rect[2] = pts[np.argmax(s)] + tmp = np.delete(pts, (np.argmin(s), np.argmax(s)), axis=0) + diff = np.diff(np.array(tmp), axis=1) + rect[1] = tmp[np.argmin(diff)] + rect[3] = tmp[np.argmax(diff)] + return rect def clip_det_res(self, points, img_height, img_width): for pno in range(points.shape[0]): From 715fc2377e9ad2dab94873635a4346815673fb5e Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Wed, 22 Jun 2022 12:29:06 +0800 Subject: [PATCH 112/129] fix --- ppocr/data/imaug/label_ops.py | 26 +++++++++----------------- tools/infer/predict_det.py | 2 +- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 36017a823e..39c2cbbac8 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -23,7 +23,6 @@ import string from shapely.geometry import LineString, Point, Polygon import json import copy -from scipy.spatial import distance as dist from ppocr.utils.logging import get_logger @@ -70,22 +69,15 @@ class DetLabelEncode(object): return data def order_points_clockwise(self, pts): - """ - refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 - """ - # sort the points based on their x-coordinates - xSorted = pts[np.argsort(pts[:, 0]), :] - - leftMost = xSorted[:2, :] - rightMost = xSorted[2:, :] - - leftMost = leftMost[np.argsort(leftMost[:, 1]), :] - (tl, bl) = leftMost - - D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] - (br, tr) = rightMost[np.argsort(D)[::-1], :] - - return np.array([tl, tr, br, bl], dtype="float32") + rect = np.zeros((4, 2), dtype="float32") + s = pts.sum(axis=1) + rect[0] = pts[np.argmin(s)] + rect[2] = pts[np.argmax(s)] + tmp = np.delete(pts, (np.argmin(s), np.argmax(s)), axis=0) + diff = np.diff(np.array(tmp), axis=1) + rect[1] = tmp[np.argmin(diff)] + rect[3] = tmp[np.argmax(diff)] + return rect def expand_points_num(self, boxes): max_points_num = 0 diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index b9fab7dd0d..7b6bebf1fb 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -150,7 +150,7 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="int32") + rect = np.zeros((4, 2), dtype="float32") s = pts.sum(axis=1) rect[0] = pts[np.argmin(s)] rect[2] = pts[np.argmax(s)] From f140143f318b8903cc28e98ddd91388f18921885 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Wed, 22 Jun 2022 07:03:44 +0000 Subject: [PATCH 113/129] update log --- .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- .../train_pact_infer_python.txt | 0 .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- .../train_pact_infer_python.txt | 0 ..._normal_amp_infer_python_linux_gpu_cpu.txt | 53 ---------------- test_tipc/test_paddle2onnx.sh | 12 ++-- test_tipc/test_ptq_inference_python.sh | 3 +- test_tipc/test_serving_infer_cpp.sh | 17 +++-- test_tipc/test_serving_infer_python.sh | 30 +++++---- test_tipc/test_train_inference_python.sh | 62 +++---------------- 18 files changed, 49 insertions(+), 393 deletions(-) rename test_tipc/configs/{ch_PP-OCRv2_det_PACT => ch_PP-OCRv2_det}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt rename test_tipc/configs/{ch_PP-OCRv2_rec_PACT => ch_PP-OCRv2_rec}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt rename test_tipc/configs/{ch_PP-OCRv3_det_PACT => ch_PP-OCRv3_det}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt rename test_tipc/configs/{ch_PP-OCRv3_rec_PACT => ch_PP-OCRv3_rec}/train_pact_infer_python.txt (100%) rename test_tipc/configs/{ch_ppocr_mobile_v2.0_det_PACT => ch_ppocr_mobile_v2.0_det}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt rename test_tipc/configs/{ch_ppocr_mobile_v2.0_rec_PACT => ch_ppocr_mobile_v2.0_rec}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt rename test_tipc/configs/{en_table_structure_PACT => en_table_structure}/train_pact_infer_python.txt (100%) delete mode 100644 test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_det/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_det_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv2_det/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index 3afc0acb79..0000000000 --- a/test_tipc/configs/ch_PP-OCRv2_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:ch_PP-OCRv2_det_PACT -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 -Global.pretrained_model:null -train_model_name:latest -train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml -o -fpgm_export: -distill_export:null -export1:null -export2:null -inference_dir:Student -infer_model:./inference/ch_PP-OCRv2_det_infer/ -infer_export:null -infer_quant:False -inference:tools/infer/predict_det.py ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1 ---use_tensorrt:False ---precision:fp32 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ -null:null ---benchmark:True -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_PP-OCRv2_rec/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv2_rec/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index e0f86d9020..0000000000 --- a/test_tipc/configs/ch_PP-OCRv2_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:ch_PP-OCRv2_rec_PACT -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 -Global.pretrained_model:pretrain_models/ch_PP-OCRv2_rec_train/best_accuracy -train_model_name:latest -train_infer_img_dir:./inference/rec_inference -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml -o -fpgm_export: null -distill_export:null -export1:null -export2:null -inference_dir:Student -infer_model:./inference/ch_PP-OCRv2_rec_slim_quant_infer -infer_export:null -infer_quant:True -inference:tools/infer/predict_rec.py ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1|6 ---use_tensorrt:False ---precision:fp32 ---rec_model_dir: ---image_dir:./inference/rec_inference -null:null ---benchmark:True -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,32,320]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_det/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_det_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv3_det/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index 252378e4dc..0000000000 --- a/test_tipc/configs/ch_PP-OCRv3_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:ch_PP-OCRv3_det_PACT -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 -Global.pretrained_model:null -train_model_name:latest -train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o -fpgm_export: -distill_export:null -export1:null -export2:null -inference_dir:Student -infer_model:./inference/ch_PP-OCRv3_det_infer/ -infer_export:null -infer_quant:False -inference:tools/infer/predict_det.py ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1 ---use_tensorrt:False ---precision:fp32 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ -null:null ---benchmark:True -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_PP-OCRv3_rec/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_PP-OCRv3_rec_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_PP-OCRv3_rec/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_det/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index 3a5d8faf3f..0000000000 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_det_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:ch_ppocr_mobile_v2.0_det_PACT -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=2|whole_train_whole_infer=4 -Global.pretrained_model:null -train_model_name:latest -train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o -fpgm_export:null -distill_export:null -export1:null -export2:null -inference_dir:null -train_model:./inference/ch_ppocr_mobile_v2.0_det_prune_infer/ -infer_export:null -infer_quant:False -inference:tools/infer/predict_det.py ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1 ---use_tensorrt:False ---precision:fp32 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ -null:null ---benchmark:True -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,640,640]}];[{float32,[3,960,960]}] diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_pact_infer_python.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_pact_infer_python.txt rename to test_tipc/configs/ch_ppocr_mobile_v2.0_rec/train_pact_infer_python.txt diff --git a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index a1a2a8e63d..0000000000 --- a/test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:ch_ppocr_mobile_v2.0_rec_PACT -python:python3.7 -gpu_list:0 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=128|whole_train_whole_infer=128 -Global.checkpoints:null -train_model_name:latest -train_infer_img_dir:./train_data/ic15_data/test/word_1.png -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/rec_chinese_lite_train_v2.0.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/ch_ppocr_mobile_v2.0_rec_PACT/rec_chinese_lite_train_v2.0.yml -o -fpgm_export:null -distill_export:null -export1:null -export2:null -inference_dir:null -infer_model:./inference/ch_ppocr_mobile_v2.0_rec_slim_infer/ -infer_export:null -infer_quant:False -inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ppocr_keys_v1.txt --rec_image_shape="3,32,100" ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1|6 ---use_tensorrt:False ---precision:fp32 ---rec_model_dir: ---image_dir:./inference/rec_inference ---save_log_path:./test/output/ ---benchmark:True -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,32,320]}] diff --git a/test_tipc/configs/en_table_structure_PACT/train_pact_infer_python.txt b/test_tipc/configs/en_table_structure/train_pact_infer_python.txt similarity index 100% rename from test_tipc/configs/en_table_structure_PACT/train_pact_infer_python.txt rename to test_tipc/configs/en_table_structure/train_pact_infer_python.txt diff --git a/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt b/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt deleted file mode 100644 index d7c847fcdc..0000000000 --- a/test_tipc/configs/en_table_structure_PACT/train_linux_gpu_normal_amp_infer_python_linux_gpu_cpu.txt +++ /dev/null @@ -1,53 +0,0 @@ -===========================train_params=========================== -model_name:en_table_structure_PACT -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:amp -Global.epoch_num:lite_train_lite_infer=1|whole_train_whole_infer=50 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=128 -Global.pretrained_model:./pretrain_models/en_ppocr_mobile_v2.0_table_structure_train/best_accuracy -train_model_name:latest -train_infer_img_dir:./ppstructure/docs/table/table.jpg -null:null -## -trainer:pact_train -norm_train:null -pact_train:deploy/slim/quantization/quant.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o -fpgm_train:null -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:null -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.checkpoints: -norm_export:null -quant_export:deploy/slim/quantization/export_model.py -c test_tipc/configs/en_table_structure/table_mv3.yml -o -fpgm_export: -distill_export:null -export1:null -export2:null -## -infer_model:./inference/en_ppocr_mobile_v2.0_table_structure_infer -infer_export:null -infer_quant:True -inference:ppstructure/table/predict_table.py --det_model_dir=./inference/en_ppocr_mobile_v2.0_table_det_infer --rec_model_dir=./inference/en_ppocr_mobile_v2.0_table_rec_infer --rec_char_dict_path=./ppocr/utils/dict/table_dict.txt --table_char_dict_path=./ppocr/utils/dict/table_structure_dict.txt --image_dir=./ppstructure/docs/table/table.jpg --det_limit_side_len=736 --det_limit_type=min --output ./output/table ---use_gpu:True|False ---enable_mkldnn:False ---cpu_threads:6 ---rec_batch_num:1 ---use_tensorrt:False ---precision:fp32 ---table_model_dir: ---image_dir:./ppstructure/docs/table/table.jpg -null:null ---benchmark:False -null:null -===========================infer_benchmark_params========================== -random_infer_input:[{float32,[3,488,488]}] diff --git a/test_tipc/test_paddle2onnx.sh b/test_tipc/test_paddle2onnx.sh index 4ad2035f48..356bc98041 100644 --- a/test_tipc/test_paddle2onnx.sh +++ b/test_tipc/test_paddle2onnx.sh @@ -62,7 +62,8 @@ function func_paddle2onnx(){ set_save_model=$(func_set_params "--save_file" "${det_save_file_value}") set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") - trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + trans_det_log="${LOG_PATH}/trans_model_det.log" + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker} > ${trans_det_log} 2>&1 " eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" @@ -73,7 +74,8 @@ function func_paddle2onnx(){ set_save_model=$(func_set_params "--save_file" "${rec_save_file_value}") set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") - trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + trans_rec_log="${LOG_PATH}/trans_model_rec.log" + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker} > ${trans_rec_log} 2>&1 " eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" @@ -85,7 +87,8 @@ function func_paddle2onnx(){ set_save_model=$(func_set_params "--save_file" "${det_save_file_value}") set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") - trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + trans_det_log="${LOG_PATH}/trans_model_det.log" + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker} > ${trans_det_log} 2>&1 " eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" @@ -97,7 +100,8 @@ function func_paddle2onnx(){ set_save_model=$(func_set_params "--save_file" "${rec_save_file_value}") set_opset_version=$(func_set_params "${opset_version_key}" "${opset_version_value}") set_enable_onnx_checker=$(func_set_params "${enable_onnx_checker_key}" "${enable_onnx_checker_value}") - trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker}" + trans_rec_log="${LOG_PATH}/trans_model_rec.log" + trans_model_cmd="${padlle2onnx_cmd} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_save_model} ${set_opset_version} ${set_enable_onnx_checker} > ${trans_rec_log} 2>&1 " eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" diff --git a/test_tipc/test_ptq_inference_python.sh b/test_tipc/test_ptq_inference_python.sh index 2454c0b50a..c1aa3daa6c 100644 --- a/test_tipc/test_ptq_inference_python.sh +++ b/test_tipc/test_ptq_inference_python.sh @@ -139,7 +139,8 @@ if [ ${MODE} = "whole_infer" ]; then save_infer_dir="${infer_model}_klquant" set_export_weight=$(func_set_params "${export_weight}" "${infer_model}") set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_dir}") - export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key}" + export_log_path="${LOG_PATH}/_export_${Count}.log" + export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key} > ${export_log_path} 2>&1 " echo ${infer_run_exports[Count]} echo $export_cmd eval $export_cmd diff --git a/test_tipc/test_serving_infer_cpp.sh b/test_tipc/test_serving_infer_cpp.sh index f9f7ac1aa5..4088c66f57 100644 --- a/test_tipc/test_serving_infer_cpp.sh +++ b/test_tipc/test_serving_infer_cpp.sh @@ -70,7 +70,8 @@ function func_serving(){ set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_det_log="${LOG_PATH}/cpp_trans_model_det.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_det_log} 2>&1 " eval $trans_model_cmd cp "deploy/pdserving/serving_client_conf.prototxt" ${det_serving_client_value} # trans rec @@ -78,7 +79,8 @@ function func_serving(){ set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_rec_log="${LOG_PATH}/cpp_trans_model_rec.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_rec_log} 2>&1 " eval $trans_model_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${trans_model_cmd}" "${status_log}" "${model_name}" @@ -88,22 +90,25 @@ function func_serving(){ # cpp serving for gpu_id in ${gpu_value[*]}; do if [ ${gpu_id} = "null" ]; then - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > serving_log_cpu.log &" + server_log_path="${LOG_PATH}/cpp_server_cpu.log" + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} > ${server_log_path} 2>&1 " eval $web_service_cpp_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cpp_cmd}" "${status_log}" "${model_name}" sleep 5s - _save_log_path="${LOG_PATH}/server_infer_cpp_cpu.log" + _save_log_path="${LOG_PATH}/cpp_client_cpu.log" cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" eval $cpp_client_cmd last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" status_check $last_status "${cpp_client_cmd}" "${status_log}" "${model_name}" ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9 else - web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > serving_log_gpu.log &" + server_log_path="${LOG_PATH}/cpp_server_gpu.log" + web_service_cpp_cmd="${python_list[0]} ${web_service_py} --model ${det_server_value} ${rec_server_value} ${op_key} ${op_value} ${port_key} ${port_value} ${gpu_key} ${gpu_id} > ${server_log_path} 2>&1 " eval $web_service_cpp_cmd sleep 5s - _save_log_path="${LOG_PATH}/server_infer_cpp_gpu.log" + _save_log_path="${LOG_PATH}/cpp_client_gpu.log" cpp_client_cmd="${python_list[0]} ${cpp_client_py} ${det_client_value} ${rec_client_value} > ${_save_log_path} 2>&1" eval $cpp_client_cmd last_status=${PIPESTATUS[0]} diff --git a/test_tipc/test_serving_infer_python.sh b/test_tipc/test_serving_infer_python.sh index c76d6f5d19..57dab6aeb5 100644 --- a/test_tipc/test_serving_infer_python.sh +++ b/test_tipc/test_serving_infer_python.sh @@ -77,14 +77,16 @@ function func_serving(){ set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_det_log="${LOG_PATH}/python_trans_model_det.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_det_log} 2>&1 " eval $trans_model_cmd # trans rec set_dirname=$(func_set_params "--dirname" "${rec_infer_model_dir_value}") set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_rec_log="${LOG_PATH}/python_trans_model_rec.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_rec_log} 2>&1 " eval $trans_model_cmd elif [[ ${model_name} =~ "det" ]]; then # trans det @@ -92,7 +94,8 @@ function func_serving(){ set_serving_server=$(func_set_params "--serving_server" "${det_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${det_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_det_log="${LOG_PATH}/python_trans_model_det.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_det_log} 2>&1 " eval $trans_model_cmd elif [[ ${model_name} =~ "rec" ]]; then # trans rec @@ -100,7 +103,8 @@ function func_serving(){ set_serving_server=$(func_set_params "--serving_server" "${rec_serving_server_value}") set_serving_client=$(func_set_params "--serving_client" "${rec_serving_client_value}") python_list=(${python_list}) - trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + trans_rec_log="${LOG_PATH}/python_trans_model_rec.log" + trans_model_cmd="${python_list[0]} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client} > ${trans_rec_log} 2>&1 " eval $trans_model_cmd fi set_image_dir=$(func_set_params "${image_dir_key}" "${image_dir_value}") @@ -115,29 +119,30 @@ function func_serving(){ for use_mkldnn in ${web_use_mkldnn_list[*]}; do for threads in ${web_cpu_threads_list[*]}; do set_cpu_threads=$(func_set_params "${web_cpu_threads_key}" "${threads}") + server_log_path="${LOG_PATH}/python_server_cpu_usemkldnn_${use_mkldnn}_threads_${threads}.log" if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} ${set_rec_model_config} &" + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} ${set_rec_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" elif [[ ${model_name} =~ "det" ]]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} &" + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_det_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_rec_model_config} &" + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}="" ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_rec_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" fi sleep 2s for pipeline in ${pipeline_py[*]}; do - _save_log_path="${LOG_PATH}/server_infer_cpu_${pipeline%_client*}_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" + _save_log_path="${LOG_PATH}/python_client_cpu_${pipeline%_client*}_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" pipeline_cmd="${python} ${pipeline} ${set_image_dir} > ${_save_log_path} 2>&1 " eval $pipeline_cmd last_status=${PIPESTATUS[0]} @@ -151,6 +156,7 @@ function func_serving(){ elif [ ${use_gpu} = "gpu" ]; then for use_trt in ${web_use_trt_list[*]}; do for precision in ${web_precision_list[*]}; do + server_log_path="${LOG_PATH}/python_server_gpu_usetrt_${use_trt}_precision_${precision}.log" if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then continue fi @@ -168,26 +174,26 @@ function func_serving(){ if [ ${model_name} = "ch_PP-OCRv2" ] || [ ${model_name} = "ch_PP-OCRv3" ] || [ ${model_name} = "ch_ppocr_mobile_v2.0" ] || [ ${model_name} = "ch_ppocr_server_v2.0" ]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") - web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} ${set_rec_model_config} &" + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} ${set_rec_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" elif [[ ${model_name} =~ "det" ]]; then set_det_model_config=$(func_set_params "${det_server_key}" "${det_server_value}") - web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} &" + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_det_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" elif [[ ${model_name} =~ "rec" ]]; then set_rec_model_config=$(func_set_params "${rec_server_key}" "${rec_server_value}") - web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_rec_model_config} &" + web_service_cmd="${python} ${web_service_py} ${set_tensorrt} ${set_precision} ${set_rec_model_config} > ${server_log_path} 2>&1 " eval $web_service_cmd last_status=${PIPESTATUS[0]} status_check $last_status "${web_service_cmd}" "${status_log}" "${model_name}" fi sleep 2s for pipeline in ${pipeline_py[*]}; do - _save_log_path="${LOG_PATH}/server_infer_gpu_${pipeline%_client*}_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" + _save_log_path="${LOG_PATH}/python_client_gpu_${pipeline%_client*}_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" pipeline_cmd="${python} ${pipeline} ${set_image_dir}> ${_save_log_path} 2>&1" eval $pipeline_cmd last_status=${PIPESTATUS[0]} diff --git a/test_tipc/test_train_inference_python.sh b/test_tipc/test_train_inference_python.sh index 62a56a32ce..fa68cb2632 100644 --- a/test_tipc/test_train_inference_python.sh +++ b/test_tipc/test_train_inference_python.sh @@ -2,7 +2,7 @@ source test_tipc/common_func.sh FILENAME=$1 -# MODE be one of ['lite_train_lite_infer' 'lite_train_whole_infer' 'whole_train_whole_infer', 'whole_infer', 'klquant_whole_infer'] +# MODE be one of ['lite_train_lite_infer' 'lite_train_whole_infer' 'whole_train_whole_infer', 'whole_infer'] MODE=$2 dataline=$(awk 'NR==1, NR==51{print}' $FILENAME) @@ -88,43 +88,6 @@ benchmark_value=$(func_parser_value "${lines[49]}") infer_key1=$(func_parser_key "${lines[50]}") infer_value1=$(func_parser_value "${lines[50]}") -# parser klquant_infer -if [ ${MODE} = "klquant_whole_infer" ]; then - dataline=$(awk 'NR==1, NR==17{print}' $FILENAME) - lines=(${dataline}) - model_name=$(func_parser_value "${lines[1]}") - python=$(func_parser_value "${lines[2]}") - export_weight=$(func_parser_key "${lines[3]}") - save_infer_key=$(func_parser_key "${lines[4]}") - # parser inference model - infer_model_dir_list=$(func_parser_value "${lines[5]}") - infer_export_list=$(func_parser_value "${lines[6]}") - infer_is_quant=$(func_parser_value "${lines[7]}") - # parser inference - inference_py=$(func_parser_value "${lines[8]}") - use_gpu_key=$(func_parser_key "${lines[9]}") - use_gpu_list=$(func_parser_value "${lines[9]}") - use_mkldnn_key=$(func_parser_key "${lines[10]}") - use_mkldnn_list=$(func_parser_value "${lines[10]}") - cpu_threads_key=$(func_parser_key "${lines[11]}") - cpu_threads_list=$(func_parser_value "${lines[11]}") - batch_size_key=$(func_parser_key "${lines[12]}") - batch_size_list=$(func_parser_value "${lines[12]}") - use_trt_key=$(func_parser_key "${lines[13]}") - use_trt_list=$(func_parser_value "${lines[13]}") - precision_key=$(func_parser_key "${lines[14]}") - precision_list=$(func_parser_value "${lines[14]}") - infer_model_key=$(func_parser_key "${lines[15]}") - image_dir_key=$(func_parser_key "${lines[16]}") - infer_img_dir=$(func_parser_value "${lines[16]}") - save_log_key=$(func_parser_key "${lines[17]}") - save_log_value=$(func_parser_value "${lines[17]}") - benchmark_key=$(func_parser_key "${lines[18]}") - benchmark_value=$(func_parser_value "${lines[18]}") - infer_key1=$(func_parser_key "${lines[19]}") - infer_value1=$(func_parser_value "${lines[19]}") -fi - LOG_PATH="./test_tipc/output/${model_name}/${MODE}" mkdir -p ${LOG_PATH} status_log="${LOG_PATH}/results_python.log" @@ -211,7 +174,7 @@ function func_inference(){ done } -if [ ${MODE} = "whole_infer" ] || [ ${MODE} = "klquant_whole_infer" ]; then +if [ ${MODE} = "whole_infer" ]; then GPUID=$3 if [ ${#GPUID} -le 0 ];then env=" " @@ -226,16 +189,12 @@ if [ ${MODE} = "whole_infer" ] || [ ${MODE} = "klquant_whole_infer" ]; then infer_quant_flag=(${infer_is_quant}) for infer_model in ${infer_model_dir_list[*]}; do # run export - if [ ${infer_run_exports[Count]} != "null" ];then - if [ ${MODE} = "klquant_whole_infer" ]; then - save_infer_dir="${infer_model}_klquant" - fi - if [ ${MODE} = "whole_infer" ]; then - save_infer_dir="${infer_model}" - fi + if [ ${infer_run_exports[Count]} != "null" ];then + save_infer_dir="${infer_model}" set_export_weight=$(func_set_params "${export_weight}" "${infer_model}") set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_dir}") - export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key}" + export_log_path="${LOG_PATH}/_export_${Count}.log" + export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key} > ${export_log_path} 2>&1 " echo ${infer_run_exports[Count]} echo $export_cmd eval $export_cmd @@ -246,9 +205,6 @@ if [ ${MODE} = "whole_infer" ] || [ ${MODE} = "klquant_whole_infer" ]; then fi #run inference is_quant=${infer_quant_flag[Count]} - if [ ${MODE} = "klquant_whole_infer" ]; then - is_quant="True" - fi func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${LOG_PATH}" "${infer_img_dir}" ${is_quant} Count=$(($Count + 1)) done @@ -347,7 +303,8 @@ else if [ ${eval_py} != "null" ]; then eval ${env} set_eval_params1=$(func_set_params "${eval_key1}" "${eval_value1}") - eval_cmd="${python} ${eval_py} ${set_eval_pretrain} ${set_use_gpu} ${set_eval_params1}" + eval_log_path="${LOG_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}_eval.log" + eval_cmd="${python} ${eval_py} ${set_eval_pretrain} ${set_use_gpu} ${set_eval_params1} > ${eval_log_path} 2>&1 " eval $eval_cmd status_check $? "${eval_cmd}" "${status_log}" "${model_name}" fi @@ -355,9 +312,10 @@ else if [ ${run_export} != "null" ]; then # run export model save_infer_path="${save_log}" + export_log_path="${LOG_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}_export.log" set_export_weight=$(func_set_params "${export_weight}" "${save_log}/${train_model_name}") set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_path}") - export_cmd="${python} ${run_export} ${set_export_weight} ${set_save_infer_key}" + export_cmd="${python} ${run_export} ${set_export_weight} ${set_save_infer_key} > ${export_log_path} 2>&1 " eval $export_cmd status_check $? "${export_cmd}" "${status_log}" "${model_name}" From ea1cc9225794efff63715ea6f7126add0159cfb8 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 22 Jun 2022 09:38:22 +0000 Subject: [PATCH 114/129] add ch doc --- deploy/avh/README_ch.md | 93 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 deploy/avh/README_ch.md diff --git a/deploy/avh/README_ch.md b/deploy/avh/README_ch.md new file mode 100644 index 0000000000..94db92e72c --- /dev/null +++ b/deploy/avh/README_ch.md @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + +通过TVM在 Arm(R) Cortex(R)-M55 CPU 上运行 PaddleOCR文 本能识别模型 +=============================================================== + +此文件夹包含如何使用 TVM 在 Cortex(R)-M55 CPU 上运行 PaddleOCR 模型的示例。 + +依赖 +------------- +本demo运行在TVM提供的docker环境上,在该环境中已经安装好的必须的软件 + + +在非docker环境中,需要手动安装如下依赖项: + +- 软件可通过[安装脚本](https://github.com/apache/tvm/docker/install/ubuntu_install_ethosu_driver_stack.sh)一键安装 + - [Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps) + - [cmake 3.19.5](https://github.com/Kitware/CMake/releases/) + - [GCC toolchain from Arm(R)](https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2) + - [Arm(R) Ethos(TM)-U NPU driver stack](https://review.mlplatform.org) + - [CMSIS](https://github.com/ARM-software/CMSIS_5) +- python 依赖 + ```bash + pip install -r ./requirements.txt + ``` +- TVM + - 从源码安装([Install from Source](https://tvm.apache.org/docs/install/from_source.html)) + 从源码安装时,需要设置如下字段 + - set(USE_CMSISNN ON) + - set(USE_MICRO ON) + - set(USE_LLVM ON) + - 从TLCPack 安装([TLCPack](https://tlcpack.ai/)) + +安装完成后需要更新环境变量,以软件安装地址为`/opt/arm`为例: +```bash +export PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4:/opt/arm/cmake/bin:$PATH +``` + +运行demo +---------------------------- +使用如下命令可以一键运行demo + +```bash +./run_demo.sh +``` + +如果 Ethos(TM)-U 平台或 CMSIS 没有安装在 `/opt/arm/ethosu` 中,可通过参数进行设置,例如: + +```bash +./run_demo.sh --cmsis_path /home/tvm-user/cmsis \ +--ethosu_platform_path /home/tvm-user/ethosu/core_platform +``` + +`./run_demo.sh`脚本会执行如下步骤: +- 下载 PaddleOCR 文字识别模型 +- 使用tvm将PaddleOCR 文字识别模型编译为 Cortex(R)-M55 CPU 和 CMSIS-NN 后端的可执行文件 +- 创建一个包含输入图像数据的头文件`inputs.c` +- 创建一个包含输出tensor大小的头文件`outputs.c` +- 编译可执行程序 +- 运行程序 +- 输出图片上的文字和置信度 + +使用自己的图片 +-------------------- +替换 `run_demo.sh ` 中140行处的图片地址即可 + +使用自己的模型 +-------------------- +替换 `run_demo.sh ` 中130行处的模型地址即可 + +模型描述 +----------------- + +在这个demo中,我们使用的模型是基于[PP-OCRv3](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/PP-OCRv3_introduction.md)的英文识别模型。 PP-OCRv3是[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)发布的PP-OCR系列模型的第三个版本。 该系列模型具有以下特点: + - 超轻量级OCR系统:检测(3.6M)+方向分类器(1.4M)+识别(12M)=17.0M。 + - 支持80多种多语言识别模型,包括英文、中文、法文、德文、阿拉伯文、韩文、日文等。 + - 支持竖排文本识别,长文本识别。 + +PP-OCRv3 中的文本识别模型支持 80 多种语言。 在模型开发过程中,由于Arm(R) Cortex(R)-M55 CPU不支持rnn算子,我们在PP-OCRv3文本识别模型的基础上删除了不支持的算子,得到当前模型。 \ No newline at end of file From 6778ab933ae29bdef0d6f62a9b023c47f08ebab3 Mon Sep 17 00:00:00 2001 From: WenmuZhou <572459439@qq.com> Date: Wed, 22 Jun 2022 09:42:24 +0000 Subject: [PATCH 115/129] update doc --- deploy/avh/README.md | 2 +- deploy/avh/README_ch.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/avh/README.md b/deploy/avh/README.md index ecd635cc42..922fb4da92 100644 --- a/deploy/avh/README.md +++ b/deploy/avh/README.md @@ -28,7 +28,7 @@ software will already be installed. If the demo is not run in the ci_cpu Docker container, then you will need the following: - Software required to build and run the demo (These can all be installed by running - tvm/docker/install/ubuntu_install_ethosu_driver_stack.sh.) + https://github.com/apache/tvm/blob/main/docker/install/ubuntu_install_ethosu_driver_stack.sh .) - [Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps) - [cmake 3.19.5](https://github.com/Kitware/CMake/releases/) - [GCC toolchain from Arm(R)](https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2) diff --git a/deploy/avh/README_ch.md b/deploy/avh/README_ch.md index 94db92e72c..7e6272ae12 100644 --- a/deploy/avh/README_ch.md +++ b/deploy/avh/README_ch.md @@ -27,7 +27,7 @@ 在非docker环境中,需要手动安装如下依赖项: -- 软件可通过[安装脚本](https://github.com/apache/tvm/docker/install/ubuntu_install_ethosu_driver_stack.sh)一键安装 +- 软件可通过[安装脚本](https://github.com/apache/tvm/blob/main/docker/install/ubuntu_install_ethosu_driver_stack.sh)一键安装 - [Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps) - [cmake 3.19.5](https://github.com/Kitware/CMake/releases/) - [GCC toolchain from Arm(R)](https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2) From 6a8980e478ccacb7d3dfd9cd093c0c47132e01c9 Mon Sep 17 00:00:00 2001 From: an1018 <614803115@qq.com> Date: Sat, 25 Jun 2022 17:28:34 +0800 Subject: [PATCH 116/129] update --- applications/多模态表单识别.md | 157 ++++++++++++++++----------------- 1 file changed, 77 insertions(+), 80 deletions(-) diff --git a/applications/多模态表单识别.md b/applications/多模态表单识别.md index d47bbe7704..457d397030 100644 --- a/applications/多模态表单识别.md +++ b/applications/多模态表单识别.md @@ -1,4 +1,8 @@ -# 1 项目说明 +# 多模态表单识别 + +[TOC] + +## 1 项目说明 计算机视觉在金融领域的应用覆盖文字识别、图像识别、视频识别等,其中文字识别(OCR)是金融领域中的核心AI能力,其应用覆盖客户服务、风险防控、运营管理等各项业务,针对的对象包括通用卡证票据识别(银行卡、身份证、营业执照等)、通用文本表格识别(印刷体、多语言、手写体等)以及一些金融特色票据凭证。通过因此如果能够在结构化信息提取时同时利用文字、页面布局等信息,便可增强不同版式下的泛化性。 @@ -16,39 +20,37 @@
图1 多模态表单识别流程图
-注:欢迎再AIStudio领取免费算力体验线上实训,项目链接: [多模态表单识别](https://aistudio.baidu.com/aistudio/projectdetail/3884375)(配备Tesla V100、A100等高级算力资源) +注:欢迎再AIStudio领取免费算力体验线上实训,项目链接: [多模态表单识别](https://aistudio.baidu.com/aistudio/projectdetail/3884375?contributionType=1) - - -# 2 安装说明 +## 2 安装说明 下载PaddleOCR源码,上述AIStudio项目中已经帮大家打包好的PaddleOCR(已经修改好配置文件),无需下载解压即可,只需安装依赖环境~ ```python -! unzip -q PaddleOCR.zip +unzip -q PaddleOCR.zip ``` ```python # 如仍需安装or安装更新,可以执行以下步骤 -# ! git clone https://github.com/PaddlePaddle/PaddleOCR.git -b dygraph -# ! git clone https://gitee.com/PaddlePaddle/PaddleOCR +# git clone https://github.com/PaddlePaddle/PaddleOCR.git -b dygraph +# git clone https://gitee.com/PaddlePaddle/PaddleOCR ``` ```python # 安装依赖包 -! pip install -U pip -! pip install -r /home/aistudio/PaddleOCR/requirements.txt -! pip install paddleocr +pip install -U pip +pip install -r /home/aistudio/PaddleOCR/requirements.txt +pip install paddleocr -! pip install yacs gnureadline paddlenlp==2.2.1 -! pip install xlsxwriter +pip install yacs gnureadline paddlenlp==2.2.1 +pip install xlsxwriter ``` -# 3 数据准备 +## 3 数据准备 这里使用[XFUN数据集](https://github.com/doc-analysis/XFUND)做为实验数据集。 XFUN数据集是微软提出的一个用于KIE任务的多语言数据集,共包含七个数据集,每个数据集包含149张训练集和50张验证集 @@ -59,7 +61,7 @@
图2 数据集样例,左中文,右法语
-## 3.1 下载处理好的数据集 +### 3.1 下载处理好的数据集 处理好的XFUND中文数据集下载地址:[https://paddleocr.bj.bcebos.com/dataset/XFUND.tar](https://paddleocr.bj.bcebos.com/dataset/XFUND.tar) ,可以运行如下指令完成中文数据集下载和解压。 @@ -69,13 +71,13 @@ ```python -! wget https://paddleocr.bj.bcebos.com/dataset/XFUND.tar -! tar -xf XFUND.tar +wget https://paddleocr.bj.bcebos.com/dataset/XFUND.tar +tar -xf XFUND.tar # XFUN其他数据集使用下面的代码进行转换 # 代码链接:https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.4/ppstructure/vqa/helper/trans_xfun_data.py # %cd PaddleOCR -# !python3 ppstructure/vqa/tools/trans_xfun_data.py --ori_gt_path=path/to/json_path --output_path=path/to/save_path +# python3 ppstructure/vqa/tools/trans_xfun_data.py --ori_gt_path=path/to/json_path --output_path=path/to/save_path # %cd ../ ``` @@ -119,7 +121,7 @@ } ``` -## 3.2 转换为PaddleOCR检测和识别格式 +### 3.2 转换为PaddleOCR检测和识别格式 使用XFUND训练PaddleOCR检测和识别模型,需要将数据集格式改为训练需求的格式。 @@ -147,7 +149,7 @@ train_data/rec/train/word_002.jpg 用科技让复杂的世界更简单 ```python -! unzip -q /home/aistudio/data/data140302/XFUND_ori.zip -d /home/aistudio/data/data140302/ +unzip -q /home/aistudio/data/data140302/XFUND_ori.zip -d /home/aistudio/data/data140302/ ``` 已经提供转换脚本,执行如下代码即可转换成功: @@ -155,21 +157,20 @@ train_data/rec/train/word_002.jpg 用科技让复杂的世界更简单 ```python %cd /home/aistudio/ -! python trans_xfund_data.py +python trans_xfund_data.py ``` -# 4 OCR +## 4 OCR 选用飞桨OCR开发套件[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/README_ch.md)中的PP-OCRv2模型进行文本检测和识别。PP-OCRv2在PP-OCR的基础上,进一步在5个方面重点优化,检测模型采用CML协同互学习知识蒸馏策略和CopyPaste数据增广策略;识别模型采用LCNet轻量级骨干网络、UDML 改进知识蒸馏策略和[Enhanced CTC loss](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/doc/doc_ch/enhanced_ctc_loss.md)损失函数改进,进一步在推理速度和预测效果上取得明显提升。更多细节请参考PP-OCRv2[技术报告](https://arxiv.org/abs/2109.03144)。 - -## 4.1 文本检测 +### 4.1 文本检测 我们使用2种方案进行训练、评估: - **PP-OCRv2中英文超轻量检测预训练模型** - **XFUND数据集+fine-tune** -### **4.1.1 方案1:预训练模型** +#### **4.1.1 方案1:预训练模型** **1)下载预训练模型** @@ -195,8 +196,8 @@ PaddleOCR已经提供了PP-OCR系列模型,部分模型展示如下表所示 ```python %cd /home/aistudio/PaddleOCR/pretrain/ -! wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar -! tar -xf ch_PP-OCRv2_det_distill_train.tar && rm -rf ch_PP-OCRv2_det_distill_train.tar +wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar +tar -xf ch_PP-OCRv2_det_distill_train.tar && rm -rf ch_PP-OCRv2_det_distill_train.tar % cd .. ``` @@ -226,7 +227,7 @@ Eval.dataset.label_file_list:指向验证集标注文件 ```python %cd /home/aistudio/PaddleOCR -! python tools/eval.py \ +python tools/eval.py \ -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml \ -o Global.checkpoints="./pretrain_models/ch_PP-OCRv2_det_distill_train/best_accuracy" ``` @@ -237,9 +238,9 @@ Eval.dataset.label_file_list:指向验证集标注文件 | -------- | -------- | | PP-OCRv2中英文超轻量检测预训练模型 | 77.26% | -使用文本检测预训练模型在XFUND验证集上评估,达到77%左右,充分说明ppocr提供的预训练模型有一定的泛化能力。 +使用文本检测预训练模型在XFUND验证集上评估,达到77%左右,充分说明ppocr提供的预训练模型具有泛化能力。 -### **4.1.2 方案2:XFUND数据集+fine-tune** +#### **4.1.2 方案2:XFUND数据集+fine-tune** PaddleOCR提供的蒸馏预训练模型包含了多个模型的参数,我们提取Student模型的参数,在XFUND数据集上进行finetune,可以参考如下代码: @@ -281,7 +282,7 @@ Eval.dataset.transforms.DetResizeForTest:评估尺寸,添加如下参数 ```python -! CUDA_VISIBLE_DEVICES=0 python tools/train.py \ +CUDA_VISIBLE_DEVICES=0 python tools/train.py \ -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml ``` @@ -290,12 +291,12 @@ Eval.dataset.transforms.DetResizeForTest:评估尺寸,添加如下参数
图8 文本检测方案2-模型评估
-使用训练好的模型进行评估,更新模型路径`Global.checkpoints`,这里为大家提供训练好的模型`./pretrain/ch_db_mv3-student1600-finetune/best_accuracy`,[模型下载地址](https://paddleocr.bj.bcebos.com/fanliku/sheet_recognition/ch_db_mv3-student1600-finetune.zip) +使用训练好的模型进行评估,更新模型路径`Global.checkpoints`。 ```python %cd /home/aistudio/PaddleOCR/ -! python tools/eval.py \ +python tools/eval.py \ -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml \ -o Global.checkpoints="pretrain/ch_db_mv3-student1600-finetune/best_accuracy" ``` @@ -305,7 +306,7 @@ Eval.dataset.transforms.DetResizeForTest:评估尺寸,添加如下参数 ```python %cd /home/aistudio/PaddleOCR/ -! python tools/eval.py \ +python tools/eval.py \ -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml \ -o Global.checkpoints="pretrain/ch_db_mv3-student1600/best_accuracy" ``` @@ -331,7 +332,7 @@ Eval.dataset.transforms.DetResizeForTest:评估尺寸,添加如下参数 # 加载配置文件`ch_PP-OCRv2_det_student.yml`,从`pretrain/ch_db_mv3-student1600-finetune`目录下加载`best_accuracy`模型 # inference模型保存在`./output/det_db_inference`目录下 %cd /home/aistudio/PaddleOCR/ -! python tools/export_model.py \ +python tools/export_model.py \ -c configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml \ -o Global.pretrained_model="pretrain/ch_db_mv3-student1600-finetune/best_accuracy" \ Global.save_inference_dir="./output/det_db_inference/" @@ -374,12 +375,11 @@ use_gpu:是否使用GPU | 方案 | hmeans | 结果分析 | | -------- | -------- | -------- | -| PP-OCRv2中英文超轻量检测预训练模型 | 77.26% | ppocr提供的预训练模型有一定的泛化能力 | +| PP-OCRv2中英文超轻量检测预训练模型 | 77.26% | ppocr提供的预训练模型有泛化能力 | | XFUND数据集 | 79.27% | | | XFUND数据集+finetune | 85.24% | finetune会提升垂类场景效果 | - -## 4.2 文本识别 +### 4.2 文本识别 我们分别使用如下3种方案进行训练、评估: @@ -387,8 +387,7 @@ use_gpu:是否使用GPU - XFUND数据集+fine-tune - XFUND数据集+fine-tune+真实通用识别数据 - -### **4.2.1 方案1:预训练模型** +#### **4.2.1 方案1:预训练模型** **1)下载预训练模型** @@ -401,8 +400,8 @@ use_gpu:是否使用GPU ```python %cd /home/aistudio/PaddleOCR/pretrain/ -! wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar -! tar -xf ch_PP-OCRv2_rec_train.tar && rm -rf ch_PP-OCRv2_rec_train.tar +wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar +tar -xf ch_PP-OCRv2_rec_train.tar && rm -rf ch_PP-OCRv2_rec_train.tar % cd .. ``` @@ -424,7 +423,7 @@ Eval.dataset.label_file_list:指向验证集标注文件 ```python %cd /home/aistudio/PaddleOCR -! CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ +CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ -c configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml \ -o Global.checkpoints=./pretrain/ch_PP-OCRv2_rec_train/best_accuracy ``` @@ -435,9 +434,9 @@ Eval.dataset.label_file_list:指向验证集标注文件 | -------- | -------- | | PP-OCRv2中英文超轻量识别预训练模型 | 67.48% | -使用文本预训练模型在XFUND验证集上评估,acc达到67%左右,充分说明ppocr提供的预训练模型有一定的泛化能力。 +使用文本预训练模型在XFUND验证集上评估,acc达到67%左右,充分说明ppocr提供的预训练模型具有泛化能力。 -### **4.2.2 方案2:XFUND数据集+finetune** +#### **4.2.2 方案2:XFUND数据集+finetune** 同检测模型,我们提取Student模型的参数,在XFUND数据集上进行finetune,可以参考如下代码: @@ -474,11 +473,9 @@ Eval.dataset.label_file_list:指向验证集标注文件 ``` 执行如下命令启动训练: - - ```python %cd /home/aistudio/PaddleOCR/ -! CUDA_VISIBLE_DEVICES=0 python tools/train.py \ +CUDA_VISIBLE_DEVICES=0 python tools/train.py \ -c configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml ``` @@ -493,7 +490,7 @@ Eval.dataset.label_file_list:指向验证集标注文件 ```python %cd /home/aistudio/PaddleOCR/ -! CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ +CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ -c configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml \ -o Global.checkpoints=./pretrain/rec_mobile_pp-OCRv2-student-finetune/best_accuracy ``` @@ -506,7 +503,7 @@ Eval.dataset.label_file_list:指向验证集标注文件 使用XFUND数据集+finetune训练,在验证集上评估达到72%左右,说明 finetune会提升垂类场景效果。 -### **4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据** +#### **4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据** 接着我们在上述`XFUND数据集+finetune`实验的基础上,添加真实通用识别数据,进一步提升识别效果。首先准备真实通用识别数据,并上传到AIStudio: @@ -528,7 +525,7 @@ Train.dataset.ratio_list:动态采样 ```python %cd /home/aistudio/PaddleOCR/ -! CUDA_VISIBLE_DEVICES=0 python tools/train.py \ +CUDA_VISIBLE_DEVICES=0 python tools/train.py \ -c configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml ``` @@ -538,11 +535,11 @@ Train.dataset.ratio_list:动态采样
图16 文本识别方案3-模型评估
-使用训练好的模型进行评估,更新模型路径`Global.checkpoints`,这里为大家提供训练好的模型`./pretrain/rec_mobile_pp-OCRv2-student-readldata/best_accuracy`,[模型下载地址](https://paddleocr.bj.bcebos.com/fanliku/sheet_recognition/rec_mobile_pp-OCRv2-student-realdata.zip) +使用训练好的模型进行评估,更新模型路径`Global.checkpoints`。 ```python -! CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ +CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ -c configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml \ -o Global.checkpoints=./pretrain/rec_mobile_pp-OCRv2-student-realdata/best_accuracy ``` @@ -580,7 +577,7 @@ Train.dataset.ratio_list:动态采样 ```python -! python tools/infer/predict_system.py \ +python tools/infer/predict_system.py \ --image_dir="./doc/vqa/input/zh_val_21.jpg" \ --det_model_dir="./output/det_db_inference/" \ --rec_model_dir="./output/rec_crnn_inference/" \ @@ -592,11 +589,11 @@ Train.dataset.ratio_list:动态采样 | 方案 | acc | 结果分析 | | -------- | -------- | -------- | -| PP-OCRv2中英文超轻量识别预训练模型 | 67.48% | ppocr提供的预训练模型有一定的泛化能力 | +| PP-OCRv2中英文超轻量识别预训练模型 | 67.48% | ppocr提供的预训练模型具有泛化能力 | | XFUND数据集+fine-tune |72.33% | finetune会提升垂类场景效果 | | XFUND数据集+fine-tune+真实通用识别数据 | 85.29% | 真实通用识别数据对于性能提升很有帮助 | -# 5 文档视觉问答(DOC-VQA) +## 5 文档视觉问答(DOC-VQA) VQA指视觉问答,主要针对图像内容进行提问和回答,DOC-VQA是VQA任务中的一种,DOC-VQA主要针对文本图像的文字内容提出问题。 @@ -608,14 +605,13 @@ PaddleOCR中DOC-VQA系列算法基于PaddleNLP自然语言处理算法库实现L ```python %cd pretrain #下载SER模型 -! wget https://paddleocr.bj.bcebos.com/pplayout/ser_LayoutXLM_xfun_zh.tar && tar -xvf ser_LayoutXLM_xfun_zh.tar +wget https://paddleocr.bj.bcebos.com/pplayout/ser_LayoutXLM_xfun_zh.tar && tar -xvf ser_LayoutXLM_xfun_zh.tar #下载RE模型 -! wget https://paddleocr.bj.bcebos.com/pplayout/re_LayoutXLM_xfun_zh.tar && tar -xvf re_LayoutXLM_xfun_zh.tar +wget https://paddleocr.bj.bcebos.com/pplayout/re_LayoutXLM_xfun_zh.tar && tar -xvf re_LayoutXLM_xfun_zh.tar %cd ../ ``` - -## 5.1 SER +### 5.1 SER SER: 语义实体识别 (Semantic Entity Recognition), 可以完成对图像中的文本识别与分类。 @@ -647,7 +643,7 @@ SER: 语义实体识别 (Semantic Entity Recognition), 可以完成对图像 ```python %cd /home/aistudio/PaddleOCR/ -! CUDA_VISIBLE_DEVICES=0 python tools/train.py -c configs/vqa/ser/layoutxlm.yml +CUDA_VISIBLE_DEVICES=0 python tools/train.py -c configs/vqa/ser/layoutxlm.yml ``` 最终会打印出`precision`, `recall`, `hmean`等指标。 在`./output/ser_layoutxlm/`文件夹中会保存训练日志,最优的模型和最新epoch的模型。 @@ -664,7 +660,7 @@ SER: 语义实体识别 (Semantic Entity Recognition), 可以完成对图像 ```python -! CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ +CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ -c configs/vqa/ser/layoutxlm.yml \ -o Architecture.Backbone.checkpoints=pretrain/ser_LayoutXLM_xfun_zh/ ``` @@ -684,7 +680,7 @@ SER: 语义实体识别 (Semantic Entity Recognition), 可以完成对图像 ```python -! CUDA_VISIBLE_DEVICES=0 python tools/infer_vqa_token_ser.py \ +CUDA_VISIBLE_DEVICES=0 python tools/infer_vqa_token_ser.py \ -c configs/vqa/ser/layoutxlm.yml \ -o Architecture.Backbone.checkpoints=pretrain/ser_LayoutXLM_xfun_zh/ \ Global.infer_img=doc/vqa/input/zh_val_42.jpg @@ -704,7 +700,7 @@ plt.figure(figsize=(48,24)) plt.imshow(img) ``` -## 5.2 RE +### 5.2 RE 基于 RE 任务,可以完成对图象中的文本内容的关系提取,如判断问题对(pair)。 @@ -729,7 +725,7 @@ plt.imshow(img) ```python -! CUDA_VISIBLE_DEVICES=0 python3 tools/train.py -c configs/vqa/re/layoutxlm.yml +CUDA_VISIBLE_DEVICES=0 python3 tools/train.py -c configs/vqa/re/layoutxlm.yml ``` 最终会打印出`precision`, `recall`, `hmean`等指标。 在`./output/re_layoutxlm/`文件夹中会保存训练日志,最优的模型和最新epoch的模型 @@ -744,7 +740,7 @@ plt.imshow(img) ```python -! CUDA_VISIBLE_DEVICES=0 python3 tools/eval.py \ +CUDA_VISIBLE_DEVICES=0 python3 tools/eval.py \ -c configs/vqa/re/layoutxlm.yml \ -o Architecture.Backbone.checkpoints=pretrain/re_LayoutXLM_xfun_zh/ ``` @@ -760,20 +756,14 @@ plt.imshow(img)
图26 RE-模型预测
- 使用OCR引擎 + SER + RE串联预测 - -使用如下命令即可完成OCR引擎 + SER + RE的串联预测, 以预训练SER和RE模型为例: - - +使用如下命令即可完成OCR引擎 + SER + RE的串联预测, 以预训练SER和RE模型为例, 最终会在config.Global.save_res_path字段所配置的目录下保存预测结果可视化图像以及预测结果文本文件,预测结果文本文件名为infer_results.txt。 - - ```python -%cd /home/aistudio/PaddleOCR -! CUDA_VISIBLE_DEVICES=0 python3 tools/infer_vqa_token_ser_re.py \ +cd /home/aistudio/PaddleOCR +CUDA_VISIBLE_DEVICES=0 python3 tools/infer_vqa_token_ser_re.py \ -c configs/vqa/re/layoutxlm.yml \ -o Architecture.Backbone.checkpoints=pretrain/re_LayoutXLM_xfun_zh/ \ Global.infer_img=test_imgs/ \ @@ -787,10 +777,9 @@ plt.imshow(img) test_imgs/t131.jpg {"政治面税": "群众", "性别": "男", "籍贯": "河北省邯郸市", "婚姻状况": "亏末婚口已婚口已娇", "通讯地址": "邯郸市阳光苑7号楼003", "民族": "汉族", "毕业院校": "河南工业大学", "户口性质": "口农村城镇", "户口地址": "河北省邯郸市", "联系电话": "13288888888", "健康状况": "健康", "姓名": "小六", "好高cm": "180", "出生年月": "1996年8月9日", "文化程度": "本科", "身份证号码": "458933777777777777"} ```` - +展示预测结果 ```python -# 展示预测结果 import cv2 from matplotlib import pyplot as plt %matplotlib inline @@ -800,7 +789,7 @@ plt.figure(figsize=(48,24)) plt.imshow(img) ``` -# 6 导出Excel +## 6 导出Excel
图27 导出Excel
@@ -859,7 +848,15 @@ with open('output/re/infer_results.txt', 'r', encoding='utf-8') as fin: workbook.close() ``` -# 更多资源 +## 获得模型 + +如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 +
+ +
+将下载或训练完成的模型放置在对应目录下即可完成模型推理 + +## 更多资源 - 更多深度学习知识、产业案例、面试宝典等,请参考:[awesome-DeepLearning](https://github.com/paddlepaddle/awesome-DeepLearning) @@ -869,7 +866,7 @@ workbook.close() - 飞桨框架相关资料,请参考:[飞桨深度学习平台](https://www.paddlepaddle.org.cn/?fr=paddleEdu_aistudio) -# 参考链接 +## 参考链接 - LayoutXLM: Multimodal Pre-training for Multilingual Visually-rich Document Understanding, https://arxiv.org/pdf/2104.08836.pdf From 079cdf980cccaf54302040562fafde94b9a9181e Mon Sep 17 00:00:00 2001 From: zhoujun Date: Mon, 27 Jun 2022 00:49:00 +0800 Subject: [PATCH 117/129] update save model func (#6693) * save latest metric * save latest metric * add boader judge * add boader judge --- PPOCRLabel/libs/shape.py | 1 + applications/轻量级车牌识别.md | 11 ++++++----- ppocr/data/imaug/fce_targets.py | 9 +++++++-- ppocr/utils/save_load.py | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/PPOCRLabel/libs/shape.py b/PPOCRLabel/libs/shape.py index 18cc4a8e76..97e2eb7238 100644 --- a/PPOCRLabel/libs/shape.py +++ b/PPOCRLabel/libs/shape.py @@ -48,6 +48,7 @@ class Shape(object): def __init__(self, label=None, line_color=None, difficult=False, key_cls="None", paintLabel=False): self.label = label + self.idx = 0 self.points = [] self.fill = False self.selected = False diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index 7012c7f4bb..1a63091b92 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -311,7 +311,6 @@ python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o 在上述命令中,通过`-o`的方式修改了配置文件中的参数。 -训练好的模型地址为: [det_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_finetune.tar) **评估** @@ -354,8 +353,6 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] ``` -训练好的模型地址为: [det_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_quant.tar) - 量化后指标对比如下 |方案|hmeans| 模型大小 | 预测速度(lite) | @@ -436,6 +433,12 @@ python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] ``` +如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 +
+ +
+ + 评估部分日志如下: ```bash [2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy @@ -528,7 +531,6 @@ python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \ Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] ``` -训练好的模型地址为: [rec_ppocr_v3_finetune.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_finetune.tar) **评估** @@ -570,7 +572,6 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \ Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt] ``` -训练好的模型地址为: [rec_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_quant.tar) 量化后指标对比如下 diff --git a/ppocr/data/imaug/fce_targets.py b/ppocr/data/imaug/fce_targets.py index 4d1903c0a7..8c64276e26 100644 --- a/ppocr/data/imaug/fce_targets.py +++ b/ppocr/data/imaug/fce_targets.py @@ -107,17 +107,20 @@ class FCENetTargets: for i in range(1, n): current_line_len = i * delta_length - while current_line_len >= length_cumsum[current_edge_ind + 1]: + while current_edge_ind + 1 < len(length_cumsum) and current_line_len >= length_cumsum[current_edge_ind + 1]: current_edge_ind += 1 + current_edge_end_shift = current_line_len - length_cumsum[ current_edge_ind] + + if current_edge_ind >= len(length_list): + break end_shift_ratio = current_edge_end_shift / length_list[ current_edge_ind] current_point = line[current_edge_ind] + (line[current_edge_ind + 1] - line[current_edge_ind] ) * end_shift_ratio resampled_line.append(current_point) - resampled_line.append(line[-1]) resampled_line = np.array(resampled_line) @@ -328,6 +331,8 @@ class FCENetTargets: resampled_top_line, resampled_bot_line = self.resample_sidelines( top_line, bot_line, self.resample_step) resampled_bot_line = resampled_bot_line[::-1] + if len(resampled_top_line) != len(resampled_bot_line): + continue center_line = (resampled_top_line + resampled_bot_line) / 2 line_head_shrink_len = norm(resampled_top_line[0] - diff --git a/ppocr/utils/save_load.py b/ppocr/utils/save_load.py index b09f1db6e9..3647111fdd 100644 --- a/ppocr/utils/save_load.py +++ b/ppocr/utils/save_load.py @@ -177,9 +177,9 @@ def save_model(model, model.backbone.model.save_pretrained(model_prefix) metric_prefix = os.path.join(model_prefix, 'metric') # save metric and config + with open(metric_prefix + '.states', 'wb') as f: + pickle.dump(kwargs, f, protocol=2) if is_best: - with open(metric_prefix + '.states', 'wb') as f: - pickle.dump(kwargs, f, protocol=2) logger.info('save best model is to {}'.format(model_prefix)) else: logger.info("save model in {}".format(model_prefix)) From d554037ece782db092cb46394ad4aface7834c0c Mon Sep 17 00:00:00 2001 From: an1018 <614803115@qq.com> Date: Mon, 27 Jun 2022 10:04:39 +0800 Subject: [PATCH 118/129] update --- applications/多模态表单识别.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/applications/多模态表单识别.md b/applications/多模态表单识别.md index 457d397030..27f981101a 100644 --- a/applications/多模态表单识别.md +++ b/applications/多模态表单识别.md @@ -1,6 +1,31 @@ # 多模态表单识别 - -[TOC] +- [多模态表单识别](#多模态表单识别) + - [1 项目说明](#1-项目说明) + - [2 安装说明](#2-安装说明) + - [3 数据准备](#3-数据准备) + - [3.1 下载处理好的数据集](#31-下载处理好的数据集) + - [3.2 转换为PaddleOCR检测和识别格式](#32-转换为paddleocr检测和识别格式) + - [4 OCR](#4-ocr) + - [4.1 文本检测](#41-文本检测) + - [**4.1.1 方案1:预训练模型**](#411-方案1预训练模型) + - [**4.1.2 方案2:XFUND数据集+fine-tune**](#412-方案2xfund数据集fine-tune) + - [4.2 文本识别](#42-文本识别) + - [**4.2.1 方案1:预训练模型**](#421-方案1预训练模型) + - [**4.2.2 方案2:XFUND数据集+finetune**](#422-方案2xfund数据集finetune) + - [**4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据**](#423-方案3xfund数据集finetune真实通用识别数据) + - [5 文档视觉问答(DOC-VQA)](#5-文档视觉问答doc-vqa) + - [5.1 SER](#51-ser) + - [5.1.1 模型训练](#511-模型训练) + - [5.1.2 模型评估](#512-模型评估) + - [5.1.3 模型预测](#513-模型预测) + - [5.2 RE](#52-re) + - [5.2.1 模型训练](#521-模型训练) + - [5.2.2 模型评估](#522-模型评估) + - [5.2.3 模型预测](#523-模型预测) + - [6 导出Excel](#6-导出excel) + - [获得模型](#获得模型) + - [更多资源](#更多资源) + - [参考链接](#参考链接) ## 1 项目说明 From 1eba8ae3f89ac850fbec35f5d3b1c6e402dfd02a Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:51:33 +0800 Subject: [PATCH 119/129] =?UTF-8?q?Update=20=E5=85=89=E5=8A=9F=E7=8E=87?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E7=A0=81=E7=AE=A1=E5=AD=97=E7=AC=A6=E8=AF=86?= =?UTF-8?q?=E5=88=AB.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/光功率计数码管字符识别.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/applications/光功率计数码管字符识别.md b/applications/光功率计数码管字符识别.md index 33c515a5e9..d6c11259bf 100644 --- a/applications/光功率计数码管字符识别.md +++ b/applications/光功率计数码管字符识别.md @@ -21,7 +21,12 @@ 第二步,使用文本识别模型获得准确的数字和单位信息。 -本项目主要介绍如何完成第二步文本识别部分。 +本项目主要介绍如何完成第二步文本识别部分,包括: + +* 真实评估集的建立 +* 训练数据的合成 +* 基于 PP-OCRv3 和 SVTR_Tiny 两个模型进行训练 +* 评估并推理 ## 2. PaddleOCR 快速使用 @@ -400,7 +405,11 @@ python tools/train.py -c rec_svtr_tiny_none_ctc_ch_train/rec_svtr_tiny_6local_6g ### 3.4 验证效果 -**本例中的评估集和模型路径,可通过填写[问卷](todo:add link)获得** +如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 +
+ +
+将下载或训练完成的模型放置在对应目录下即可完成模型推理 * 指标评估 From ec3f8ff7e83d2462ef99b538ff0b5c7311ae992d Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Mon, 27 Jun 2022 19:29:33 +0800 Subject: [PATCH 120/129] support PP-OCRv3 for lite demo (arm8) --- deploy/lite/config.txt | 3 ++- deploy/lite/crnn_process.cc | 18 ++++++++-------- deploy/lite/crnn_process.h | 2 +- deploy/lite/ocr_db_crnn.cc | 13 ++++++++---- deploy/lite/readme.md | 36 ++++++++++++++++++-------------- deploy/lite/readme_ch.md | 41 ++++++++++++++++++++----------------- 6 files changed, 65 insertions(+), 48 deletions(-) diff --git a/deploy/lite/config.txt b/deploy/lite/config.txt index 4c68105d39..dda0d2b032 100644 --- a/deploy/lite/config.txt +++ b/deploy/lite/config.txt @@ -4,4 +4,5 @@ det_db_box_thresh 0.5 det_db_unclip_ratio 1.6 det_db_use_dilate 0 det_use_polygon_score 1 -use_direction_classify 1 \ No newline at end of file +use_direction_classify 1 +rec_image_height 32 \ No newline at end of file diff --git a/deploy/lite/crnn_process.cc b/deploy/lite/crnn_process.cc index 7528f36fe6..6d5fc1504e 100644 --- a/deploy/lite/crnn_process.cc +++ b/deploy/lite/crnn_process.cc @@ -19,25 +19,27 @@ const std::vector rec_image_shape{3, 32, 320}; -cv::Mat CrnnResizeImg(cv::Mat img, float wh_ratio) { +cv::Mat CrnnResizeImg(cv::Mat img, float wh_ratio, int rec_image_height) { int imgC, imgH, imgW; imgC = rec_image_shape[0]; + imgH = rec_image_height; imgW = rec_image_shape[2]; - imgH = rec_image_shape[1]; - imgW = int(32 * wh_ratio); + imgW = int(imgH * wh_ratio); - float ratio = static_cast(img.cols) / static_cast(img.rows); + float ratio = float(img.cols) / float(img.rows); int resize_w, resize_h; + if (ceilf(imgH * ratio) > imgW) resize_w = imgW; else - resize_w = static_cast(ceilf(imgH * ratio)); - cv::Mat resize_img; + resize_w = int(ceilf(imgH * ratio)); + cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, cv::INTER_LINEAR); - - return resize_img; + cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, + int(imgW - resize_img.cols), cv::BORDER_CONSTANT, + {127, 127, 127}); } std::vector ReadDict(std::string path) { diff --git a/deploy/lite/crnn_process.h b/deploy/lite/crnn_process.h index 29e6790697..ed7a316706 100644 --- a/deploy/lite/crnn_process.h +++ b/deploy/lite/crnn_process.h @@ -26,7 +26,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc.hpp" -cv::Mat CrnnResizeImg(cv::Mat img, float wh_ratio); +cv::Mat CrnnResizeImg(cv::Mat img, float wh_ratio, int rec_image_height); std::vector ReadDict(std::string path); diff --git a/deploy/lite/ocr_db_crnn.cc b/deploy/lite/ocr_db_crnn.cc index 1ffbbacb74..cb2bf7791a 100644 --- a/deploy/lite/ocr_db_crnn.cc +++ b/deploy/lite/ocr_db_crnn.cc @@ -162,7 +162,8 @@ void RunRecModel(std::vector>> boxes, cv::Mat img, std::vector charactor_dict, std::shared_ptr predictor_cls, int use_direction_classify, - std::vector *times) { + std::vector *times, + int rec_image_height) { std::vector mean = {0.5f, 0.5f, 0.5f}; std::vector scale = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f}; @@ -183,7 +184,7 @@ void RunRecModel(std::vector>> boxes, cv::Mat img, float wh_ratio = static_cast(crop_img.cols) / static_cast(crop_img.rows); - resize_img = CrnnResizeImg(crop_img, wh_ratio); + resize_img = CrnnResizeImg(crop_img, wh_ratio, rec_image_height); resize_img.convertTo(resize_img, CV_32FC3, 1 / 255.f); const float *dimg = reinterpret_cast(resize_img.data); @@ -444,7 +445,7 @@ void system(char **argv){ //// load config from txt file auto Config = LoadConfigTxt(det_config_path); int use_direction_classify = int(Config["use_direction_classify"]); - + int rec_image_height = int(Config["rec_image_height"]); auto charactor_dict = ReadDict(dict_path); charactor_dict.insert(charactor_dict.begin(), "#"); // blank char for ctc charactor_dict.push_back(" "); @@ -590,12 +591,16 @@ void rec(int argc, char **argv) { std::string batchsize = argv[6]; std::string img_dir = argv[7]; std::string dict_path = argv[8]; + std::string config_path = argv[9]; if (strcmp(argv[4], "FP32") != 0 && strcmp(argv[4], "INT8") != 0) { std::cerr << "Only support FP32 or INT8." << std::endl; exit(1); } + auto Config = LoadConfigTxt(config_path); + int rec_image_height = int(Config["rec_image_height"]); + std::vector cv_all_img_names; cv::glob(img_dir, cv_all_img_names); @@ -630,7 +635,7 @@ void rec(int argc, char **argv) { std::vector rec_text_score; std::vector times; RunRecModel(boxes, srcimg, rec_predictor, rec_text, rec_text_score, - charactor_dict, cls_predictor, 0, ×); + charactor_dict, cls_predictor, 0, ×, rec_image_height); //// print recognized text for (int i = 0; i < rec_text.size(); i++) { diff --git a/deploy/lite/readme.md b/deploy/lite/readme.md index 9926e2dd8c..883aff9890 100644 --- a/deploy/lite/readme.md +++ b/deploy/lite/readme.md @@ -34,7 +34,7 @@ For the compilation process of different development environments, please refer ### 1.2 Prepare Paddle-Lite library There are two ways to obtain the Paddle-Lite library: -- 1. Download directly, the download link of the Paddle-Lite library is as follows: +- 1. [Recommended] Download directly, the download link of the Paddle-Lite library is as follows: | Platform | Paddle-Lite library download link | |---|---| @@ -43,7 +43,9 @@ There are two ways to obtain the Paddle-Lite library: Note: 1. The above Paddle-Lite library is compiled from the Paddle-Lite 2.10 branch. For more information about Paddle-Lite 2.10, please refer to [link](https://github.com/PaddlePaddle/Paddle-Lite/releases/tag/v2.10). -- 2. [Recommended] Compile Paddle-Lite to get the prediction library. The compilation method of Paddle-Lite is as follows: + **Note: It is recommended to use paddlelite>=2.10 version of the prediction library, other prediction library versions [download link](https://github.com/PaddlePaddle/Paddle-Lite/tags)** + +- 2. Compile Paddle-Lite to get the prediction library. The compilation method of Paddle-Lite is as follows: ``` git clone https://github.com/PaddlePaddle/Paddle-Lite.git cd Paddle-Lite @@ -104,20 +106,16 @@ If you directly use the model in the above table for deployment, you can skip th If the model to be deployed is not in the above table, you need to follow the steps below to obtain the optimized model. -The `opt` tool can be obtained by compiling Paddle Lite. +- Step 1: Refer to [document](https://www.paddlepaddle.org.cn/lite/v2.10/user_guides/opt/opt_python.html) to install paddlelite, which is used to convert paddle inference model to paddlelite required for running nb model ``` -git clone https://github.com/PaddlePaddle/Paddle-Lite.git -cd Paddle-Lite -git checkout release/v2.10 -./lite/tools/build.sh build_optimize_tool +pip install paddlelite==2.10 # The paddlelite version should be the same as the prediction library version +``` +After installation, the following commands can view the help information +``` +paddle_lite_opt ``` -After the compilation is complete, the opt file is located under build.opt/lite/api/, You can view the operating options and usage of opt in the following ways: - -``` -cd build.opt/lite/api/ -./opt -``` +Introduction to paddle_lite_opt parameters: |Options|Description| |---|---| @@ -131,6 +129,8 @@ cd build.opt/lite/api/ `--model_dir` is suitable for the non-combined mode of the model to be optimized, and the inference model of PaddleOCR is the combined mode, that is, the model structure and model parameters are stored in a single file. +- Step 2: Use paddle_lite_opt to convert the inference model to the mobile model format. + The following takes the ultra-lightweight Chinese model of PaddleOCR as an example to introduce the use of the compiled opt file to complete the conversion of the inference model to the Paddle-Lite optimized model ``` @@ -240,6 +240,7 @@ det_db_thresh 0.3 # Used to filter the binarized image of DB prediction, det_db_box_thresh 0.5 # DDB post-processing filter box threshold, if there is a missing box detected, it can be reduced as appropriate det_db_unclip_ratio 1.6 # Indicates the compactness of the text box, the smaller the value, the closer the text box to the text use_direction_classify 0 # Whether to use the direction classifier, 0 means not to use, 1 means to use +rec_image_height 32 # The height of the input image of the recognition model, the PP-OCRv3 model needs to be set to 48, and the PP-OCRv2 model needs to be set to 32 ``` 5. Run Model on phone @@ -258,8 +259,9 @@ After the above steps are completed, you can use adb to push the file to the pho cd /data/local/tmp/debug export LD_LIBRARY_PATH=${PWD}:$LD_LIBRARY_PATH # The use of ocr_db_crnn is: - # ./ocr_db_crnn Detection model file Orientation classifier model file Recognition model file Test image path Dictionary file path - ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_opt.nb ./11.jpg ppocr_keys_v1.txt + # ./ocr_db_crnn Detection model file Orientation classifier model file Recognition model file Hardware Precision Threads Batchsize Test image path Dictionary file path + ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True +# precision can be INT8 for quantitative model or FP32 for normal model. ``` If you modify the code, you need to recompile and push to the phone. @@ -283,3 +285,7 @@ A2: Replace the .jpg test image under ./debug with the image you want to test, a Q3: How to package it into the mobile APP? A3: This demo aims to provide the core algorithm part that can run OCR on mobile phones. Further, PaddleOCR/deploy/android_demo is an example of encapsulating this demo into a mobile app for reference. + +Q4: When running the demo, an error is reported `Error: This model is not supported, because kernel for 'io_copy' is not supported by Paddle-Lite.` + +A4: The problem is that the installed paddlelite version does not match the downloaded prediction library version. Make sure that the paddleliteopt tool matches your prediction library version, and try to switch to the nb model again. diff --git a/deploy/lite/readme_ch.md b/deploy/lite/readme_ch.md index 99a543d0d6..e238b4ec53 100644 --- a/deploy/lite/readme_ch.md +++ b/deploy/lite/readme_ch.md @@ -8,7 +8,7 @@ - [2.1 模型优化](#21-模型优化) - [2.2 与手机联调](#22-与手机联调) - [FAQ](#faq) - + 本教程将介绍基于[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 在移动端部署PaddleOCR超轻量中文检测、识别模型的详细步骤。 @@ -32,7 +32,7 @@ Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理 ### 1.2 准备预测库 预测库有两种获取方式: -- 1. 直接下载,预测库下载链接如下: +- 1. [推荐]直接下载,预测库下载链接如下: | 平台 | 预测库下载链接 | |---|---| @@ -41,7 +41,9 @@ Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理 注:1. 上述预测库为PaddleLite 2.10分支编译得到,有关PaddleLite 2.10 详细信息可参考 [链接](https://github.com/PaddlePaddle/Paddle-Lite/releases/tag/v2.10) 。 -- 2. [推荐]编译Paddle-Lite得到预测库,Paddle-Lite的编译方式如下: +**注:建议使用paddlelite>=2.10版本的预测库,其他预测库版本[下载链接](https://github.com/PaddlePaddle/Paddle-Lite/tags)** + +- 2. 编译Paddle-Lite得到预测库,Paddle-Lite的编译方式如下: ``` git clone https://github.com/PaddlePaddle/Paddle-Lite.git cd Paddle-Lite @@ -102,22 +104,16 @@ Paddle-Lite 提供了多种策略来自动优化原始的模型,其中包括 如果要部署的模型不在上述表格中,则需要按照如下步骤获得优化后的模型。 -模型优化需要Paddle-Lite的opt可执行文件,可以通过编译Paddle-Lite源码获得,编译步骤如下: +- 步骤1:参考[文档](https://www.paddlepaddle.org.cn/lite/v2.10/user_guides/opt/opt_python.html)安装paddlelite,用于转换paddle inference model为paddlelite运行所需的nb模型 ``` -# 如果准备环境时已经clone了Paddle-Lite,则不用重新clone Paddle-Lite -git clone https://github.com/PaddlePaddle/Paddle-Lite.git -cd Paddle-Lite -git checkout release/v2.10 -# 启动编译 -./lite/tools/build.sh build_optimize_tool +pip install paddlelite==2.10 # paddlelite版本要与预测库版本一致 ``` - -编译完成后,opt文件位于`build.opt/lite/api/`下,可通过如下方式查看opt的运行选项和使用方式; +安装完后,如下指令可以查看帮助信息 ``` -cd build.opt/lite/api/ -./opt +paddle_lite_opt ``` +paddle_lite_opt 参数介绍: |选项|说明| |---|---| |--model_dir|待优化的PaddlePaddle模型(非combined形式)的路径| @@ -130,6 +126,8 @@ cd build.opt/lite/api/ `--model_dir`适用于待优化的模型是非combined方式,PaddleOCR的inference模型是combined方式,即模型结构和模型参数使用单独一个文件存储。 +- 步骤2:使用paddle_lite_opt将inference模型转换成移动端模型格式。 + 下面以PaddleOCR的超轻量中文模型为例,介绍使用编译好的opt文件完成inference模型到Paddle-Lite优化模型的转换。 ``` @@ -148,7 +146,7 @@ wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_cls 转换成功后,inference模型目录下会多出`.nb`结尾的文件,即是转换成功的模型文件。 -注意:使用paddle-lite部署时,需要使用opt工具优化后的模型。 opt 工具的输入模型是paddle保存的inference模型 +注意:使用paddle-lite部署时,需要使用opt工具优化后的模型。 opt工具的输入模型是paddle保存的inference模型 ### 2.2 与手机联调 @@ -234,13 +232,14 @@ ppocr_keys_v1.txt # 中文字典 ... ``` -2. `config.txt` 包含了检测器、分类器的超参数,如下: +2. `config.txt` 包含了检测器、分类器、识别器的超参数,如下: ``` max_side_len 960 # 输入图像长宽大于960时,等比例缩放图像,使得图像最长边为960 det_db_thresh 0.3 # 用于过滤DB预测的二值化图像,设置为0.-0.3对结果影响不明显 -det_db_box_thresh 0.5 # DB后处理过滤box的阈值,如果检测存在漏框情况,可酌情减小 +det_db_box_thresh 0.5 # 检测器后处理过滤box的阈值,如果检测存在漏框情况,可酌情减小 det_db_unclip_ratio 1.6 # 表示文本框的紧致程度,越小则文本框更靠近文本 use_direction_classify 0 # 是否使用方向分类器,0表示不使用,1表示使用 +rec_image_height 32 # 识别模型输入图像的高度,PP-OCRv3模型设置为48,PP-OCRv2模型需要设置为32 ``` 5. 启动调试 @@ -259,8 +258,8 @@ use_direction_classify 0 # 是否使用方向分类器,0表示不使用,1 cd /data/local/tmp/debug export LD_LIBRARY_PATH=${PWD}:$LD_LIBRARY_PATH # 开始使用,ocr_db_crnn可执行文件的使用方式为: - # ./ocr_db_crnn 检测模型文件 方向分类器模型文件 识别模型文件 测试图像路径 字典文件路径 - ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb ./11.jpg ppocr_keys_v1.txt + # ./ocr_db_crnn 检测模型文件 方向分类器模型文件 识别模型文件 运行硬件 运行精度 线程数 batchsize 测试图像路径 参数配置路径 字典文件路径 是否使用benchmark参数 + ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True ``` 如果对代码做了修改,则需要重新编译并push到手机上。 @@ -284,3 +283,7 @@ A2:替换debug下的.jpg测试图像为你想要测试的图像,adb push 到 Q3:如何封装到手机APP中? A3:此demo旨在提供能在手机上运行OCR的核心算法部分,PaddleOCR/deploy/android_demo是将这个demo封装到手机app的示例,供参考 + +Q4:运行demo时遇到报错`Error: This model is not supported, because kernel for 'io_copy' is not supported by Paddle-Lite.` + +A4:问题是安装的paddlelite版本和下载的预测库版本不匹配,确保paddleliteopt工具和你的预测库版本匹配,重新转nb模型试试。 From d56c0b9b7cea28bca25b5b8720c5eff9453178a3 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Mon, 27 Jun 2022 19:47:07 +0800 Subject: [PATCH 121/129] add mode --- deploy/lite/readme.md | 10 ++++++++-- deploy/lite/readme_ch.md | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/deploy/lite/readme.md b/deploy/lite/readme.md index 883aff9890..a1bef8120e 100644 --- a/deploy/lite/readme.md +++ b/deploy/lite/readme.md @@ -259,9 +259,15 @@ After the above steps are completed, you can use adb to push the file to the pho cd /data/local/tmp/debug export LD_LIBRARY_PATH=${PWD}:$LD_LIBRARY_PATH # The use of ocr_db_crnn is: - # ./ocr_db_crnn Detection model file Orientation classifier model file Recognition model file Hardware Precision Threads Batchsize Test image path Dictionary file path - ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True + # ./ocr_db_crnn Mode Detection model file Orientation classifier model file Recognition model file Hardware Precision Threads Batchsize Test image path Dictionary file path + ./ocr_db_crnn system ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True # precision can be INT8 for quantitative model or FP32 for normal model. + +# Only using detection model +./ocr_db_crnn det ch_PP-OCRv2_det_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt + +# Only using recognition model +./ocr_db_crnn rec ch_PP-OCRv2_rec_slim_opt.nb arm8 INT8 10 1 word_1.jpg ppocr_keys_v1.txt config.txt ``` If you modify the code, you need to recompile and push to the phone. diff --git a/deploy/lite/readme_ch.md b/deploy/lite/readme_ch.md index e238b4ec53..0793827fe6 100644 --- a/deploy/lite/readme_ch.md +++ b/deploy/lite/readme_ch.md @@ -258,8 +258,14 @@ rec_image_height 32 # 识别模型输入图像的高度,PP-OCRv3模型 cd /data/local/tmp/debug export LD_LIBRARY_PATH=${PWD}:$LD_LIBRARY_PATH # 开始使用,ocr_db_crnn可执行文件的使用方式为: - # ./ocr_db_crnn 检测模型文件 方向分类器模型文件 识别模型文件 运行硬件 运行精度 线程数 batchsize 测试图像路径 参数配置路径 字典文件路径 是否使用benchmark参数 - ./ocr_db_crnn ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True + # ./ocr_db_crnn 预测模式 检测模型文件 方向分类器模型文件 识别模型文件 运行硬件 运行精度 线程数 batchsize 测试图像路径 参数配置路径 字典文件路径 是否使用benchmark参数 + ./ocr_db_crnn system ch_PP-OCRv2_det_slim_opt.nb ch_PP-OCRv2_rec_slim_opt.nb ch_ppocr_mobile_v2.0_cls_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt ppocr_keys_v1.txt True + +# 仅使用文本检测模型,使用方式如下: +./ocr_db_crnn det ch_PP-OCRv2_det_slim_opt.nb arm8 INT8 10 1 ./11.jpg config.txt + +# 仅使用文本识别模型,使用方式如下: +./ocr_db_crnn rec ch_PP-OCRv2_rec_slim_opt.nb arm8 INT8 10 1 word_1.jpg ppocr_keys_v1.txt config.txt ``` 如果对代码做了修改,则需要重新编译并push到手机上。 From adeb8a17c9f67f99f4ed6021a3b50e3b0d6f02e3 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 28 Jun 2022 02:17:53 +0000 Subject: [PATCH 122/129] fix amp vqa --- tools/program.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tools/program.py b/tools/program.py index aa0d2698cf..9a90eda2f8 100755 --- a/tools/program.py +++ b/tools/program.py @@ -255,6 +255,8 @@ def train(config, with paddle.amp.auto_cast(): if model_type == 'table' or extra_input: preds = model(images, data=batch[1:]) + elif model_type in ["kie", 'vqa']: + preds = model(batch) else: preds = model(images) else: @@ -307,7 +309,8 @@ def train(config, train_stats.update(stats) if log_writer is not None and dist.get_rank() == 0: - log_writer.log_metrics(metrics=train_stats.get(), prefix="TRAIN", step=global_step) + log_writer.log_metrics( + metrics=train_stats.get(), prefix="TRAIN", step=global_step) if dist.get_rank() == 0 and ( (global_step > 0 and global_step % print_batch_step == 0) or @@ -354,7 +357,8 @@ def train(config, # logger metric if log_writer is not None: - log_writer.log_metrics(metrics=cur_metric, prefix="EVAL", step=global_step) + log_writer.log_metrics( + metrics=cur_metric, prefix="EVAL", step=global_step) if cur_metric[main_indicator] >= best_model_dict[ main_indicator]: @@ -377,11 +381,18 @@ def train(config, logger.info(best_str) # logger best metric if log_writer is not None: - log_writer.log_metrics(metrics={ - "best_{}".format(main_indicator): best_model_dict[main_indicator] - }, prefix="EVAL", step=global_step) - - log_writer.log_model(is_best=True, prefix="best_accuracy", metadata=best_model_dict) + log_writer.log_metrics( + metrics={ + "best_{}".format(main_indicator): + best_model_dict[main_indicator] + }, + prefix="EVAL", + step=global_step) + + log_writer.log_model( + is_best=True, + prefix="best_accuracy", + metadata=best_model_dict) reader_start = time.time() if dist.get_rank() == 0: @@ -413,7 +424,8 @@ def train(config, epoch=epoch, global_step=global_step) if log_writer is not None: - log_writer.log_model(is_best=False, prefix='iter_epoch_{}'.format(epoch)) + log_writer.log_model( + is_best=False, prefix='iter_epoch_{}'.format(epoch)) best_str = 'best metric, {}'.format(', '.join( ['{}: {}'.format(k, v) for k, v in best_model_dict.items()])) @@ -585,7 +597,8 @@ def preprocess(is_train=False): vdl_writer_path = '{}/vdl/'.format(save_model_dir) log_writer = VDLLogger(save_model_dir) loggers.append(log_writer) - if ('use_wandb' in config['Global'] and config['Global']['use_wandb']) or 'wandb' in config: + if ('use_wandb' in config['Global'] and + config['Global']['use_wandb']) or 'wandb' in config: save_dir = config['Global']['save_model_dir'] wandb_writer_path = "{}/wandb".format(save_dir) if "wandb" in config: From 671415bbd878bd6d4bc392b22b7a61afa9e6048b Mon Sep 17 00:00:00 2001 From: topduke <784990967@qq.com> Date: Tue, 28 Jun 2022 15:06:53 +0800 Subject: [PATCH 123/129] [New Rec]add rec ViTSTR & ABINet algorithm. (#6414) * add rec vitstr algorithm. * fix cpu_thread and precision * fix svtr tipc * modify vitstr name * modify vitstr config batchsize * [New Rec] add vitstr and ABINet * add rec_resnet45 * svtr ch large model * [application] svtr ch model * [application] svtr ch model * [application] svtr ch model * add abinet_rec_aug and trained model * aug p infe * fix ci export bug * fix abinet ci bug --- applications/高精度中文识别模型.md | 107 ++++ configs/rec/rec_mtb_nrtr.yml | 16 +- configs/rec/rec_r45_abinet.yml | 101 ++++ configs/rec/rec_svtrnet.yml | 12 +- configs/rec/rec_svtrnet_ch.yml | 155 ++++++ configs/rec/rec_vitstr_none_ce.yml | 102 ++++ doc/doc_ch/algorithm_overview.md | 5 +- doc/doc_ch/algorithm_rec_abinet.md | 155 ++++++ doc/doc_ch/algorithm_rec_nrtr.md | 140 ++++- doc/doc_ch/algorithm_rec_svtr.md | 1 - doc/doc_ch/algorithm_rec_vitstr.md | 154 ++++++ doc/doc_en/algorithm_overview_en.md | 5 +- doc/doc_en/algorithm_rec_abinet_en.md | 136 +++++ doc/doc_en/algorithm_rec_nrtr_en.md | 141 ++++- doc/doc_en/algorithm_rec_svtr_en.md | 1 - doc/doc_en/algorithm_rec_vitstr_en.md | 134 +++++ ppocr/data/imaug/__init__.py | 6 +- ppocr/data/imaug/abinet_aug.py | 407 +++++++++++++++ ppocr/data/imaug/label_ops.py | 127 +++-- ppocr/data/imaug/operators.py | 33 -- ppocr/data/imaug/rec_img_aug.py | 170 ++++-- ppocr/losses/__init__.py | 4 +- ppocr/losses/rec_ce_loss.py | 66 +++ ppocr/losses/rec_nrtr_loss.py | 30 -- ppocr/modeling/backbones/__init__.py | 18 +- ppocr/modeling/backbones/rec_resnet_45.py | 147 ++++++ ppocr/modeling/backbones/rec_svtrnet.py | 102 ++-- ppocr/modeling/backbones/rec_vitstr.py | 120 +++++ ppocr/modeling/heads/__init__.py | 3 +- ppocr/modeling/heads/multiheadAttention.py | 163 ------ ppocr/modeling/heads/rec_abinet_head.py | 296 +++++++++++ ppocr/modeling/heads/rec_nrtr_head.py | 489 ++++++------------ ppocr/postprocess/__init__.py | 4 +- ppocr/postprocess/rec_postprocess.py | 183 ++++--- .../configs/rec_mtb_nrtr/rec_mtb_nrtr.yml | 8 +- .../configs/rec_r45_abinet/rec_r45_abinet.yml | 106 ++++ .../rec_r45_abinet/train_infer_python.txt | 53 ++ test_tipc/configs/rec_svtrnet/rec_svtrnet.yml | 117 +++++ .../rec_svtrnet/train_infer_python.txt | 53 ++ .../rec_vitstr_none_ce/rec_vitstr_none_ce.yml | 104 ++++ .../rec_vitstr_none_ce/train_infer_python.txt | 53 ++ tools/export_model.py | 40 +- tools/infer/predict_rec.py | 70 ++- tools/program.py | 3 +- 44 files changed, 3550 insertions(+), 790 deletions(-) create mode 100644 applications/高精度中文识别模型.md create mode 100644 configs/rec/rec_r45_abinet.yml create mode 100644 configs/rec/rec_svtrnet_ch.yml create mode 100644 configs/rec/rec_vitstr_none_ce.yml create mode 100644 doc/doc_ch/algorithm_rec_abinet.md create mode 100644 doc/doc_ch/algorithm_rec_vitstr.md create mode 100644 doc/doc_en/algorithm_rec_abinet_en.md create mode 100644 doc/doc_en/algorithm_rec_vitstr_en.md create mode 100644 ppocr/data/imaug/abinet_aug.py create mode 100644 ppocr/losses/rec_ce_loss.py delete mode 100644 ppocr/losses/rec_nrtr_loss.py create mode 100644 ppocr/modeling/backbones/rec_resnet_45.py create mode 100644 ppocr/modeling/backbones/rec_vitstr.py delete mode 100755 ppocr/modeling/heads/multiheadAttention.py create mode 100644 ppocr/modeling/heads/rec_abinet_head.py create mode 100644 test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml create mode 100644 test_tipc/configs/rec_r45_abinet/train_infer_python.txt create mode 100644 test_tipc/configs/rec_svtrnet/rec_svtrnet.yml create mode 100644 test_tipc/configs/rec_svtrnet/train_infer_python.txt create mode 100644 test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml create mode 100644 test_tipc/configs/rec_vitstr_none_ce/train_infer_python.txt diff --git a/applications/高精度中文识别模型.md b/applications/高精度中文识别模型.md new file mode 100644 index 0000000000..3c31af42ee --- /dev/null +++ b/applications/高精度中文识别模型.md @@ -0,0 +1,107 @@ +# 高精度中文场景文本识别模型SVTR + +## 1. 简介 + +PP-OCRv3是百度开源的超轻量级场景文本检测识别模型库,其中超轻量的场景中文识别模型SVTR_LCNet使用了SVTR算法结构。为了保证速度,SVTR_LCNet将SVTR模型的Local Blocks替换为LCNet,使用两层Global Blocks。在中文场景中,PP-OCRv3识别主要使用如下优化策略: +- GTC:Attention指导CTC训练策略; +- TextConAug:挖掘文字上下文信息的数据增广策略; +- TextRotNet:自监督的预训练模型; +- UDML:联合互学习策略; +- UIM:无标注数据挖掘方案。 + +其中 *UIM:无标注数据挖掘方案* 使用了高精度的SVTR中文模型进行无标注文件的刷库,该模型在PP-OCRv3识别的数据集上训练,精度对比如下表。 + +|中文识别算法|模型|UIM|精度| +| --- | --- | --- |--- | +|PP-OCRv3|SVTR_LCNet| w/o |78.4%| +|PP-OCRv3|SVTR_LCNet| w |79.4%| +|SVTR|SVTR-Tiny|-|82.5%| + +aistudio项目链接: [高精度中文场景文本识别模型SVTR](https://aistudio.baidu.com/aistudio/projectdetail/4263032) + +## 2. SVTR中文模型使用 + +### 环境准备 + + +本任务基于Aistudio完成, 具体环境如下: + +- 操作系统: Linux +- PaddlePaddle: 2.3 +- PaddleOCR: dygraph + +下载 PaddleOCR代码 + +```bash +git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR +``` + +安装依赖库 + +```bash +pip install -r PaddleOCR/requirements.txt -i https://mirror.baidu.com/pypi/simple +``` + +### 快速使用 + +获取SVTR中文模型文件,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 +
+ +
+ +```bash +# 解压模型文件 +tar xf svtr_ch_high_accuracy.tar +``` + +预测中文文本,以下图为例: +![](../doc/imgs_words/ch/word_1.jpg) + +预测命令: + +```bash +# CPU预测 +python tools/infer_rec.py -c configs/rec/rec_svtrnet_ch.yml -o Global.pretrained_model=./svtr_ch_high_accuracy/best_accuracy Global.infer_img=./doc/imgs_words/ch/word_1.jpg Global.use_gpu=False + +# GPU预测 +#python tools/infer_rec.py -c configs/rec/rec_svtrnet_ch.yml -o Global.pretrained_model=./svtr_ch_high_accuracy/best_accuracy Global.infer_img=./doc/imgs_words/ch/word_1.jpg Global.use_gpu=True +``` + +可以看到最后打印结果为 +- result: 韩国小馆 0.9853458404541016 + +0.9853458404541016为预测置信度。 + +### 推理模型导出与预测 + +inference 模型(paddle.jit.save保存的模型) 一般是模型训练,把模型结构和模型参数保存在文件中的固化模型,多用于预测部署场景。 训练过程中保存的模型是checkpoints模型,保存的只有模型的参数,多用于恢复训练等。 与checkpoints模型相比,inference 模型会额外保存模型的结构信息,在预测部署、加速推理上性能优越,灵活方便,适合于实际系统集成。 + +运行识别模型转inference模型命令,如下: + +```bash +python tools/export_model.py -c configs/rec/rec_svtrnet_ch.yml -o Global.pretrained_model=./svtr_ch_high_accuracy/best_accuracy Global.save_inference_dir=./inference/svtr_ch +``` + +转换成功后,在目录下有三个文件: +```shell +inference/svtr_ch/ + ├── inference.pdiparams # 识别inference模型的参数文件 + ├── inference.pdiparams.info # 识别inference模型的参数信息,可忽略 + └── inference.pdmodel # 识别inference模型的program文件 +``` + +inference模型预测,命令如下: + +```bash +# CPU预测 +python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/ch/word_1.jpg" --rec_algorithm='SVTR' --rec_model_dir=./inference/svtr_ch/ --rec_image_shape='3, 32, 320' --rec_char_dict_path=ppocr/utils/ppocr_keys_v1.txt --use_gpu=False + +# GPU预测 +#python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/ch/word_1.jpg" --rec_algorithm='SVTR' --rec_model_dir=./inference/svtr_ch/ --rec_image_shape='3, 32, 320' --rec_char_dict_path=ppocr/utils/ppocr_keys_v1.txt --use_gpu=True +``` + +**注意** + +- 使用SVTR算法时,需要指定--rec_algorithm='SVTR' +- 如果使用自定义字典训练的模型,需要将--rec_char_dict_path=ppocr/utils/ppocr_keys_v1.txt修改为自定义的字典 +- --rec_image_shape='3, 32, 320' 该参数不能去掉 diff --git a/configs/rec/rec_mtb_nrtr.yml b/configs/rec/rec_mtb_nrtr.yml index 0426750085..4e5826adc9 100644 --- a/configs/rec/rec_mtb_nrtr.yml +++ b/configs/rec/rec_mtb_nrtr.yml @@ -9,7 +9,7 @@ Global: eval_batch_step: [0, 2000] cal_metric_during_train: True pretrained_model: - checkpoints: + checkpoints: save_inference_dir: use_visualdl: False infer_img: doc/imgs_words_en/word_10.png @@ -49,7 +49,7 @@ Architecture: Loss: - name: NRTRLoss + name: CELoss smoothing: True PostProcess: @@ -68,8 +68,8 @@ Train: img_mode: BGR channel_first: False - NRTRLabelEncode: # Class handling label - - NRTRRecResizeImg: - image_shape: [100, 32] + - GrayRecResizeImg: + image_shape: [100, 32] # W H resize_type: PIL # PIL or OpenCV - KeepKeys: keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order @@ -82,14 +82,14 @@ Train: Eval: dataset: name: LMDBDataSet - data_dir: ./train_data/data_lmdb_release/evaluation/ + data_dir: ./train_data/data_lmdb_release/validation/ transforms: - DecodeImage: # load image img_mode: BGR channel_first: False - NRTRLabelEncode: # Class handling label - - NRTRRecResizeImg: - image_shape: [100, 32] + - GrayRecResizeImg: + image_shape: [100, 32] # W H resize_type: PIL # PIL or OpenCV - KeepKeys: keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order @@ -97,5 +97,5 @@ Eval: shuffle: False drop_last: False batch_size_per_card: 256 - num_workers: 1 + num_workers: 4 use_shared_memory: False diff --git a/configs/rec/rec_r45_abinet.yml b/configs/rec/rec_r45_abinet.yml new file mode 100644 index 0000000000..e604bcd12d --- /dev/null +++ b/configs/rec/rec_r45_abinet.yml @@ -0,0 +1,101 @@ +Global: + use_gpu: True + epoch_num: 10 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/r45_abinet/ + save_epoch_step: 1 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: + character_type: en + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_abinet.txt + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.99 + clip_norm: 20.0 + lr: + name: Piecewise + decay_epochs: [6] + values: [0.0001, 0.00001] + regularizer: + name: 'L2' + factor: 0. + +Architecture: + model_type: rec + algorithm: ABINet + in_channels: 3 + Transform: + Backbone: + name: ResNet45 + Head: + name: ABINetHead + use_lang: True + iter_size: 3 + + +Loss: + name: CELoss + ignore_index: &ignore_index 100 # Must be greater than the number of character classes + +PostProcess: + name: ABINetLabelDecode + +Metric: + name: RecMetric + main_indicator: acc + +Train: + dataset: + name: LMDBDataSet + data_dir: ./train_data/data_lmdb_release/training/ + transforms: + - DecodeImage: # load image + img_mode: RGB + channel_first: False + - ABINetRecAug: + - ABINetLabelEncode: # Class handling label + ignore_index: *ignore_index + - ABINetRecResizeImg: + image_shape: [3, 32, 128] + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 96 + drop_last: True + num_workers: 4 + +Eval: + dataset: + name: LMDBDataSet + data_dir: ./train_data/data_lmdb_release/validation/ + transforms: + - DecodeImage: # load image + img_mode: RGB + channel_first: False + - ABINetLabelEncode: # Class handling label + ignore_index: *ignore_index + - ABINetRecResizeImg: + image_shape: [3, 32, 128] + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 256 + num_workers: 4 + use_shared_memory: False diff --git a/configs/rec/rec_svtrnet.yml b/configs/rec/rec_svtrnet.yml index 233d5e2765..c1f5cc380a 100644 --- a/configs/rec/rec_svtrnet.yml +++ b/configs/rec/rec_svtrnet.yml @@ -26,7 +26,7 @@ Optimizer: name: AdamW beta1: 0.9 beta2: 0.99 - epsilon: 0.00000008 + epsilon: 8.e-8 weight_decay: 0.05 no_weight_decay_name: norm pos_embed one_dim_param_no_weight_decay: true @@ -77,14 +77,13 @@ Metric: Train: dataset: name: LMDBDataSet - data_dir: ./train_data/data_lmdb_release/training/ + data_dir: ./train_data/data_lmdb_release/training transforms: - DecodeImage: # load image img_mode: BGR channel_first: False - CTCLabelEncode: # Class handling label - - RecResizeImg: - character_dict_path: + - SVTRRecResizeImg: image_shape: [3, 64, 256] padding: False - KeepKeys: @@ -98,14 +97,13 @@ Train: Eval: dataset: name: LMDBDataSet - data_dir: ./train_data/data_lmdb_release/validation/ + data_dir: ./train_data/data_lmdb_release/validation transforms: - DecodeImage: # load image img_mode: BGR channel_first: False - CTCLabelEncode: # Class handling label - - RecResizeImg: - character_dict_path: + - SVTRRecResizeImg: image_shape: [3, 64, 256] padding: False - KeepKeys: diff --git a/configs/rec/rec_svtrnet_ch.yml b/configs/rec/rec_svtrnet_ch.yml new file mode 100644 index 0000000000..0d3f63d125 --- /dev/null +++ b/configs/rec/rec_svtrnet_ch.yml @@ -0,0 +1,155 @@ +Global: + use_gpu: true + epoch_num: 100 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/svtr_ch_all/ + save_epoch_step: 10 + eval_batch_step: + - 0 + - 2000 + cal_metric_during_train: true + pretrained_model: null + checkpoints: null + save_inference_dir: null + use_visualdl: false + infer_img: doc/imgs_words/ch/word_1.jpg + character_dict_path: ppocr/utils/ppocr_keys_v1.txt + max_text_length: 25 + infer_mode: false + use_space_char: true + save_res_path: ./output/rec/predicts_svtr_tiny_ch_all.txt +Optimizer: + name: AdamW + beta1: 0.9 + beta2: 0.99 + epsilon: 8.0e-08 + weight_decay: 0.05 + no_weight_decay_name: norm pos_embed + one_dim_param_no_weight_decay: true + lr: + name: Cosine + learning_rate: 0.0005 + warmup_epoch: 2 +Architecture: + model_type: rec + algorithm: SVTR + Transform: null + Backbone: + name: SVTRNet + img_size: + - 32 + - 320 + out_char_num: 40 + out_channels: 96 + patch_merging: Conv + embed_dim: + - 64 + - 128 + - 256 + depth: + - 3 + - 6 + - 3 + num_heads: + - 2 + - 4 + - 8 + mixer: + - Local + - Local + - Local + - Local + - Local + - Local + - Global + - Global + - Global + - Global + - Global + - Global + local_mixer: + - - 7 + - 11 + - - 7 + - 11 + - - 7 + - 11 + last_stage: true + prenorm: false + Neck: + name: SequenceEncoder + encoder_type: reshape + Head: + name: CTCHead +Loss: + name: CTCLoss +PostProcess: + name: CTCLabelDecode +Metric: + name: RecMetric + main_indicator: acc +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data + label_file_list: + - ./train_data/train_list.txt + ext_op_transform_idx: 1 + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - RecConAug: + prob: 0.5 + ext_data_num: 2 + image_shape: + - 32 + - 320 + - 3 + - RecAug: null + - CTCLabelEncode: null + - SVTRRecResizeImg: + image_shape: + - 3 + - 32 + - 320 + padding: true + - KeepKeys: + keep_keys: + - image + - label + - length + loader: + shuffle: true + batch_size_per_card: 256 + drop_last: true + num_workers: 8 +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data + label_file_list: + - ./train_data/val_list.txt + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - CTCLabelEncode: null + - SVTRRecResizeImg: + image_shape: + - 3 + - 32 + - 320 + padding: true + - KeepKeys: + keep_keys: + - image + - label + - length + loader: + shuffle: false + drop_last: false + batch_size_per_card: 256 + num_workers: 2 +profiler_options: null diff --git a/configs/rec/rec_vitstr_none_ce.yml b/configs/rec/rec_vitstr_none_ce.yml new file mode 100644 index 0000000000..b969c83a5d --- /dev/null +++ b/configs/rec/rec_vitstr_none_ce.yml @@ -0,0 +1,102 @@ +Global: + use_gpu: True + epoch_num: 20 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/vitstr_none_ce/ + save_epoch_step: 1 + # evaluation is run every 2000 iterations after the 0th iteration# + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: ppocr/utils/EN_symbol_dict.txt + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_vitstr.txt + + +Optimizer: + name: Adadelta + epsilon: 1.e-8 + rho: 0.95 + clip_norm: 5.0 + lr: + learning_rate: 1.0 + +Architecture: + model_type: rec + algorithm: ViTSTR + in_channels: 1 + Transform: + Backbone: + name: ViTSTR + scale: tiny + Neck: + name: SequenceEncoder + encoder_type: reshape + Head: + name: CTCHead + +Loss: + name: CELoss + with_all: True + ignore_index: &ignore_index 0 # Must be zero or greater than the number of character classes + +PostProcess: + name: ViTSTRLabelDecode + +Metric: + name: RecMetric + main_indicator: acc + +Train: + dataset: + name: LMDBDataSet + data_dir: ./train_data/data_lmdb_release/training/ + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ViTSTRLabelEncode: # Class handling label + ignore_index: *ignore_index + - GrayRecResizeImg: + image_shape: [224, 224] # W H + resize_type: PIL # PIL or OpenCV + inter_type: 'Image.BICUBIC' + scale: false + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 48 + drop_last: True + num_workers: 8 + +Eval: + dataset: + name: LMDBDataSet + data_dir: ./train_data/data_lmdb_release/validation/ + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ViTSTRLabelEncode: # Class handling label + ignore_index: *ignore_index + - GrayRecResizeImg: + image_shape: [224, 224] # W H + resize_type: PIL # PIL or OpenCV + inter_type: 'Image.BICUBIC' + scale: false + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 256 + num_workers: 2 diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md index 6227a21498..eb81e4cd6d 100755 --- a/doc/doc_ch/algorithm_overview.md +++ b/doc/doc_ch/algorithm_overview.md @@ -66,6 +66,8 @@ - [x] [SAR](./algorithm_rec_sar.md) - [x] [SEED](./algorithm_rec_seed.md) - [x] [SVTR](./algorithm_rec_svtr.md) +- [x] [ViTSTR](./algorithm_rec_vitstr.md) +- [x] [ABINet](./algorithm_rec_abinet.md) 参考[DTRB](https://arxiv.org/abs/1904.01906)[3]文字识别训练和评估流程,使用MJSynth和SynthText两个文字识别数据集训练,在IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE数据集上进行评估,算法效果如下: @@ -84,7 +86,8 @@ |SAR|Resnet31| 87.20% | rec_r31_sar | [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_r31_sar_train.tar) | |SEED|Aster_Resnet| 85.35% | rec_resnet_stn_bilstm_att | [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_resnet_stn_bilstm_att.tar) | |SVTR|SVTR-Tiny| 89.25% | rec_svtr_tiny_none_ctc_en | [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/rec_svtr_tiny_none_ctc_en_train.tar) | - +|ViTSTR|ViTSTR| 79.82% | rec_vitstr_none_ce_en | [训练模型](https://paddleocr.bj.bcebos.com/rec_vitstr_none_ce_train.tar) | +|ABINet|Resnet45| 90.75% | rec_r45_abinet_en | [训练模型](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar) | diff --git a/doc/doc_ch/algorithm_rec_abinet.md b/doc/doc_ch/algorithm_rec_abinet.md new file mode 100644 index 0000000000..47507c36c7 --- /dev/null +++ b/doc/doc_ch/algorithm_rec_abinet.md @@ -0,0 +1,155 @@ +# 场景文本识别算法-ABINet + +- [1. 算法简介](#1) +- [2. 环境配置](#2) +- [3. 模型训练、评估、预测](#3) + - [3.1 训练](#3-1) + - [3.2 评估](#3-2) + - [3.3 预测](#3-3) +- [4. 推理部署](#4) + - [4.1 Python推理](#4-1) + - [4.2 C++推理](#4-2) + - [4.3 Serving服务化部署](#4-3) + - [4.4 更多推理部署](#4-4) +- [5. FAQ](#5) + + +## 1. 算法简介 + +论文信息: +> [ABINet: Read Like Humans: Autonomous, Bidirectional and Iterative Language Modeling for Scene Text Recognition](https://openaccess.thecvf.com/content/CVPR2021/papers/Fang_Read_Like_Humans_Autonomous_Bidirectional_and_Iterative_Language_Modeling_for_CVPR_2021_paper.pdf) +> Shancheng Fang and Hongtao Xie and Yuxin Wang and Zhendong Mao and Yongdong Zhang +> CVPR, 2021 + + + +`ABINet`使用MJSynth和SynthText两个文字识别数据集训练,在IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE数据集上进行评估,算法复现效果如下: + +|模型|骨干网络|配置文件|Acc|下载链接| +| --- | --- | --- | --- | --- | +|ABINet|ResNet45|[rec_r45_abinet.yml](../../configs/rec/rec_r45_abinet.yml)|90.75%|[预训练、训练模型](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar)| + + +## 2. 环境配置 +请先参考[《运行环境准备》](./environment.md)配置PaddleOCR运行环境,参考[《项目克隆》](./clone.md)克隆项目代码。 + + + +## 3. 模型训练、评估、预测 + + +### 3.1 模型训练 + +请参考[文本识别训练教程](./recognition.md)。PaddleOCR对代码进行了模块化,训练`ABINet`识别模型时需要**更换配置文件**为`ABINet`的[配置文件](../../configs/rec/rec_r45_abinet.yml)。 + +#### 启动训练 + + +具体地,在完成数据准备后,便可以启动训练,训练命令如下: +```shell +#单卡训练(训练周期长,不建议) +python3 tools/train.py -c configs/rec/rec_r45_abinet.yml + +#多卡训练,通过--gpus参数指定卡号 +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_r45_abinet.yml +``` + + +### 3.2 评估 + +可下载已训练完成的[模型文件](#model),使用如下命令进行评估: + +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_r45_abinet.yml -o Global.pretrained_model=./rec_r45_abinet_train/best_accuracy +``` + + +### 3.3 预测 + +使用如下命令进行单张图片预测: +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 tools/infer_rec.py -c configs/rec/rec_r45_abinet.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./rec_r45_abinet_train/best_accuracy +# 预测文件夹下所有图像时,可修改infer_img为文件夹,如 Global.infer_img='./doc/imgs_words_en/'。 +``` + + + +## 4. 推理部署 + + +### 4.1 Python推理 +首先将训练得到best模型,转换成inference model。这里以训练完成的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar) ),可以使用如下命令进行转换: + +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 tools/export_model.py -c configs/rec/rec_r45_abinet.yml -o Global.pretrained_model=./rec_r45_abinet_train/best_accuracy Global.save_inference_dir=./inference/rec_r45_abinet/ +``` +**注意:** +- 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。 +- 如果您修改了训练时的输入大小,请修改`tools/export_model.py`文件中的对应ABINet的`infer_shape`。 + +转换成功后,在目录下有三个文件: +``` +/inference/rec_r45_abinet/ + ├── inference.pdiparams # 识别inference模型的参数文件 + ├── inference.pdiparams.info # 识别inference模型的参数信息,可忽略 + └── inference.pdmodel # 识别inference模型的program文件 +``` + +执行如下命令进行模型推理: + +```shell +python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' --rec_model_dir='./inference/rec_r45_abinet/' --rec_algorithm='ABINet' --rec_image_shape='3,32,128' --rec_char_dict_path='./ppocr/utils/ic15_dict.txt' +# 预测文件夹下所有图像时,可修改image_dir为文件夹,如 --image_dir='./doc/imgs_words_en/'。 +``` + +![](../imgs_words_en/word_10.png) + +执行命令后,上面图像的预测结果(识别的文本和得分)会打印到屏幕上,示例如下: +结果如下: +```shell +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9999995231628418) +``` + +**注意**: + +- 训练上述模型采用的图像分辨率是[3,32,128],需要通过参数`rec_image_shape`设置为您训练时的识别图像形状。 +- 在推理时需要设置参数`rec_char_dict_path`指定字典,如果您修改了字典,请修改该参数为您的字典文件。 +- 如果您修改了预处理方法,需修改`tools/infer/predict_rec.py`中ABINet的预处理为您的预处理方法。 + + + +### 4.2 C++推理部署 + +由于C++预处理后处理还未支持ABINet,所以暂未支持 + + +### 4.3 Serving服务化部署 + +暂不支持 + + +### 4.4 更多推理部署 + +暂不支持 + + +## 5. FAQ + +1. MJSynth和SynthText两种数据集来自于[ABINet源repo](https://github.com/FangShancheng/ABINet) 。 +2. 我们使用ABINet作者提供的预训练模型进行finetune训练。 + +## 引用 + +```bibtex +@article{Fang2021ABINet, + title = {ABINet: Read Like Humans: Autonomous, Bidirectional and Iterative Language Modeling for Scene Text Recognition}, + author = {Shancheng Fang and Hongtao Xie and Yuxin Wang and Zhendong Mao and Yongdong Zhang}, + booktitle = {CVPR}, + year = {2021}, + url = {https://arxiv.org/abs/2103.06495}, + pages = {7098-7107} +} +``` diff --git a/doc/doc_ch/algorithm_rec_nrtr.md b/doc/doc_ch/algorithm_rec_nrtr.md index d3b626d024..c619ac1dbc 100644 --- a/doc/doc_ch/algorithm_rec_nrtr.md +++ b/doc/doc_ch/algorithm_rec_nrtr.md @@ -12,6 +12,7 @@ - [4.3 Serving服务化部署](#4-3) - [4.4 更多推理部署](#4-4) - [5. FAQ](#5) +- [6. 发行公告](#6) ## 1. 算法简介 @@ -110,7 +111,7 @@ python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' 执行命令后,上面图像的预测结果(识别的文本和得分)会打印到屏幕上,示例如下: 结果如下: ```shell -Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9265879392623901) +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9465042352676392) ``` **注意**: @@ -140,12 +141,147 @@ Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9265879392623901) 1. `NRTR`论文中使用Beam搜索进行解码字符,但是速度较慢,这里默认未使用Beam搜索,以贪婪搜索进行解码字符。 + +## 6. 发行公告 + +1. release/2.6更新NRTR代码结构,新版NRTR可加载旧版(release/2.5及之前)模型参数,使用下面示例代码将旧版模型参数转换为新版模型参数: + +```python + + params = paddle.load('path/' + '.pdparams') # 旧版本参数 + state_dict = model.state_dict() # 新版模型参数 + new_state_dict = {} + + for k1, v1 in state_dict.items(): + + k = k1 + if 'encoder' in k and 'self_attn' in k and 'qkv' in k and 'weight' in k: + + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')].transpose((1, 0, 2, 3)) + k = params[k_para.replace('qkv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('qkv', 'conv3')].transpose((1, 0, 2, 3)) + + new_state_dict[k1] = np.concatenate([q[:, :, 0, 0], k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'encoder' in k and 'self_attn' in k and 'qkv' in k and 'bias' in k: + + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')] + k = params[k_para.replace('qkv', 'conv2')] + v = params[k_para.replace('qkv', 'conv3')] + + new_state_dict[k1] = np.concatenate([q, k, v], -1) + + elif 'encoder' in k and 'self_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + elif 'encoder' in k and 'norm3' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para.replace('norm3', 'norm2')] + + elif 'encoder' in k and 'norm1' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + + elif 'decoder' in k and 'self_attn' in k and 'qkv' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')].transpose((1, 0, 2, 3)) + k = params[k_para.replace('qkv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('qkv', 'conv3')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = np.concatenate([q[:, :, 0, 0], k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'decoder' in k and 'self_attn' in k and 'qkv' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')] + k = params[k_para.replace('qkv', 'conv2')] + v = params[k_para.replace('qkv', 'conv3')] + new_state_dict[k1] = np.concatenate([q, k, v], -1) + + elif 'decoder' in k and 'self_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + elif 'decoder' in k and 'cross_attn' in k and 'q' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + q = params[k_para.replace('q', 'conv1')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = q[:, :, 0, 0] + + elif 'decoder' in k and 'cross_attn' in k and 'q' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + q = params[k_para.replace('q', 'conv1')] + new_state_dict[k1] = q + + elif 'decoder' in k and 'cross_attn' in k and 'kv' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + k = params[k_para.replace('kv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('kv', 'conv3')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = np.concatenate([k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'decoder' in k and 'cross_attn' in k and 'kv' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + k = params[k_para.replace('kv', 'conv2')] + v = params[k_para.replace('kv', 'conv3')] + new_state_dict[k1] = np.concatenate([k, v], -1) + + elif 'decoder' in k and 'cross_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + new_state_dict[k1] = params[k_para] + elif 'decoder' in k and 'norm' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + elif 'mlp' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('fc', 'conv') + k_para = k_para.replace('mlp.', '') + w = params[k_para].transpose((1, 0, 2, 3)) + new_state_dict[k1] = w[:, :, 0, 0] + elif 'mlp' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('fc', 'conv') + k_para = k_para.replace('mlp.', '') + w = params[k_para] + new_state_dict[k1] = w + + else: + new_state_dict[k1] = params[k1] + + if list(new_state_dict[k1].shape) != list(v1.shape): + print(k1) + + + for k, v1 in state_dict.items(): + if k not in new_state_dict.keys(): + print(1, k) + elif list(new_state_dict[k].shape) != list(v1.shape): + print(2, k) + + + + model.set_state_dict(new_state_dict) + paddle.save(model.state_dict(), 'nrtrnew_from_old_params.pdparams') + +``` + +2. 新版相比与旧版,代码结构简洁,推理速度有所提高。 + + ## 引用 ```bibtex @article{Sheng2019NRTR, title = {NRTR: A No-Recurrence Sequence-to-Sequence Model For Scene Text Recognition}, - author = {Fenfen Sheng and Zhineng Chen andBo Xu}, + author = {Fenfen Sheng and Zhineng Chen and Bo Xu}, booktitle = {ICDAR}, year = {2019}, url = {http://arxiv.org/abs/1806.00926}, diff --git a/doc/doc_ch/algorithm_rec_svtr.md b/doc/doc_ch/algorithm_rec_svtr.md index 41a22ca65c..c0e26433e9 100644 --- a/doc/doc_ch/algorithm_rec_svtr.md +++ b/doc/doc_ch/algorithm_rec_svtr.md @@ -111,7 +111,6 @@ python3 tools/export_model.py -c ./rec_svtr_tiny_none_ctc_en_train/rec_svtr_tiny **注意:** - 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否为所正确的字典文件。 -- 如果您修改了训练时的输入大小,请修改`tools/export_model.py`文件中的对应SVTR的`infer_shape`。 转换成功后,在目录下有三个文件: ``` diff --git a/doc/doc_ch/algorithm_rec_vitstr.md b/doc/doc_ch/algorithm_rec_vitstr.md new file mode 100644 index 0000000000..ab12be7202 --- /dev/null +++ b/doc/doc_ch/algorithm_rec_vitstr.md @@ -0,0 +1,154 @@ +# 场景文本识别算法-ViTSTR + +- [1. 算法简介](#1) +- [2. 环境配置](#2) +- [3. 模型训练、评估、预测](#3) + - [3.1 训练](#3-1) + - [3.2 评估](#3-2) + - [3.3 预测](#3-3) +- [4. 推理部署](#4) + - [4.1 Python推理](#4-1) + - [4.2 C++推理](#4-2) + - [4.3 Serving服务化部署](#4-3) + - [4.4 更多推理部署](#4-4) +- [5. FAQ](#5) + + +## 1. 算法简介 + +论文信息: +> [Vision Transformer for Fast and Efficient Scene Text Recognition](https://arxiv.org/abs/2105.08582) +> Rowel Atienza +> ICDAR, 2021 + + + +`ViTSTR`使用MJSynth和SynthText两个文字识别数据集训练,在IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE数据集上进行评估,算法复现效果如下: + +|模型|骨干网络|配置文件|Acc|下载链接| +| --- | --- | --- | --- | --- | +|ViTSTR|ViTSTR|[rec_vitstr_none_ce.yml](../../configs/rec/rec_vitstr_none_ce.yml)|79.82%|[训练模型](https://paddleocr.bj.bcebos.com/rec_vitstr_none_ce_train.tar)| + + +## 2. 环境配置 +请先参考[《运行环境准备》](./environment.md)配置PaddleOCR运行环境,参考[《项目克隆》](./clone.md)克隆项目代码。 + + + +## 3. 模型训练、评估、预测 + + +### 3.1 模型训练 + +请参考[文本识别训练教程](./recognition.md)。PaddleOCR对代码进行了模块化,训练`ViTSTR`识别模型时需要**更换配置文件**为`ViTSTR`的[配置文件](../../configs/rec/rec_vitstr_none_ce.yml)。 + +#### 启动训练 + + +具体地,在完成数据准备后,便可以启动训练,训练命令如下: +```shell +#单卡训练(训练周期长,不建议) +python3 tools/train.py -c configs/rec/rec_vitstr_none_ce.yml + +#多卡训练,通过--gpus参数指定卡号 +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_vitstr_none_ce.yml +``` + + +### 3.2 评估 + +可下载已训练完成的[模型文件](#model),使用如下命令进行评估: + +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.pretrained_model=./rec_vitstr_none_ce_train/best_accuracy +``` + + +### 3.3 预测 + +使用如下命令进行单张图片预测: +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 tools/infer_rec.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./rec_vitstr_none_ce_train/best_accuracy +# 预测文件夹下所有图像时,可修改infer_img为文件夹,如 Global.infer_img='./doc/imgs_words_en/'。 +``` + + + +## 4. 推理部署 + + +### 4.1 Python推理 +首先将训练得到best模型,转换成inference model。这里以训练完成的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/rec_vitstr_none_ce_train.tar) ),可以使用如下命令进行转换: + +```shell +# 注意将pretrained_model的路径设置为本地路径。 +python3 tools/export_model.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.pretrained_model=./rec_vitstr_none_ce_train/best_accuracy Global.save_inference_dir=./inference/rec_vitstr/ +``` +**注意:** +- 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。 +- 如果您修改了训练时的输入大小,请修改`tools/export_model.py`文件中的对应ViTSTR的`infer_shape`。 + +转换成功后,在目录下有三个文件: +``` +/inference/rec_vitstr/ + ├── inference.pdiparams # 识别inference模型的参数文件 + ├── inference.pdiparams.info # 识别inference模型的参数信息,可忽略 + └── inference.pdmodel # 识别inference模型的program文件 +``` + +执行如下命令进行模型推理: + +```shell +python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' --rec_model_dir='./inference/rec_vitstr/' --rec_algorithm='ViTSTR' --rec_image_shape='1,224,224' --rec_char_dict_path='./ppocr/utils/EN_symbol_dict.txt' +# 预测文件夹下所有图像时,可修改image_dir为文件夹,如 --image_dir='./doc/imgs_words_en/'。 +``` + +![](../imgs_words_en/word_10.png) + +执行命令后,上面图像的预测结果(识别的文本和得分)会打印到屏幕上,示例如下: +结果如下: +```shell +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9998350143432617) +``` + +**注意**: + +- 训练上述模型采用的图像分辨率是[1,224,224],需要通过参数`rec_image_shape`设置为您训练时的识别图像形状。 +- 在推理时需要设置参数`rec_char_dict_path`指定字典,如果您修改了字典,请修改该参数为您的字典文件。 +- 如果您修改了预处理方法,需修改`tools/infer/predict_rec.py`中ViTSTR的预处理为您的预处理方法。 + + + +### 4.2 C++推理部署 + +由于C++预处理后处理还未支持ViTSTR,所以暂未支持 + + +### 4.3 Serving服务化部署 + +暂不支持 + + +### 4.4 更多推理部署 + +暂不支持 + + +## 5. FAQ + +1. 在`ViTSTR`论文中,使用在ImageNet1k上的预训练权重进行初始化训练,我们在训练未采用预训练权重,最终精度没有变化甚至有所提高。 +2. 我们仅仅复现了`ViTSTR`中的tiny版本,如果需要使用small、base版本,可将[ViTSTR源repo](https://github.com/roatienza/deep-text-recognition-benchmark) 中的预训练权重转为Paddle权重使用。 + +## 引用 + +```bibtex +@article{Atienza2021ViTSTR, + title = {Vision Transformer for Fast and Efficient Scene Text Recognition}, + author = {Rowel Atienza}, + booktitle = {ICDAR}, + year = {2021}, + url = {https://arxiv.org/abs/2105.08582} +} +``` diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md index 383cbe39bb..28aca7c0d1 100755 --- a/doc/doc_en/algorithm_overview_en.md +++ b/doc/doc_en/algorithm_overview_en.md @@ -65,6 +65,8 @@ Supported text recognition algorithms (Click the link to get the tutorial): - [x] [SAR](./algorithm_rec_sar_en.md) - [x] [SEED](./algorithm_rec_seed_en.md) - [x] [SVTR](./algorithm_rec_svtr_en.md) +- [x] [ViTSTR](./algorithm_rec_vitstr_en.md) +- [x] [ABINet](./algorithm_rec_abinet_en.md) Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation result of these above text recognition (using MJSynth and SynthText for training, evaluate on IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE) is as follow: @@ -83,7 +85,8 @@ Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation r |SAR|Resnet31| 87.20% | rec_r31_sar | [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_r31_sar_train.tar) | |SEED|Aster_Resnet| 85.35% | rec_resnet_stn_bilstm_att | [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_resnet_stn_bilstm_att.tar) | |SVTR|SVTR-Tiny| 89.25% | rec_svtr_tiny_none_ctc_en | [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/rec_svtr_tiny_none_ctc_en_train.tar) | - +|ViTSTR|ViTSTR| 79.82% | rec_vitstr_none_ce_en | [trained model](https://paddleocr.bj.bcebos.com/rec_vitstr_none_none_train.tar) | +|ABINet|Resnet45| 90.75% | rec_r45_abinet_en | [trained model](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar) | diff --git a/doc/doc_en/algorithm_rec_abinet_en.md b/doc/doc_en/algorithm_rec_abinet_en.md new file mode 100644 index 0000000000..767ca65f64 --- /dev/null +++ b/doc/doc_en/algorithm_rec_abinet_en.md @@ -0,0 +1,136 @@ +# ABINet + +- [1. Introduction](#1) +- [2. Environment](#2) +- [3. Model Training / Evaluation / Prediction](#3) + - [3.1 Training](#3-1) + - [3.2 Evaluation](#3-2) + - [3.3 Prediction](#3-3) +- [4. Inference and Deployment](#4) + - [4.1 Python Inference](#4-1) + - [4.2 C++ Inference](#4-2) + - [4.3 Serving](#4-3) + - [4.4 More](#4-4) +- [5. FAQ](#5) + + +## 1. Introduction + +Paper: +> [ABINet: Read Like Humans: Autonomous, Bidirectional and Iterative Language Modeling for Scene Text Recognition](https://openaccess.thecvf.com/content/CVPR2021/papers/Fang_Read_Like_Humans_Autonomous_Bidirectional_and_Iterative_Language_Modeling_for_CVPR_2021_paper.pdf) +> Shancheng Fang and Hongtao Xie and Yuxin Wang and Zhendong Mao and Yongdong Zhang +> CVPR, 2021 + +Using MJSynth and SynthText two text recognition datasets for training, and evaluating on IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE datasets, the algorithm reproduction effect is as follows: + +|Model|Backbone|config|Acc|Download link| +| --- | --- | --- | --- | --- | +|ABINet|ResNet45|[rec_r45_abinet.yml](../../configs/rec/rec_r45_abinet.yml)|90.75%|[pretrained & trained model](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar)| + + +## 2. Environment +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. + + + +## 3. Model Training / Evaluation / Prediction + +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. + +Training: + +Specifically, after the data preparation is completed, the training can be started. The training command is as follows: + +``` +#Single GPU training (long training period, not recommended) +python3 tools/train.py -c configs/rec/rec_r45_abinet.yml + +#Multi GPU training, specify the gpu number through the --gpus parameter +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_r45_abinet.yml +``` + +Evaluation: + +``` +# GPU evaluation +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_r45_abinet.yml -o Global.pretrained_model={path/to/weights}/best_accuracy +``` + +Prediction: + +``` +# The configuration file used for prediction must match the training +python3 tools/infer_rec.py -c configs/rec/rec_r45_abinet.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./rec_r45_abinet_train/best_accuracy +``` + + +## 4. Inference and Deployment + + +### 4.1 Python Inference +First, the model saved during the ABINet text recognition training process is converted into an inference model. ( [Model download link](https://paddleocr.bj.bcebos.com/rec_r45_abinet_train.tar)) ), you can use the following command to convert: + +``` +python3 tools/export_model.py -c configs/rec/rec_r45_abinet.yml -o Global.pretrained_model=./rec_r45_abinet_train/best_accuracy Global.save_inference_dir=./inference/rec_r45_abinet +``` + +**Note:** +- If you are training the model on your own dataset and have modified the dictionary file, please pay attention to modify the `character_dict_path` in the configuration file to the modified dictionary file. +- If you modified the input size during training, please modify the `infer_shape` corresponding to ABINet in the `tools/export_model.py` file. + +After the conversion is successful, there are three files in the directory: +``` +/inference/rec_r45_abinet/ + ├── inference.pdiparams + ├── inference.pdiparams.info + └── inference.pdmodel +``` + + +For ABINet text recognition model inference, the following commands can be executed: + +``` +python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' --rec_model_dir='./inference/rec_r45_abinet/' --rec_algorithm='ABINet' --rec_image_shape='3,32,128' --rec_char_dict_path='./ppocr/utils/ic15_dict.txt' +``` + +![](../imgs_words_en/word_10.png) + +After executing the command, the prediction result (recognized text and score) of the image above is printed to the screen, an example is as follows: +The result is as follows: +```shell +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9999995231628418) +``` + + +### 4.2 C++ Inference + +Not supported + + +### 4.3 Serving + +Not supported + + +### 4.4 More + +Not supported + + +## 5. FAQ + +1. Note that the MJSynth and SynthText datasets come from [ABINet repo](https://github.com/FangShancheng/ABINet). +2. We use the pre-trained model provided by the ABINet authors for finetune training. + +## Citation + +```bibtex +@article{Fang2021ABINet, + title = {ABINet: Read Like Humans: Autonomous, Bidirectional and Iterative Language Modeling for Scene Text Recognition}, + author = {Shancheng Fang and Hongtao Xie and Yuxin Wang and Zhendong Mao and Yongdong Zhang}, + booktitle = {CVPR}, + year = {2021}, + url = {https://arxiv.org/abs/2103.06495}, + pages = {7098-7107} +} +``` diff --git a/doc/doc_en/algorithm_rec_nrtr_en.md b/doc/doc_en/algorithm_rec_nrtr_en.md index 40c9b91629..309d7ab123 100644 --- a/doc/doc_en/algorithm_rec_nrtr_en.md +++ b/doc/doc_en/algorithm_rec_nrtr_en.md @@ -12,6 +12,7 @@ - [4.3 Serving](#4-3) - [4.4 More](#4-4) - [5. FAQ](#5) +- [6. Release Note](#6) ## 1. Introduction @@ -25,7 +26,7 @@ Using MJSynth and SynthText two text recognition datasets for training, and eval |Model|Backbone|config|Acc|Download link| | --- | --- | --- | --- | --- | -|NRTR|MTB|[rec_mtb_nrtr.yml](../../configs/rec/rec_mtb_nrtr.yml)|84.21%|[train model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mtb_nrtr_train.tar)| +|NRTR|MTB|[rec_mtb_nrtr.yml](../../configs/rec/rec_mtb_nrtr.yml)|84.21%|[trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mtb_nrtr_train.tar)| ## 2. Environment @@ -98,7 +99,7 @@ python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' After executing the command, the prediction result (recognized text and score) of the image above is printed to the screen, an example is as follows: The result is as follows: ```shell -Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9265879392623901) +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9465042352676392) ``` @@ -121,12 +122,146 @@ Not supported 1. In the `NRTR` paper, Beam search is used to decode characters, but the speed is slow. Beam search is not used by default here, and greedy search is used to decode characters. + +## 6. Release Note + +1. The release/2.6 version updates the NRTR code structure. The new version of NRTR can load the model parameters of the old version (release/2.5 and before), and you may use the following code to convert the old version model parameters to the new version model parameters: + +```python + + params = paddle.load('path/' + '.pdparams') # the old version parameters + state_dict = model.state_dict() # the new version model parameters + new_state_dict = {} + + for k1, v1 in state_dict.items(): + + k = k1 + if 'encoder' in k and 'self_attn' in k and 'qkv' in k and 'weight' in k: + + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')].transpose((1, 0, 2, 3)) + k = params[k_para.replace('qkv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('qkv', 'conv3')].transpose((1, 0, 2, 3)) + + new_state_dict[k1] = np.concatenate([q[:, :, 0, 0], k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'encoder' in k and 'self_attn' in k and 'qkv' in k and 'bias' in k: + + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')] + k = params[k_para.replace('qkv', 'conv2')] + v = params[k_para.replace('qkv', 'conv3')] + + new_state_dict[k1] = np.concatenate([q, k, v], -1) + + elif 'encoder' in k and 'self_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + elif 'encoder' in k and 'norm3' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para.replace('norm3', 'norm2')] + + elif 'encoder' in k and 'norm1' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + + elif 'decoder' in k and 'self_attn' in k and 'qkv' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')].transpose((1, 0, 2, 3)) + k = params[k_para.replace('qkv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('qkv', 'conv3')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = np.concatenate([q[:, :, 0, 0], k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'decoder' in k and 'self_attn' in k and 'qkv' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + q = params[k_para.replace('qkv', 'conv1')] + k = params[k_para.replace('qkv', 'conv2')] + v = params[k_para.replace('qkv', 'conv3')] + new_state_dict[k1] = np.concatenate([q, k, v], -1) + + elif 'decoder' in k and 'self_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + + elif 'decoder' in k and 'cross_attn' in k and 'q' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + q = params[k_para.replace('q', 'conv1')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = q[:, :, 0, 0] + + elif 'decoder' in k and 'cross_attn' in k and 'q' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + q = params[k_para.replace('q', 'conv1')] + new_state_dict[k1] = q + + elif 'decoder' in k and 'cross_attn' in k and 'kv' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + k = params[k_para.replace('kv', 'conv2')].transpose((1, 0, 2, 3)) + v = params[k_para.replace('kv', 'conv3')].transpose((1, 0, 2, 3)) + new_state_dict[k1] = np.concatenate([k[:, :, 0, 0], v[:, :, 0, 0]], -1) + + elif 'decoder' in k and 'cross_attn' in k and 'kv' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + k = params[k_para.replace('kv', 'conv2')] + v = params[k_para.replace('kv', 'conv3')] + new_state_dict[k1] = np.concatenate([k, v], -1) + + elif 'decoder' in k and 'cross_attn' in k and 'out_proj' in k: + + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('cross_attn', 'multihead_attn') + new_state_dict[k1] = params[k_para] + elif 'decoder' in k and 'norm' in k: + k_para = k[:13] + 'layers.' + k[13:] + new_state_dict[k1] = params[k_para] + elif 'mlp' in k and 'weight' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('fc', 'conv') + k_para = k_para.replace('mlp.', '') + w = params[k_para].transpose((1, 0, 2, 3)) + new_state_dict[k1] = w[:, :, 0, 0] + elif 'mlp' in k and 'bias' in k: + k_para = k[:13] + 'layers.' + k[13:] + k_para = k_para.replace('fc', 'conv') + k_para = k_para.replace('mlp.', '') + w = params[k_para] + new_state_dict[k1] = w + + else: + new_state_dict[k1] = params[k1] + + if list(new_state_dict[k1].shape) != list(v1.shape): + print(k1) + + + for k, v1 in state_dict.items(): + if k not in new_state_dict.keys(): + print(1, k) + elif list(new_state_dict[k].shape) != list(v1.shape): + print(2, k) + + + + model.set_state_dict(new_state_dict) + paddle.save(model.state_dict(), 'nrtrnew_from_old_params.pdparams') + +``` + +2. The new version has a clean code structure and improved inference speed compared with the old version. + ## Citation ```bibtex @article{Sheng2019NRTR, title = {NRTR: A No-Recurrence Sequence-to-Sequence Model For Scene Text Recognition}, - author = {Fenfen Sheng and Zhineng Chen andBo Xu}, + author = {Fenfen Sheng and Zhineng Chen and Bo Xu}, booktitle = {ICDAR}, year = {2019}, url = {http://arxiv.org/abs/1806.00926}, diff --git a/doc/doc_en/algorithm_rec_svtr_en.md b/doc/doc_en/algorithm_rec_svtr_en.md index d402a6b491..37cd35f35a 100644 --- a/doc/doc_en/algorithm_rec_svtr_en.md +++ b/doc/doc_en/algorithm_rec_svtr_en.md @@ -88,7 +88,6 @@ python3 tools/export_model.py -c configs/rec/rec_svtrnet.yml -o Global.pretraine **Note:** - If you are training the model on your own dataset and have modified the dictionary file, please pay attention to modify the `character_dict_path` in the configuration file to the modified dictionary file. -- If you modified the input size during training, please modify the `infer_shape` corresponding to SVTR in the `tools/export_model.py` file. After the conversion is successful, there are three files in the directory: ``` diff --git a/doc/doc_en/algorithm_rec_vitstr_en.md b/doc/doc_en/algorithm_rec_vitstr_en.md new file mode 100644 index 0000000000..a6f9e2f15d --- /dev/null +++ b/doc/doc_en/algorithm_rec_vitstr_en.md @@ -0,0 +1,134 @@ +# ViTSTR + +- [1. Introduction](#1) +- [2. Environment](#2) +- [3. Model Training / Evaluation / Prediction](#3) + - [3.1 Training](#3-1) + - [3.2 Evaluation](#3-2) + - [3.3 Prediction](#3-3) +- [4. Inference and Deployment](#4) + - [4.1 Python Inference](#4-1) + - [4.2 C++ Inference](#4-2) + - [4.3 Serving](#4-3) + - [4.4 More](#4-4) +- [5. FAQ](#5) + + +## 1. Introduction + +Paper: +> [Vision Transformer for Fast and Efficient Scene Text Recognition](https://arxiv.org/abs/2105.08582) +> Rowel Atienza +> ICDAR, 2021 + +Using MJSynth and SynthText two text recognition datasets for training, and evaluating on IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE datasets, the algorithm reproduction effect is as follows: + +|Model|Backbone|config|Acc|Download link| +| --- | --- | --- | --- | --- | +|ViTSTR|ViTSTR|[rec_vitstr_none_ce.yml](../../configs/rec/rec_vitstr_none_ce.yml)|79.82%|[trained model](https://paddleocr.bj.bcebos.com/rec_vitstr_none_none_train.tar)| + + +## 2. Environment +Please refer to ["Environment Preparation"](./environment_en.md) to configure the PaddleOCR environment, and refer to ["Project Clone"](./clone_en.md) to clone the project code. + + + +## 3. Model Training / Evaluation / Prediction + +Please refer to [Text Recognition Tutorial](./recognition_en.md). PaddleOCR modularizes the code, and training different recognition models only requires **changing the configuration file**. + +Training: + +Specifically, after the data preparation is completed, the training can be started. The training command is as follows: + +``` +#Single GPU training (long training period, not recommended) +python3 tools/train.py -c configs/rec/rec_vitstr_none_ce.yml + +#Multi GPU training, specify the gpu number through the --gpus parameter +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_vitstr_none_ce.yml +``` + +Evaluation: + +``` +# GPU evaluation +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.pretrained_model={path/to/weights}/best_accuracy +``` + +Prediction: + +``` +# The configuration file used for prediction must match the training +python3 tools/infer_rec.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./rec_vitstr_none_ce_train/best_accuracy +``` + + +## 4. Inference and Deployment + + +### 4.1 Python Inference +First, the model saved during the ViTSTR text recognition training process is converted into an inference model. ( [Model download link](https://paddleocr.bj.bcebos.com/rec_vitstr_none_none_train.tar)) ), you can use the following command to convert: + +``` +python3 tools/export_model.py -c configs/rec/rec_vitstr_none_ce.yml -o Global.pretrained_model=./rec_vitstr_none_ce_train/best_accuracy Global.save_inference_dir=./inference/rec_vitstr +``` + +**Note:** +- If you are training the model on your own dataset and have modified the dictionary file, please pay attention to modify the `character_dict_path` in the configuration file to the modified dictionary file. +- If you modified the input size during training, please modify the `infer_shape` corresponding to ViTSTR in the `tools/export_model.py` file. + +After the conversion is successful, there are three files in the directory: +``` +/inference/rec_vitstr/ + ├── inference.pdiparams + ├── inference.pdiparams.info + └── inference.pdmodel +``` + + +For ViTSTR text recognition model inference, the following commands can be executed: + +``` +python3 tools/infer/predict_rec.py --image_dir='./doc/imgs_words_en/word_10.png' --rec_model_dir='./inference/rec_vitstr/' --rec_algorithm='ViTSTR' --rec_image_shape='1,224,224' --rec_char_dict_path='./ppocr/utils/EN_symbol_dict.txt' +``` + +![](../imgs_words_en/word_10.png) + +After executing the command, the prediction result (recognized text and score) of the image above is printed to the screen, an example is as follows: +The result is as follows: +```shell +Predicts of ./doc/imgs_words_en/word_10.png:('pain', 0.9998350143432617) +``` + + +### 4.2 C++ Inference + +Not supported + + +### 4.3 Serving + +Not supported + + +### 4.4 More + +Not supported + + +## 5. FAQ + +1. In the `ViTSTR` paper, using pre-trained weights on ImageNet1k for initial training, we did not use pre-trained weights in training, and the final accuracy did not change or even improved. + +## Citation + +```bibtex +@article{Atienza2021ViTSTR, + title = {Vision Transformer for Fast and Efficient Scene Text Recognition}, + author = {Rowel Atienza}, + booktitle = {ICDAR}, + year = {2021}, + url = {https://arxiv.org/abs/2105.08582} +} +``` diff --git a/ppocr/data/imaug/__init__.py b/ppocr/data/imaug/__init__.py index f0fd578f61..63dfda91f8 100644 --- a/ppocr/data/imaug/__init__.py +++ b/ppocr/data/imaug/__init__.py @@ -22,8 +22,10 @@ from .make_shrink_map import MakeShrinkMap from .random_crop_data import EastRandomCropData, RandomCropImgMask from .make_pse_gt import MakePseGt -from .rec_img_aug import BaseDataAugmentation, RecAug, RecConAug, RecResizeImg, ClsResizeImg, \ - SRNRecResizeImg, NRTRRecResizeImg, SARRecResizeImg, PRENResizeImg + +from .rec_img_aug import RecAug, RecConAug, RecResizeImg, ClsResizeImg, \ + SRNRecResizeImg, GrayRecResizeImg, SARRecResizeImg, PRENResizeImg, \ + ABINetRecResizeImg, SVTRRecResizeImg, ABINetRecAug from .ssl_img_aug import SSLRotateResize from .randaugment import RandAugment from .copy_paste import CopyPaste diff --git a/ppocr/data/imaug/abinet_aug.py b/ppocr/data/imaug/abinet_aug.py new file mode 100644 index 0000000000..eefdc75d5a --- /dev/null +++ b/ppocr/data/imaug/abinet_aug.py @@ -0,0 +1,407 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +""" +This code is refer from: +https://github.com/FangShancheng/ABINet/blob/main/transforms.py +""" +import math +import numbers +import random + +import cv2 +import numpy as np +from paddle.vision.transforms import Compose, ColorJitter + + +def sample_asym(magnitude, size=None): + return np.random.beta(1, 4, size) * magnitude + + +def sample_sym(magnitude, size=None): + return (np.random.beta(4, 4, size=size) - 0.5) * 2 * magnitude + + +def sample_uniform(low, high, size=None): + return np.random.uniform(low, high, size=size) + + +def get_interpolation(type='random'): + if type == 'random': + choice = [ + cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA + ] + interpolation = choice[random.randint(0, len(choice) - 1)] + elif type == 'nearest': + interpolation = cv2.INTER_NEAREST + elif type == 'linear': + interpolation = cv2.INTER_LINEAR + elif type == 'cubic': + interpolation = cv2.INTER_CUBIC + elif type == 'area': + interpolation = cv2.INTER_AREA + else: + raise TypeError( + 'Interpolation types only nearest, linear, cubic, area are supported!' + ) + return interpolation + + +class CVRandomRotation(object): + def __init__(self, degrees=15): + assert isinstance(degrees, + numbers.Number), "degree should be a single number." + assert degrees >= 0, "degree must be positive." + self.degrees = degrees + + @staticmethod + def get_params(degrees): + return sample_sym(degrees) + + def __call__(self, img): + angle = self.get_params(self.degrees) + src_h, src_w = img.shape[:2] + M = cv2.getRotationMatrix2D( + center=(src_w / 2, src_h / 2), angle=angle, scale=1.0) + abs_cos, abs_sin = abs(M[0, 0]), abs(M[0, 1]) + dst_w = int(src_h * abs_sin + src_w * abs_cos) + dst_h = int(src_h * abs_cos + src_w * abs_sin) + M[0, 2] += (dst_w - src_w) / 2 + M[1, 2] += (dst_h - src_h) / 2 + + flags = get_interpolation() + return cv2.warpAffine( + img, + M, (dst_w, dst_h), + flags=flags, + borderMode=cv2.BORDER_REPLICATE) + + +class CVRandomAffine(object): + def __init__(self, degrees, translate=None, scale=None, shear=None): + assert isinstance(degrees, + numbers.Number), "degree should be a single number." + assert degrees >= 0, "degree must be positive." + self.degrees = degrees + + if translate is not None: + assert isinstance(translate, (tuple, list)) and len(translate) == 2, \ + "translate should be a list or tuple and it must be of length 2." + for t in translate: + if not (0.0 <= t <= 1.0): + raise ValueError( + "translation values should be between 0 and 1") + self.translate = translate + + if scale is not None: + assert isinstance(scale, (tuple, list)) and len(scale) == 2, \ + "scale should be a list or tuple and it must be of length 2." + for s in scale: + if s <= 0: + raise ValueError("scale values should be positive") + self.scale = scale + + if shear is not None: + if isinstance(shear, numbers.Number): + if shear < 0: + raise ValueError( + "If shear is a single number, it must be positive.") + self.shear = [shear] + else: + assert isinstance(shear, (tuple, list)) and (len(shear) == 2), \ + "shear should be a list or tuple and it must be of length 2." + self.shear = shear + else: + self.shear = shear + + def _get_inverse_affine_matrix(self, center, angle, translate, scale, + shear): + # https://github.com/pytorch/vision/blob/v0.4.0/torchvision/transforms/functional.py#L717 + from numpy import sin, cos, tan + + if isinstance(shear, numbers.Number): + shear = [shear, 0] + + if not isinstance(shear, (tuple, list)) and len(shear) == 2: + raise ValueError( + "Shear should be a single value or a tuple/list containing " + + "two values. Got {}".format(shear)) + + rot = math.radians(angle) + sx, sy = [math.radians(s) for s in shear] + + cx, cy = center + tx, ty = translate + + # RSS without scaling + a = cos(rot - sy) / cos(sy) + b = -cos(rot - sy) * tan(sx) / cos(sy) - sin(rot) + c = sin(rot - sy) / cos(sy) + d = -sin(rot - sy) * tan(sx) / cos(sy) + cos(rot) + + # Inverted rotation matrix with scale and shear + # det([[a, b], [c, d]]) == 1, since det(rotation) = 1 and det(shear) = 1 + M = [d, -b, 0, -c, a, 0] + M = [x / scale for x in M] + + # Apply inverse of translation and of center translation: RSS^-1 * C^-1 * T^-1 + M[2] += M[0] * (-cx - tx) + M[1] * (-cy - ty) + M[5] += M[3] * (-cx - tx) + M[4] * (-cy - ty) + + # Apply center translation: C * RSS^-1 * C^-1 * T^-1 + M[2] += cx + M[5] += cy + return M + + @staticmethod + def get_params(degrees, translate, scale_ranges, shears, height): + angle = sample_sym(degrees) + if translate is not None: + max_dx = translate[0] * height + max_dy = translate[1] * height + translations = (np.round(sample_sym(max_dx)), + np.round(sample_sym(max_dy))) + else: + translations = (0, 0) + + if scale_ranges is not None: + scale = sample_uniform(scale_ranges[0], scale_ranges[1]) + else: + scale = 1.0 + + if shears is not None: + if len(shears) == 1: + shear = [sample_sym(shears[0]), 0.] + elif len(shears) == 2: + shear = [sample_sym(shears[0]), sample_sym(shears[1])] + else: + shear = 0.0 + + return angle, translations, scale, shear + + def __call__(self, img): + src_h, src_w = img.shape[:2] + angle, translate, scale, shear = self.get_params( + self.degrees, self.translate, self.scale, self.shear, src_h) + + M = self._get_inverse_affine_matrix((src_w / 2, src_h / 2), angle, + (0, 0), scale, shear) + M = np.array(M).reshape(2, 3) + + startpoints = [(0, 0), (src_w - 1, 0), (src_w - 1, src_h - 1), + (0, src_h - 1)] + project = lambda x, y, a, b, c: int(a * x + b * y + c) + endpoints = [(project(x, y, *M[0]), project(x, y, *M[1])) + for x, y in startpoints] + + rect = cv2.minAreaRect(np.array(endpoints)) + bbox = cv2.boxPoints(rect).astype(dtype=np.int) + max_x, max_y = bbox[:, 0].max(), bbox[:, 1].max() + min_x, min_y = bbox[:, 0].min(), bbox[:, 1].min() + + dst_w = int(max_x - min_x) + dst_h = int(max_y - min_y) + M[0, 2] += (dst_w - src_w) / 2 + M[1, 2] += (dst_h - src_h) / 2 + + # add translate + dst_w += int(abs(translate[0])) + dst_h += int(abs(translate[1])) + if translate[0] < 0: M[0, 2] += abs(translate[0]) + if translate[1] < 0: M[1, 2] += abs(translate[1]) + + flags = get_interpolation() + return cv2.warpAffine( + img, + M, (dst_w, dst_h), + flags=flags, + borderMode=cv2.BORDER_REPLICATE) + + +class CVRandomPerspective(object): + def __init__(self, distortion=0.5): + self.distortion = distortion + + def get_params(self, width, height, distortion): + offset_h = sample_asym( + distortion * height / 2, size=4).astype(dtype=np.int) + offset_w = sample_asym( + distortion * width / 2, size=4).astype(dtype=np.int) + topleft = (offset_w[0], offset_h[0]) + topright = (width - 1 - offset_w[1], offset_h[1]) + botright = (width - 1 - offset_w[2], height - 1 - offset_h[2]) + botleft = (offset_w[3], height - 1 - offset_h[3]) + + startpoints = [(0, 0), (width - 1, 0), (width - 1, height - 1), + (0, height - 1)] + endpoints = [topleft, topright, botright, botleft] + return np.array( + startpoints, dtype=np.float32), np.array( + endpoints, dtype=np.float32) + + def __call__(self, img): + height, width = img.shape[:2] + startpoints, endpoints = self.get_params(width, height, self.distortion) + M = cv2.getPerspectiveTransform(startpoints, endpoints) + + # TODO: more robust way to crop image + rect = cv2.minAreaRect(endpoints) + bbox = cv2.boxPoints(rect).astype(dtype=np.int) + max_x, max_y = bbox[:, 0].max(), bbox[:, 1].max() + min_x, min_y = bbox[:, 0].min(), bbox[:, 1].min() + min_x, min_y = max(min_x, 0), max(min_y, 0) + + flags = get_interpolation() + img = cv2.warpPerspective( + img, + M, (max_x, max_y), + flags=flags, + borderMode=cv2.BORDER_REPLICATE) + img = img[min_y:, min_x:] + return img + + +class CVRescale(object): + def __init__(self, factor=4, base_size=(128, 512)): + """ Define image scales using gaussian pyramid and rescale image to target scale. + + Args: + factor: the decayed factor from base size, factor=4 keeps target scale by default. + base_size: base size the build the bottom layer of pyramid + """ + if isinstance(factor, numbers.Number): + self.factor = round(sample_uniform(0, factor)) + elif isinstance(factor, (tuple, list)) and len(factor) == 2: + self.factor = round(sample_uniform(factor[0], factor[1])) + else: + raise Exception('factor must be number or list with length 2') + # assert factor is valid + self.base_h, self.base_w = base_size[:2] + + def __call__(self, img): + if self.factor == 0: return img + src_h, src_w = img.shape[:2] + cur_w, cur_h = self.base_w, self.base_h + scale_img = cv2.resize( + img, (cur_w, cur_h), interpolation=get_interpolation()) + for _ in range(self.factor): + scale_img = cv2.pyrDown(scale_img) + scale_img = cv2.resize( + scale_img, (src_w, src_h), interpolation=get_interpolation()) + return scale_img + + +class CVGaussianNoise(object): + def __init__(self, mean=0, var=20): + self.mean = mean + if isinstance(var, numbers.Number): + self.var = max(int(sample_asym(var)), 1) + elif isinstance(var, (tuple, list)) and len(var) == 2: + self.var = int(sample_uniform(var[0], var[1])) + else: + raise Exception('degree must be number or list with length 2') + + def __call__(self, img): + noise = np.random.normal(self.mean, self.var**0.5, img.shape) + img = np.clip(img + noise, 0, 255).astype(np.uint8) + return img + + +class CVMotionBlur(object): + def __init__(self, degrees=12, angle=90): + if isinstance(degrees, numbers.Number): + self.degree = max(int(sample_asym(degrees)), 1) + elif isinstance(degrees, (tuple, list)) and len(degrees) == 2: + self.degree = int(sample_uniform(degrees[0], degrees[1])) + else: + raise Exception('degree must be number or list with length 2') + self.angle = sample_uniform(-angle, angle) + + def __call__(self, img): + M = cv2.getRotationMatrix2D((self.degree // 2, self.degree // 2), + self.angle, 1) + motion_blur_kernel = np.zeros((self.degree, self.degree)) + motion_blur_kernel[self.degree // 2, :] = 1 + motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, M, + (self.degree, self.degree)) + motion_blur_kernel = motion_blur_kernel / self.degree + img = cv2.filter2D(img, -1, motion_blur_kernel) + img = np.clip(img, 0, 255).astype(np.uint8) + return img + + +class CVGeometry(object): + def __init__(self, + degrees=15, + translate=(0.3, 0.3), + scale=(0.5, 2.), + shear=(45, 15), + distortion=0.5, + p=0.5): + self.p = p + type_p = random.random() + if type_p < 0.33: + self.transforms = CVRandomRotation(degrees=degrees) + elif type_p < 0.66: + self.transforms = CVRandomAffine( + degrees=degrees, translate=translate, scale=scale, shear=shear) + else: + self.transforms = CVRandomPerspective(distortion=distortion) + + def __call__(self, img): + if random.random() < self.p: + return self.transforms(img) + else: + return img + + +class CVDeterioration(object): + def __init__(self, var, degrees, factor, p=0.5): + self.p = p + transforms = [] + if var is not None: + transforms.append(CVGaussianNoise(var=var)) + if degrees is not None: + transforms.append(CVMotionBlur(degrees=degrees)) + if factor is not None: + transforms.append(CVRescale(factor=factor)) + + random.shuffle(transforms) + transforms = Compose(transforms) + self.transforms = transforms + + def __call__(self, img): + if random.random() < self.p: + + return self.transforms(img) + else: + return img + + +class CVColorJitter(object): + def __init__(self, + brightness=0.5, + contrast=0.5, + saturation=0.5, + hue=0.1, + p=0.5): + self.p = p + self.transforms = ColorJitter( + brightness=brightness, + contrast=contrast, + saturation=saturation, + hue=hue) + + def __call__(self, img): + if random.random() < self.p: return self.transforms(img) + else: return img diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 39c2cbbac8..312d6dc9ad 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -157,37 +157,6 @@ class BaseRecLabelEncode(object): return text_list -class NRTRLabelEncode(BaseRecLabelEncode): - """ Convert between text-label and text-index """ - - def __init__(self, - max_text_length, - character_dict_path=None, - use_space_char=False, - **kwargs): - - super(NRTRLabelEncode, self).__init__( - max_text_length, character_dict_path, use_space_char) - - def __call__(self, data): - text = data['label'] - text = self.encode(text) - if text is None: - return None - if len(text) >= self.max_text_len - 1: - return None - data['length'] = np.array(len(text)) - text.insert(0, 2) - text.append(3) - text = text + [0] * (self.max_text_len - len(text)) - data['label'] = np.array(text) - return data - - def add_special_char(self, dict_character): - dict_character = ['blank', '', '', ''] + dict_character - return dict_character - - class CTCLabelEncode(BaseRecLabelEncode): """ Convert between text-label and text-index """ @@ -1046,3 +1015,99 @@ class MultiLabelEncode(BaseRecLabelEncode): data_out['label_sar'] = sar['label'] data_out['length'] = ctc['length'] return data_out + + +class NRTRLabelEncode(BaseRecLabelEncode): + """ Convert between text-label and text-index """ + + def __init__(self, + max_text_length, + character_dict_path=None, + use_space_char=False, + **kwargs): + + super(NRTRLabelEncode, self).__init__( + max_text_length, character_dict_path, use_space_char) + + def __call__(self, data): + text = data['label'] + text = self.encode(text) + if text is None: + return None + if len(text) >= self.max_text_len - 1: + return None + data['length'] = np.array(len(text)) + text.insert(0, 2) + text.append(3) + text = text + [0] * (self.max_text_len - len(text)) + data['label'] = np.array(text) + return data + + def add_special_char(self, dict_character): + dict_character = ['blank', '', '', ''] + dict_character + return dict_character + + +class ViTSTRLabelEncode(BaseRecLabelEncode): + """ Convert between text-label and text-index """ + + def __init__(self, + max_text_length, + character_dict_path=None, + use_space_char=False, + ignore_index=0, + **kwargs): + + super(ViTSTRLabelEncode, self).__init__( + max_text_length, character_dict_path, use_space_char) + self.ignore_index = ignore_index + + def __call__(self, data): + text = data['label'] + text = self.encode(text) + if text is None: + return None + if len(text) >= self.max_text_len: + return None + data['length'] = np.array(len(text)) + text.insert(0, self.ignore_index) + text.append(1) + text = text + [self.ignore_index] * (self.max_text_len + 2 - len(text)) + data['label'] = np.array(text) + return data + + def add_special_char(self, dict_character): + dict_character = ['', ''] + dict_character + return dict_character + + +class ABINetLabelEncode(BaseRecLabelEncode): + """ Convert between text-label and text-index """ + + def __init__(self, + max_text_length, + character_dict_path=None, + use_space_char=False, + ignore_index=100, + **kwargs): + + super(ABINetLabelEncode, self).__init__( + max_text_length, character_dict_path, use_space_char) + self.ignore_index = ignore_index + + def __call__(self, data): + text = data['label'] + text = self.encode(text) + if text is None: + return None + if len(text) >= self.max_text_len: + return None + data['length'] = np.array(len(text)) + text.append(0) + text = text + [self.ignore_index] * (self.max_text_len + 1 - len(text)) + data['label'] = np.array(text) + return data + + def add_special_char(self, dict_character): + dict_character = ['
'] + dict_character + return dict_character diff --git a/ppocr/data/imaug/operators.py b/ppocr/data/imaug/operators.py index 09736515e7..5397d71ccb 100644 --- a/ppocr/data/imaug/operators.py +++ b/ppocr/data/imaug/operators.py @@ -67,39 +67,6 @@ class DecodeImage(object): return data -class NRTRDecodeImage(object): - """ decode image """ - - def __init__(self, img_mode='RGB', channel_first=False, **kwargs): - self.img_mode = img_mode - self.channel_first = channel_first - - def __call__(self, data): - img = data['image'] - if six.PY2: - assert type(img) is str and len( - img) > 0, "invalid input 'img' in DecodeImage" - else: - assert type(img) is bytes and len( - img) > 0, "invalid input 'img' in DecodeImage" - img = np.frombuffer(img, dtype='uint8') - - img = cv2.imdecode(img, 1) - - if img is None: - return None - if self.img_mode == 'GRAY': - img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) - elif self.img_mode == 'RGB': - assert img.shape[2] == 3, 'invalid shape of image[%s]' % (img.shape) - img = img[:, :, ::-1] - img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - if self.channel_first: - img = img.transpose((2, 0, 1)) - data['image'] = img - return data - - class NormalizeImage(object): """ normalize image such as substract mean, divide std """ diff --git a/ppocr/data/imaug/rec_img_aug.py b/ppocr/data/imaug/rec_img_aug.py index 32de2b3fc3..26773d0a51 100644 --- a/ppocr/data/imaug/rec_img_aug.py +++ b/ppocr/data/imaug/rec_img_aug.py @@ -19,6 +19,8 @@ import random import copy from PIL import Image from .text_image_aug import tia_perspective, tia_stretch, tia_distort +from .abinet_aug import CVGeometry, CVDeterioration, CVColorJitter +from paddle.vision.transforms import Compose class RecAug(object): @@ -94,6 +96,36 @@ class BaseDataAugmentation(object): return data +class ABINetRecAug(object): + def __init__(self, + geometry_p=0.5, + deterioration_p=0.25, + colorjitter_p=0.25, + **kwargs): + self.transforms = Compose([ + CVGeometry( + degrees=45, + translate=(0.0, 0.0), + scale=(0.5, 2.), + shear=(45, 15), + distortion=0.5, + p=geometry_p), CVDeterioration( + var=20, degrees=6, factor=4, p=deterioration_p), + CVColorJitter( + brightness=0.5, + contrast=0.5, + saturation=0.5, + hue=0.1, + p=colorjitter_p) + ]) + + def __call__(self, data): + img = data['image'] + img = self.transforms(img) + data['image'] = img + return data + + class RecConAug(object): def __init__(self, prob=0.5, @@ -148,46 +180,6 @@ class ClsResizeImg(object): return data -class NRTRRecResizeImg(object): - def __init__(self, image_shape, resize_type, padding=False, **kwargs): - self.image_shape = image_shape - self.resize_type = resize_type - self.padding = padding - - def __call__(self, data): - img = data['image'] - img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - image_shape = self.image_shape - if self.padding: - imgC, imgH, imgW = image_shape - # todo: change to 0 and modified image shape - h = img.shape[0] - w = img.shape[1] - ratio = w / float(h) - if math.ceil(imgH * ratio) > imgW: - resized_w = imgW - else: - resized_w = int(math.ceil(imgH * ratio)) - resized_image = cv2.resize(img, (resized_w, imgH)) - norm_img = np.expand_dims(resized_image, -1) - norm_img = norm_img.transpose((2, 0, 1)) - resized_image = norm_img.astype(np.float32) / 128. - 1. - padding_im = np.zeros((imgC, imgH, imgW), dtype=np.float32) - padding_im[:, :, 0:resized_w] = resized_image - data['image'] = padding_im - return data - if self.resize_type == 'PIL': - image_pil = Image.fromarray(np.uint8(img)) - img = image_pil.resize(self.image_shape, Image.ANTIALIAS) - img = np.array(img) - if self.resize_type == 'OpenCV': - img = cv2.resize(img, self.image_shape) - norm_img = np.expand_dims(img, -1) - norm_img = norm_img.transpose((2, 0, 1)) - data['image'] = norm_img.astype(np.float32) / 128. - 1. - return data - - class RecResizeImg(object): def __init__(self, image_shape, @@ -268,6 +260,84 @@ class PRENResizeImg(object): return data +class GrayRecResizeImg(object): + def __init__(self, + image_shape, + resize_type, + inter_type='Image.ANTIALIAS', + scale=True, + padding=False, + **kwargs): + self.image_shape = image_shape + self.resize_type = resize_type + self.padding = padding + self.inter_type = eval(inter_type) + self.scale = scale + + def __call__(self, data): + img = data['image'] + img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + image_shape = self.image_shape + if self.padding: + imgC, imgH, imgW = image_shape + # todo: change to 0 and modified image shape + h = img.shape[0] + w = img.shape[1] + ratio = w / float(h) + if math.ceil(imgH * ratio) > imgW: + resized_w = imgW + else: + resized_w = int(math.ceil(imgH * ratio)) + resized_image = cv2.resize(img, (resized_w, imgH)) + norm_img = np.expand_dims(resized_image, -1) + norm_img = norm_img.transpose((2, 0, 1)) + resized_image = norm_img.astype(np.float32) / 128. - 1. + padding_im = np.zeros((imgC, imgH, imgW), dtype=np.float32) + padding_im[:, :, 0:resized_w] = resized_image + data['image'] = padding_im + return data + if self.resize_type == 'PIL': + image_pil = Image.fromarray(np.uint8(img)) + img = image_pil.resize(self.image_shape, self.inter_type) + img = np.array(img) + if self.resize_type == 'OpenCV': + img = cv2.resize(img, self.image_shape) + norm_img = np.expand_dims(img, -1) + norm_img = norm_img.transpose((2, 0, 1)) + if self.scale: + data['image'] = norm_img.astype(np.float32) / 128. - 1. + else: + data['image'] = norm_img.astype(np.float32) / 255. + return data + + +class ABINetRecResizeImg(object): + def __init__(self, image_shape, **kwargs): + self.image_shape = image_shape + + def __call__(self, data): + img = data['image'] + norm_img, valid_ratio = resize_norm_img_abinet(img, self.image_shape) + data['image'] = norm_img + data['valid_ratio'] = valid_ratio + return data + + +class SVTRRecResizeImg(object): + def __init__(self, image_shape, padding=True, **kwargs): + self.image_shape = image_shape + self.padding = padding + + def __call__(self, data): + img = data['image'] + + norm_img, valid_ratio = resize_norm_img(img, self.image_shape, + self.padding) + data['image'] = norm_img + data['valid_ratio'] = valid_ratio + return data + + def resize_norm_img_sar(img, image_shape, width_downsample_ratio=0.25): imgC, imgH, imgW_min, imgW_max = image_shape h = img.shape[0] @@ -386,6 +456,26 @@ def resize_norm_img_srn(img, image_shape): return np.reshape(img_black, (c, row, col)).astype(np.float32) +def resize_norm_img_abinet(img, image_shape): + imgC, imgH, imgW = image_shape + + resized_image = cv2.resize( + img, (imgW, imgH), interpolation=cv2.INTER_LINEAR) + resized_w = imgW + resized_image = resized_image.astype('float32') + resized_image = resized_image / 255. + + mean = np.array([0.485, 0.456, 0.406]) + std = np.array([0.229, 0.224, 0.225]) + resized_image = ( + resized_image - mean[None, None, ...]) / std[None, None, ...] + resized_image = resized_image.transpose((2, 0, 1)) + resized_image = resized_image.astype('float32') + + valid_ratio = min(1.0, float(resized_w / imgW)) + return resized_image, valid_ratio + + def srn_other_inputs(image_shape, num_heads, max_text_length): imgC, imgH, imgW = image_shape diff --git a/ppocr/losses/__init__.py b/ppocr/losses/__init__.py index de8419b7c1..7bea87f62f 100755 --- a/ppocr/losses/__init__.py +++ b/ppocr/losses/__init__.py @@ -30,7 +30,7 @@ from .det_fce_loss import FCELoss from .rec_ctc_loss import CTCLoss from .rec_att_loss import AttentionLoss from .rec_srn_loss import SRNLoss -from .rec_nrtr_loss import NRTRLoss +from .rec_ce_loss import CELoss from .rec_sar_loss import SARLoss from .rec_aster_loss import AsterLoss from .rec_pren_loss import PRENLoss @@ -60,7 +60,7 @@ def build_loss(config): support_dict = [ 'DBLoss', 'PSELoss', 'EASTLoss', 'SASTLoss', 'FCELoss', 'CTCLoss', 'ClsLoss', 'AttentionLoss', 'SRNLoss', 'PGLoss', 'CombinedLoss', - 'NRTRLoss', 'TableAttentionLoss', 'SARLoss', 'AsterLoss', 'SDMGRLoss', + 'CELoss', 'TableAttentionLoss', 'SARLoss', 'AsterLoss', 'SDMGRLoss', 'VQASerTokenLayoutLMLoss', 'LossFromOutput', 'PRENLoss', 'MultiLoss' ] config = copy.deepcopy(config) diff --git a/ppocr/losses/rec_ce_loss.py b/ppocr/losses/rec_ce_loss.py new file mode 100644 index 0000000000..614384de86 --- /dev/null +++ b/ppocr/losses/rec_ce_loss.py @@ -0,0 +1,66 @@ +import paddle +from paddle import nn +import paddle.nn.functional as F + + +class CELoss(nn.Layer): + def __init__(self, + smoothing=False, + with_all=False, + ignore_index=-1, + **kwargs): + super(CELoss, self).__init__() + if ignore_index >= 0: + self.loss_func = nn.CrossEntropyLoss( + reduction='mean', ignore_index=ignore_index) + else: + self.loss_func = nn.CrossEntropyLoss(reduction='mean') + self.smoothing = smoothing + self.with_all = with_all + + def forward(self, pred, batch): + + if isinstance(pred, dict): # for ABINet + loss = {} + loss_sum = [] + for name, logits in pred.items(): + if isinstance(logits, list): + logit_num = len(logits) + all_tgt = paddle.concat([batch[1]] * logit_num, 0) + all_logits = paddle.concat(logits, 0) + flt_logtis = all_logits.reshape([-1, all_logits.shape[2]]) + flt_tgt = all_tgt.reshape([-1]) + else: + flt_logtis = logits.reshape([-1, logits.shape[2]]) + flt_tgt = batch[1].reshape([-1]) + loss[name + '_loss'] = self.loss_func(flt_logtis, flt_tgt) + loss_sum.append(loss[name + '_loss']) + loss['loss'] = sum(loss_sum) + return loss + else: + if self.with_all: # for ViTSTR + tgt = batch[1] + pred = pred.reshape([-1, pred.shape[2]]) + tgt = tgt.reshape([-1]) + loss = self.loss_func(pred, tgt) + return {'loss': loss} + else: # for NRTR + max_len = batch[2].max() + tgt = batch[1][:, 1:2 + max_len] + pred = pred.reshape([-1, pred.shape[2]]) + tgt = tgt.reshape([-1]) + if self.smoothing: + eps = 0.1 + n_class = pred.shape[1] + one_hot = F.one_hot(tgt, pred.shape[1]) + one_hot = one_hot * (1 - eps) + (1 - one_hot) * eps / ( + n_class - 1) + log_prb = F.log_softmax(pred, axis=1) + non_pad_mask = paddle.not_equal( + tgt, paddle.zeros( + tgt.shape, dtype=tgt.dtype)) + loss = -(one_hot * log_prb).sum(axis=1) + loss = loss.masked_select(non_pad_mask).mean() + else: + loss = self.loss_func(pred, tgt) + return {'loss': loss} diff --git a/ppocr/losses/rec_nrtr_loss.py b/ppocr/losses/rec_nrtr_loss.py deleted file mode 100644 index 200a6d0486..0000000000 --- a/ppocr/losses/rec_nrtr_loss.py +++ /dev/null @@ -1,30 +0,0 @@ -import paddle -from paddle import nn -import paddle.nn.functional as F - - -class NRTRLoss(nn.Layer): - def __init__(self, smoothing=True, **kwargs): - super(NRTRLoss, self).__init__() - self.loss_func = nn.CrossEntropyLoss(reduction='mean', ignore_index=0) - self.smoothing = smoothing - - def forward(self, pred, batch): - pred = pred.reshape([-1, pred.shape[2]]) - max_len = batch[2].max() - tgt = batch[1][:, 1:2 + max_len] - tgt = tgt.reshape([-1]) - if self.smoothing: - eps = 0.1 - n_class = pred.shape[1] - one_hot = F.one_hot(tgt, pred.shape[1]) - one_hot = one_hot * (1 - eps) + (1 - one_hot) * eps / (n_class - 1) - log_prb = F.log_softmax(pred, axis=1) - non_pad_mask = paddle.not_equal( - tgt, paddle.zeros( - tgt.shape, dtype=tgt.dtype)) - loss = -(one_hot * log_prb).sum(axis=1) - loss = loss.masked_select(non_pad_mask).mean() - else: - loss = self.loss_func(pred, tgt) - return {'loss': loss} diff --git a/ppocr/modeling/backbones/__init__.py b/ppocr/modeling/backbones/__init__.py index 072d6e0f84..f8959e263e 100755 --- a/ppocr/modeling/backbones/__init__.py +++ b/ppocr/modeling/backbones/__init__.py @@ -28,35 +28,37 @@ def build_backbone(config, model_type): from .rec_mv1_enhance import MobileNetV1Enhance from .rec_nrtr_mtb import MTB from .rec_resnet_31 import ResNet31 + from .rec_resnet_45 import ResNet45 from .rec_resnet_aster import ResNet_ASTER from .rec_micronet import MicroNet from .rec_efficientb3_pren import EfficientNetb3_PREN from .rec_svtrnet import SVTRNet + from .rec_vitstr import ViTSTR support_dict = [ 'MobileNetV1Enhance', 'MobileNetV3', 'ResNet', 'ResNetFPN', 'MTB', - "ResNet31", "ResNet_ASTER", 'MicroNet', 'EfficientNetb3_PREN', - 'SVTRNet' + 'ResNet31', 'ResNet45', 'ResNet_ASTER', 'MicroNet', + 'EfficientNetb3_PREN', 'SVTRNet', 'ViTSTR' ] - elif model_type == "e2e": + elif model_type == 'e2e': from .e2e_resnet_vd_pg import ResNet support_dict = ['ResNet'] elif model_type == 'kie': from .kie_unet_sdmgr import Kie_backbone support_dict = ['Kie_backbone'] - elif model_type == "table": + elif model_type == 'table': from .table_resnet_vd import ResNet from .table_mobilenet_v3 import MobileNetV3 - support_dict = ["ResNet", "MobileNetV3"] + support_dict = ['ResNet', 'MobileNetV3'] elif model_type == 'vqa': from .vqa_layoutlm import LayoutLMForSer, LayoutLMv2ForSer, LayoutLMv2ForRe, LayoutXLMForSer, LayoutXLMForRe support_dict = [ - "LayoutLMForSer", "LayoutLMv2ForSer", 'LayoutLMv2ForRe', - "LayoutXLMForSer", 'LayoutXLMForRe' + 'LayoutLMForSer', 'LayoutLMv2ForSer', 'LayoutLMv2ForRe', + 'LayoutXLMForSer', 'LayoutXLMForRe' ] else: raise NotImplementedError - module_name = config.pop("name") + module_name = config.pop('name') assert module_name in support_dict, Exception( "when model typs is {}, backbone only support {}".format(model_type, support_dict)) diff --git a/ppocr/modeling/backbones/rec_resnet_45.py b/ppocr/modeling/backbones/rec_resnet_45.py new file mode 100644 index 0000000000..9093d0bc99 --- /dev/null +++ b/ppocr/modeling/backbones/rec_resnet_45.py @@ -0,0 +1,147 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +""" +This code is refer from: +https://github.com/FangShancheng/ABINet/tree/main/modules +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import paddle +from paddle import ParamAttr +from paddle.nn.initializer import KaimingNormal +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +import math + +__all__ = ["ResNet45"] + + +def conv1x1(in_planes, out_planes, stride=1): + return nn.Conv2D( + in_planes, + out_planes, + kernel_size=1, + stride=1, + weight_attr=ParamAttr(initializer=KaimingNormal()), + bias_attr=False) + + +def conv3x3(in_channel, out_channel, stride=1): + return nn.Conv2D( + in_channel, + out_channel, + kernel_size=3, + stride=stride, + padding=1, + weight_attr=ParamAttr(initializer=KaimingNormal()), + bias_attr=False) + + +class BasicBlock(nn.Layer): + expansion = 1 + + def __init__(self, in_channels, channels, stride=1, downsample=None): + super().__init__() + self.conv1 = conv1x1(in_channels, channels) + self.bn1 = nn.BatchNorm2D(channels) + self.relu = nn.ReLU() + self.conv2 = conv3x3(channels, channels, stride) + self.bn2 = nn.BatchNorm2D(channels) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + residual = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + residual = self.downsample(x) + out += residual + out = self.relu(out) + + return out + + +class ResNet45(nn.Layer): + def __init__(self, block=BasicBlock, layers=[3, 4, 6, 6, 3], in_channels=3): + self.inplanes = 32 + super(ResNet45, self).__init__() + self.conv1 = nn.Conv2D( + 3, + 32, + kernel_size=3, + stride=1, + padding=1, + weight_attr=ParamAttr(initializer=KaimingNormal()), + bias_attr=False) + self.bn1 = nn.BatchNorm2D(32) + self.relu = nn.ReLU() + + self.layer1 = self._make_layer(block, 32, layers[0], stride=2) + self.layer2 = self._make_layer(block, 64, layers[1], stride=1) + self.layer3 = self._make_layer(block, 128, layers[2], stride=2) + self.layer4 = self._make_layer(block, 256, layers[3], stride=1) + self.layer5 = self._make_layer(block, 512, layers[4], stride=1) + self.out_channels = 512 + + # for m in self.modules(): + # if isinstance(m, nn.Conv2D): + # n = m._kernel_size[0] * m._kernel_size[1] * m._out_channels + # m.weight.data.normal_(0, math.sqrt(2. / n)) + + def _make_layer(self, block, planes, blocks, stride=1): + downsample = None + if stride != 1 or self.inplanes != planes * block.expansion: + # downsample = True + downsample = nn.Sequential( + nn.Conv2D( + self.inplanes, + planes * block.expansion, + kernel_size=1, + stride=stride, + weight_attr=ParamAttr(initializer=KaimingNormal()), + bias_attr=False), + nn.BatchNorm2D(planes * block.expansion), ) + + layers = [] + layers.append(block(self.inplanes, planes, stride, downsample)) + self.inplanes = planes * block.expansion + for i in range(1, blocks): + layers.append(block(self.inplanes, planes)) + + return nn.Sequential(*layers) + + def forward(self, x): + + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + # print(x) + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + # print(x) + x = self.layer4(x) + x = self.layer5(x) + return x diff --git a/ppocr/modeling/backbones/rec_svtrnet.py b/ppocr/modeling/backbones/rec_svtrnet.py index c57bf46345..c2c07f4476 100644 --- a/ppocr/modeling/backbones/rec_svtrnet.py +++ b/ppocr/modeling/backbones/rec_svtrnet.py @@ -147,7 +147,7 @@ class Attention(nn.Layer): dim, num_heads=8, mixer='Global', - HW=[8, 25], + HW=None, local_k=[7, 11], qkv_bias=False, qk_scale=None, @@ -210,7 +210,7 @@ class Block(nn.Layer): num_heads, mixer='Global', local_mixer=[7, 11], - HW=[8, 25], + HW=None, mlp_ratio=4., qkv_bias=False, qk_scale=None, @@ -274,7 +274,9 @@ class PatchEmbed(nn.Layer): img_size=[32, 100], in_channels=3, embed_dim=768, - sub_num=2): + sub_num=2, + patch_size=[4, 4], + mode='pope'): super().__init__() num_patches = (img_size[1] // (2 ** sub_num)) * \ (img_size[0] // (2 ** sub_num)) @@ -282,50 +284,56 @@ class PatchEmbed(nn.Layer): self.num_patches = num_patches self.embed_dim = embed_dim self.norm = None - if sub_num == 2: - self.proj = nn.Sequential( - ConvBNLayer( - in_channels=in_channels, - out_channels=embed_dim // 2, - kernel_size=3, - stride=2, - padding=1, - act=nn.GELU, - bias_attr=None), - ConvBNLayer( - in_channels=embed_dim // 2, - out_channels=embed_dim, - kernel_size=3, - stride=2, - padding=1, - act=nn.GELU, - bias_attr=None)) - if sub_num == 3: - self.proj = nn.Sequential( - ConvBNLayer( - in_channels=in_channels, - out_channels=embed_dim // 4, - kernel_size=3, - stride=2, - padding=1, - act=nn.GELU, - bias_attr=None), - ConvBNLayer( - in_channels=embed_dim // 4, - out_channels=embed_dim // 2, - kernel_size=3, - stride=2, - padding=1, - act=nn.GELU, - bias_attr=None), - ConvBNLayer( - in_channels=embed_dim // 2, - out_channels=embed_dim, - kernel_size=3, - stride=2, - padding=1, - act=nn.GELU, - bias_attr=None)) + if mode == 'pope': + if sub_num == 2: + self.proj = nn.Sequential( + ConvBNLayer( + in_channels=in_channels, + out_channels=embed_dim // 2, + kernel_size=3, + stride=2, + padding=1, + act=nn.GELU, + bias_attr=None), + ConvBNLayer( + in_channels=embed_dim // 2, + out_channels=embed_dim, + kernel_size=3, + stride=2, + padding=1, + act=nn.GELU, + bias_attr=None)) + if sub_num == 3: + self.proj = nn.Sequential( + ConvBNLayer( + in_channels=in_channels, + out_channels=embed_dim // 4, + kernel_size=3, + stride=2, + padding=1, + act=nn.GELU, + bias_attr=None), + ConvBNLayer( + in_channels=embed_dim // 4, + out_channels=embed_dim // 2, + kernel_size=3, + stride=2, + padding=1, + act=nn.GELU, + bias_attr=None), + ConvBNLayer( + in_channels=embed_dim // 2, + out_channels=embed_dim, + kernel_size=3, + stride=2, + padding=1, + act=nn.GELU, + bias_attr=None)) + elif mode == 'linear': + self.proj = nn.Conv2D( + 1, embed_dim, kernel_size=patch_size, stride=patch_size) + self.num_patches = img_size[0] // patch_size[0] * img_size[ + 1] // patch_size[1] def forward(self, x): B, C, H, W = x.shape diff --git a/ppocr/modeling/backbones/rec_vitstr.py b/ppocr/modeling/backbones/rec_vitstr.py new file mode 100644 index 0000000000..d5d7d5148a --- /dev/null +++ b/ppocr/modeling/backbones/rec_vitstr.py @@ -0,0 +1,120 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +""" +This code is refer from: +https://github.com/roatienza/deep-text-recognition-benchmark/blob/master/modules/vitstr.py +""" + +import numpy as np +import paddle +import paddle.nn as nn +from ppocr.modeling.backbones.rec_svtrnet import Block, PatchEmbed, zeros_, trunc_normal_, ones_ + +scale_dim_heads = {'tiny': [192, 3], 'small': [384, 6], 'base': [768, 12]} + + +class ViTSTR(nn.Layer): + def __init__(self, + img_size=[224, 224], + in_channels=1, + scale='tiny', + seqlen=27, + patch_size=[16, 16], + embed_dim=None, + depth=12, + num_heads=None, + mlp_ratio=4, + qkv_bias=True, + qk_scale=None, + drop_path_rate=0., + drop_rate=0., + attn_drop_rate=0., + norm_layer='nn.LayerNorm', + act_layer='nn.GELU', + epsilon=1e-6, + out_channels=None, + **kwargs): + super().__init__() + self.seqlen = seqlen + embed_dim = embed_dim if embed_dim is not None else scale_dim_heads[ + scale][0] + num_heads = num_heads if num_heads is not None else scale_dim_heads[ + scale][1] + out_channels = out_channels if out_channels is not None else embed_dim + self.patch_embed = PatchEmbed( + img_size=img_size, + in_channels=in_channels, + embed_dim=embed_dim, + patch_size=patch_size, + mode='linear') + num_patches = self.patch_embed.num_patches + + self.pos_embed = self.create_parameter( + shape=[1, num_patches + 1, embed_dim], default_initializer=zeros_) + self.add_parameter("pos_embed", self.pos_embed) + self.cls_token = self.create_parameter( + shape=[1, 1, embed_dim], default_initializer=zeros_) + self.add_parameter("cls_token", self.cls_token) + + self.pos_drop = nn.Dropout(p=drop_rate) + + dpr = np.linspace(0, drop_path_rate, depth) + self.blocks = nn.LayerList([ + Block( + dim=embed_dim, + num_heads=num_heads, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop_rate, + attn_drop=attn_drop_rate, + drop_path=dpr[i], + norm_layer=norm_layer, + act_layer=eval(act_layer), + epsilon=epsilon, + prenorm=False) for i in range(depth) + ]) + self.norm = eval(norm_layer)(embed_dim, epsilon=epsilon) + + self.out_channels = out_channels + + trunc_normal_(self.pos_embed) + trunc_normal_(self.cls_token) + self.apply(self._init_weights) + + def _init_weights(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight) + if isinstance(m, nn.Linear) and m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.LayerNorm): + zeros_(m.bias) + ones_(m.weight) + + def forward_features(self, x): + B = x.shape[0] + x = self.patch_embed(x) + cls_tokens = paddle.tile(self.cls_token, repeat_times=[B, 1, 1]) + x = paddle.concat((cls_tokens, x), axis=1) + x = x + self.pos_embed + x = self.pos_drop(x) + for blk in self.blocks: + x = blk(x) + x = self.norm(x) + return x + + def forward(self, x): + x = self.forward_features(x) + x = x[:, :self.seqlen] + return x.transpose([0, 2, 1]).unsqueeze(2) diff --git a/ppocr/modeling/heads/__init__.py b/ppocr/modeling/heads/__init__.py index 1670ea38e6..14e6aab854 100755 --- a/ppocr/modeling/heads/__init__.py +++ b/ppocr/modeling/heads/__init__.py @@ -33,6 +33,7 @@ def build_head(config): from .rec_aster_head import AsterHead from .rec_pren_head import PRENHead from .rec_multi_head import MultiHead + from .rec_abinet_head import ABINetHead # cls head from .cls_head import ClsHead @@ -46,7 +47,7 @@ def build_head(config): 'DBHead', 'PSEHead', 'FCEHead', 'EASTHead', 'SASTHead', 'CTCHead', 'ClsHead', 'AttentionHead', 'SRNHead', 'PGHead', 'Transformer', 'TableAttentionHead', 'SARHead', 'AsterHead', 'SDMGRHead', 'PRENHead', - 'MultiHead' + 'MultiHead', 'ABINetHead' ] #table head diff --git a/ppocr/modeling/heads/multiheadAttention.py b/ppocr/modeling/heads/multiheadAttention.py deleted file mode 100755 index 900865ba1a..0000000000 --- a/ppocr/modeling/heads/multiheadAttention.py +++ /dev/null @@ -1,163 +0,0 @@ -# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. -# -# 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 paddle -from paddle import nn -import paddle.nn.functional as F -from paddle.nn import Linear -from paddle.nn.initializer import XavierUniform as xavier_uniform_ -from paddle.nn.initializer import Constant as constant_ -from paddle.nn.initializer import XavierNormal as xavier_normal_ - -zeros_ = constant_(value=0.) -ones_ = constant_(value=1.) - - -class MultiheadAttention(nn.Layer): - """Allows the model to jointly attend to information - from different representation subspaces. - See reference: Attention Is All You Need - - .. math:: - \text{MultiHead}(Q, K, V) = \text{Concat}(head_1,\dots,head_h)W^O - \text{where} head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) - - Args: - embed_dim: total dimension of the model - num_heads: parallel attention layers, or heads - - """ - - def __init__(self, - embed_dim, - num_heads, - dropout=0., - bias=True, - add_bias_kv=False, - add_zero_attn=False): - super(MultiheadAttention, self).__init__() - self.embed_dim = embed_dim - self.num_heads = num_heads - self.dropout = dropout - self.head_dim = embed_dim // num_heads - assert self.head_dim * num_heads == self.embed_dim, "embed_dim must be divisible by num_heads" - self.scaling = self.head_dim**-0.5 - self.out_proj = Linear(embed_dim, embed_dim, bias_attr=bias) - self._reset_parameters() - self.conv1 = paddle.nn.Conv2D( - in_channels=embed_dim, out_channels=embed_dim, kernel_size=(1, 1)) - self.conv2 = paddle.nn.Conv2D( - in_channels=embed_dim, out_channels=embed_dim, kernel_size=(1, 1)) - self.conv3 = paddle.nn.Conv2D( - in_channels=embed_dim, out_channels=embed_dim, kernel_size=(1, 1)) - - def _reset_parameters(self): - xavier_uniform_(self.out_proj.weight) - - def forward(self, - query, - key, - value, - key_padding_mask=None, - incremental_state=None, - attn_mask=None): - """ - Inputs of forward function - query: [target length, batch size, embed dim] - key: [sequence length, batch size, embed dim] - value: [sequence length, batch size, embed dim] - key_padding_mask: if True, mask padding based on batch size - incremental_state: if provided, previous time steps are cashed - need_weights: output attn_output_weights - static_kv: key and value are static - - Outputs of forward function - attn_output: [target length, batch size, embed dim] - attn_output_weights: [batch size, target length, sequence length] - """ - q_shape = paddle.shape(query) - src_shape = paddle.shape(key) - q = self._in_proj_q(query) - k = self._in_proj_k(key) - v = self._in_proj_v(value) - q *= self.scaling - q = paddle.transpose( - paddle.reshape( - q, [q_shape[0], q_shape[1], self.num_heads, self.head_dim]), - [1, 2, 0, 3]) - k = paddle.transpose( - paddle.reshape( - k, [src_shape[0], q_shape[1], self.num_heads, self.head_dim]), - [1, 2, 0, 3]) - v = paddle.transpose( - paddle.reshape( - v, [src_shape[0], q_shape[1], self.num_heads, self.head_dim]), - [1, 2, 0, 3]) - if key_padding_mask is not None: - assert key_padding_mask.shape[0] == q_shape[1] - assert key_padding_mask.shape[1] == src_shape[0] - attn_output_weights = paddle.matmul(q, - paddle.transpose(k, [0, 1, 3, 2])) - if attn_mask is not None: - attn_mask = paddle.unsqueeze(paddle.unsqueeze(attn_mask, 0), 0) - attn_output_weights += attn_mask - if key_padding_mask is not None: - attn_output_weights = paddle.reshape( - attn_output_weights, - [q_shape[1], self.num_heads, q_shape[0], src_shape[0]]) - key = paddle.unsqueeze(paddle.unsqueeze(key_padding_mask, 1), 2) - key = paddle.cast(key, 'float32') - y = paddle.full( - shape=paddle.shape(key), dtype='float32', fill_value='-inf') - y = paddle.where(key == 0., key, y) - attn_output_weights += y - attn_output_weights = F.softmax( - attn_output_weights.astype('float32'), - axis=-1, - dtype=paddle.float32 if attn_output_weights.dtype == paddle.float16 - else attn_output_weights.dtype) - attn_output_weights = F.dropout( - attn_output_weights, p=self.dropout, training=self.training) - - attn_output = paddle.matmul(attn_output_weights, v) - attn_output = paddle.reshape( - paddle.transpose(attn_output, [2, 0, 1, 3]), - [q_shape[0], q_shape[1], self.embed_dim]) - attn_output = self.out_proj(attn_output) - - return attn_output - - def _in_proj_q(self, query): - query = paddle.transpose(query, [1, 2, 0]) - query = paddle.unsqueeze(query, axis=2) - res = self.conv1(query) - res = paddle.squeeze(res, axis=2) - res = paddle.transpose(res, [2, 0, 1]) - return res - - def _in_proj_k(self, key): - key = paddle.transpose(key, [1, 2, 0]) - key = paddle.unsqueeze(key, axis=2) - res = self.conv2(key) - res = paddle.squeeze(res, axis=2) - res = paddle.transpose(res, [2, 0, 1]) - return res - - def _in_proj_v(self, value): - value = paddle.transpose(value, [1, 2, 0]) #(1, 2, 0) - value = paddle.unsqueeze(value, axis=2) - res = self.conv3(value) - res = paddle.squeeze(res, axis=2) - res = paddle.transpose(res, [2, 0, 1]) - return res diff --git a/ppocr/modeling/heads/rec_abinet_head.py b/ppocr/modeling/heads/rec_abinet_head.py new file mode 100644 index 0000000000..a0f60f1be1 --- /dev/null +++ b/ppocr/modeling/heads/rec_abinet_head.py @@ -0,0 +1,296 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +""" +This code is refer from: +https://github.com/FangShancheng/ABINet/tree/main/modules +""" + +import math +import paddle +from paddle import nn +import paddle.nn.functional as F +from paddle.nn import LayerList +from ppocr.modeling.heads.rec_nrtr_head import TransformerBlock, PositionalEncoding + + +class BCNLanguage(nn.Layer): + def __init__(self, + d_model=512, + nhead=8, + num_layers=4, + dim_feedforward=2048, + dropout=0., + max_length=25, + detach=True, + num_classes=37): + super().__init__() + + self.d_model = d_model + self.detach = detach + self.max_length = max_length + 1 # additional stop token + self.proj = nn.Linear(num_classes, d_model, bias_attr=False) + self.token_encoder = PositionalEncoding( + dropout=0.1, dim=d_model, max_len=self.max_length) + self.pos_encoder = PositionalEncoding( + dropout=0, dim=d_model, max_len=self.max_length) + + self.decoder = nn.LayerList([ + TransformerBlock( + d_model=d_model, + nhead=nhead, + dim_feedforward=dim_feedforward, + attention_dropout_rate=dropout, + residual_dropout_rate=dropout, + with_self_attn=False, + with_cross_attn=True) for i in range(num_layers) + ]) + + self.cls = nn.Linear(d_model, num_classes) + + def forward(self, tokens, lengths): + """ + Args: + tokens: (B, N, C) where N is length, B is batch size and C is classes number + lengths: (B,) + """ + if self.detach: tokens = tokens.detach() + embed = self.proj(tokens) # (B, N, C) + embed = self.token_encoder(embed) # (B, N, C) + padding_mask = _get_mask(lengths, self.max_length) + zeros = paddle.zeros_like(embed) # (B, N, C) + qeury = self.pos_encoder(zeros) + for decoder_layer in self.decoder: + qeury = decoder_layer(qeury, embed, cross_mask=padding_mask) + output = qeury # (B, N, C) + + logits = self.cls(output) # (B, N, C) + + return output, logits + + +def encoder_layer(in_c, out_c, k=3, s=2, p=1): + return nn.Sequential( + nn.Conv2D(in_c, out_c, k, s, p), nn.BatchNorm2D(out_c), nn.ReLU()) + + +def decoder_layer(in_c, + out_c, + k=3, + s=1, + p=1, + mode='nearest', + scale_factor=None, + size=None): + align_corners = False if mode == 'nearest' else True + return nn.Sequential( + nn.Upsample( + size=size, + scale_factor=scale_factor, + mode=mode, + align_corners=align_corners), + nn.Conv2D(in_c, out_c, k, s, p), + nn.BatchNorm2D(out_c), + nn.ReLU()) + + +class PositionAttention(nn.Layer): + def __init__(self, + max_length, + in_channels=512, + num_channels=64, + h=8, + w=32, + mode='nearest', + **kwargs): + super().__init__() + self.max_length = max_length + self.k_encoder = nn.Sequential( + encoder_layer( + in_channels, num_channels, s=(1, 2)), + encoder_layer( + num_channels, num_channels, s=(2, 2)), + encoder_layer( + num_channels, num_channels, s=(2, 2)), + encoder_layer( + num_channels, num_channels, s=(2, 2))) + self.k_decoder = nn.Sequential( + decoder_layer( + num_channels, num_channels, scale_factor=2, mode=mode), + decoder_layer( + num_channels, num_channels, scale_factor=2, mode=mode), + decoder_layer( + num_channels, num_channels, scale_factor=2, mode=mode), + decoder_layer( + num_channels, in_channels, size=(h, w), mode=mode)) + + self.pos_encoder = PositionalEncoding( + dropout=0, dim=in_channels, max_len=max_length) + self.project = nn.Linear(in_channels, in_channels) + + def forward(self, x): + B, C, H, W = x.shape + k, v = x, x + + # calculate key vector + features = [] + for i in range(0, len(self.k_encoder)): + k = self.k_encoder[i](k) + features.append(k) + for i in range(0, len(self.k_decoder) - 1): + k = self.k_decoder[i](k) + # print(k.shape, features[len(self.k_decoder) - 2 - i].shape) + k = k + features[len(self.k_decoder) - 2 - i] + k = self.k_decoder[-1](k) + + # calculate query vector + # TODO q=f(q,k) + zeros = paddle.zeros( + (B, self.max_length, C), dtype=x.dtype) # (T, N, C) + q = self.pos_encoder(zeros) # (B, N, C) + q = self.project(q) # (B, N, C) + + # calculate attention + attn_scores = q @k.flatten(2) # (B, N, (H*W)) + attn_scores = attn_scores / (C**0.5) + attn_scores = F.softmax(attn_scores, axis=-1) + + v = v.flatten(2).transpose([0, 2, 1]) # (B, (H*W), C) + attn_vecs = attn_scores @v # (B, N, C) + + return attn_vecs, attn_scores.reshape([0, self.max_length, H, W]) + + +class ABINetHead(nn.Layer): + def __init__(self, + in_channels, + out_channels, + d_model=512, + nhead=8, + num_layers=3, + dim_feedforward=2048, + dropout=0.1, + max_length=25, + use_lang=False, + iter_size=1): + super().__init__() + self.max_length = max_length + 1 + self.pos_encoder = PositionalEncoding( + dropout=0.1, dim=d_model, max_len=8 * 32) + self.encoder = nn.LayerList([ + TransformerBlock( + d_model=d_model, + nhead=nhead, + dim_feedforward=dim_feedforward, + attention_dropout_rate=dropout, + residual_dropout_rate=dropout, + with_self_attn=True, + with_cross_attn=False) for i in range(num_layers) + ]) + self.decoder = PositionAttention( + max_length=max_length + 1, # additional stop token + mode='nearest', ) + self.out_channels = out_channels + self.cls = nn.Linear(d_model, self.out_channels) + self.use_lang = use_lang + if use_lang: + self.iter_size = iter_size + self.language = BCNLanguage( + d_model=d_model, + nhead=nhead, + num_layers=4, + dim_feedforward=dim_feedforward, + dropout=dropout, + max_length=max_length, + num_classes=self.out_channels) + # alignment + self.w_att_align = nn.Linear(2 * d_model, d_model) + self.cls_align = nn.Linear(d_model, self.out_channels) + + def forward(self, x, targets=None): + x = x.transpose([0, 2, 3, 1]) + _, H, W, C = x.shape + feature = x.flatten(1, 2) + feature = self.pos_encoder(feature) + for encoder_layer in self.encoder: + feature = encoder_layer(feature) + feature = feature.reshape([0, H, W, C]).transpose([0, 3, 1, 2]) + v_feature, attn_scores = self.decoder( + feature) # (B, N, C), (B, C, H, W) + vis_logits = self.cls(v_feature) # (B, N, C) + logits = vis_logits + vis_lengths = _get_length(vis_logits) + if self.use_lang: + align_logits = vis_logits + align_lengths = vis_lengths + all_l_res, all_a_res = [], [] + for i in range(self.iter_size): + tokens = F.softmax(align_logits, axis=-1) + lengths = align_lengths + lengths = paddle.clip( + lengths, 2, self.max_length) # TODO:move to langauge model + l_feature, l_logits = self.language(tokens, lengths) + + # alignment + all_l_res.append(l_logits) + fuse = paddle.concat((l_feature, v_feature), -1) + f_att = F.sigmoid(self.w_att_align(fuse)) + output = f_att * v_feature + (1 - f_att) * l_feature + align_logits = self.cls_align(output) # (B, N, C) + + align_lengths = _get_length(align_logits) + all_a_res.append(align_logits) + if self.training: + return { + 'align': all_a_res, + 'lang': all_l_res, + 'vision': vis_logits + } + else: + logits = align_logits + if self.training: + return logits + else: + return F.softmax(logits, -1) + + +def _get_length(logit): + """ Greed decoder to obtain length from logit""" + out = (logit.argmax(-1) == 0) + abn = out.any(-1) + out_int = out.cast('int32') + out = (out_int.cumsum(-1) == 1) & out + out = out.cast('int32') + out = out.argmax(-1) + out = out + 1 + out = paddle.where(abn, out, paddle.to_tensor(logit.shape[1])) + return out + + +def _get_mask(length, max_length): + """Generate a square mask for the sequence. The masked positions are filled with float('-inf'). + Unmasked positions are filled with float(0.0). + """ + length = length.unsqueeze(-1) + B = paddle.shape(length)[0] + grid = paddle.arange(0, max_length).unsqueeze(0).tile([B, 1]) + zero_mask = paddle.zeros([B, max_length], dtype='float32') + inf_mask = paddle.full([B, max_length], '-inf', dtype='float32') + diag_mask = paddle.diag( + paddle.full( + [max_length], '-inf', dtype=paddle.float32), + offset=0, + name=None) + mask = paddle.where(grid >= length, inf_mask, zero_mask) + mask = mask.unsqueeze(1) + diag_mask + return mask.unsqueeze(1) diff --git a/ppocr/modeling/heads/rec_nrtr_head.py b/ppocr/modeling/heads/rec_nrtr_head.py index 38ba0c9178..bf9ef56145 100644 --- a/ppocr/modeling/heads/rec_nrtr_head.py +++ b/ppocr/modeling/heads/rec_nrtr_head.py @@ -14,20 +14,15 @@ import math import paddle -import copy from paddle import nn import paddle.nn.functional as F from paddle.nn import LayerList -from paddle.nn.initializer import XavierNormal as xavier_uniform_ -from paddle.nn import Dropout, Linear, LayerNorm, Conv2D +# from paddle.nn.initializer import XavierNormal as xavier_uniform_ +from paddle.nn import Dropout, Linear, LayerNorm import numpy as np -from ppocr.modeling.heads.multiheadAttention import MultiheadAttention -from paddle.nn.initializer import Constant as constant_ +from ppocr.modeling.backbones.rec_svtrnet import Mlp, zeros_, ones_ from paddle.nn.initializer import XavierNormal as xavier_normal_ -zeros_ = constant_(value=0.) -ones_ = constant_(value=1.) - class Transformer(nn.Layer): """A transformer model. User is able to modify the attributes as needed. The architechture @@ -45,7 +40,6 @@ class Transformer(nn.Layer): dropout: the dropout value (default=0.1). custom_encoder: custom encoder (default=None). custom_decoder: custom decoder (default=None). - """ def __init__(self, @@ -54,45 +48,49 @@ class Transformer(nn.Layer): num_encoder_layers=6, beam_size=0, num_decoder_layers=6, + max_len=25, dim_feedforward=1024, attention_dropout_rate=0.0, residual_dropout_rate=0.1, - custom_encoder=None, - custom_decoder=None, in_channels=0, out_channels=0, scale_embedding=True): super(Transformer, self).__init__() self.out_channels = out_channels + 1 + self.max_len = max_len self.embedding = Embeddings( d_model=d_model, vocab=self.out_channels, padding_idx=0, scale_embedding=scale_embedding) self.positional_encoding = PositionalEncoding( - dropout=residual_dropout_rate, - dim=d_model, ) - if custom_encoder is not None: - self.encoder = custom_encoder - else: - if num_encoder_layers > 0: - encoder_layer = TransformerEncoderLayer( - d_model, nhead, dim_feedforward, attention_dropout_rate, - residual_dropout_rate) - self.encoder = TransformerEncoder(encoder_layer, - num_encoder_layers) - else: - self.encoder = None + dropout=residual_dropout_rate, dim=d_model) - if custom_decoder is not None: - self.decoder = custom_decoder + if num_encoder_layers > 0: + self.encoder = nn.LayerList([ + TransformerBlock( + d_model, + nhead, + dim_feedforward, + attention_dropout_rate, + residual_dropout_rate, + with_self_attn=True, + with_cross_attn=False) for i in range(num_encoder_layers) + ]) else: - decoder_layer = TransformerDecoderLayer( - d_model, nhead, dim_feedforward, attention_dropout_rate, - residual_dropout_rate) - self.decoder = TransformerDecoder(decoder_layer, num_decoder_layers) + self.encoder = None + + self.decoder = nn.LayerList([ + TransformerBlock( + d_model, + nhead, + dim_feedforward, + attention_dropout_rate, + residual_dropout_rate, + with_self_attn=True, + with_cross_attn=True) for i in range(num_decoder_layers) + ]) - self._reset_parameters() self.beam_size = beam_size self.d_model = d_model self.nhead = nhead @@ -105,7 +103,7 @@ class Transformer(nn.Layer): def _init_weights(self, m): - if isinstance(m, nn.Conv2D): + if isinstance(m, nn.Linear): xavier_normal_(m.weight) if m.bias is not None: zeros_(m.bias) @@ -113,24 +111,20 @@ class Transformer(nn.Layer): def forward_train(self, src, tgt): tgt = tgt[:, :-1] - tgt_key_padding_mask = self.generate_padding_mask(tgt) - tgt = self.embedding(tgt).transpose([1, 0, 2]) + tgt = self.embedding(tgt) tgt = self.positional_encoding(tgt) - tgt_mask = self.generate_square_subsequent_mask(tgt.shape[0]) + tgt_mask = self.generate_square_subsequent_mask(tgt.shape[1]) if self.encoder is not None: - src = self.positional_encoding(src.transpose([1, 0, 2])) - memory = self.encoder(src) + src = self.positional_encoding(src) + for encoder_layer in self.encoder: + src = encoder_layer(src) + memory = src # B N C else: - memory = src.squeeze(2).transpose([2, 0, 1]) - output = self.decoder( - tgt, - memory, - tgt_mask=tgt_mask, - memory_mask=None, - tgt_key_padding_mask=tgt_key_padding_mask, - memory_key_padding_mask=None) - output = output.transpose([1, 0, 2]) + memory = src # B N C + for decoder_layer in self.decoder: + tgt = decoder_layer(tgt, memory, self_mask=tgt_mask) + output = tgt logit = self.tgt_word_prj(output) return logit @@ -140,8 +134,8 @@ class Transformer(nn.Layer): src: the sequence to the encoder (required). tgt: the sequence to the decoder (required). Shape: - - src: :math:`(S, N, E)`. - - tgt: :math:`(T, N, E)`. + - src: :math:`(B, sN, C)`. + - tgt: :math:`(B, tN, C)`. Examples: >>> output = transformer_model(src, tgt) """ @@ -157,36 +151,35 @@ class Transformer(nn.Layer): return self.forward_test(src) def forward_test(self, src): + bs = paddle.shape(src)[0] if self.encoder is not None: - src = self.positional_encoding(paddle.transpose(src, [1, 0, 2])) - memory = self.encoder(src) + src = self.positional_encoding(src) + for encoder_layer in self.encoder: + src = encoder_layer(src) + memory = src # B N C else: - memory = paddle.transpose(paddle.squeeze(src, 2), [2, 0, 1]) + memory = src dec_seq = paddle.full((bs, 1), 2, dtype=paddle.int64) dec_prob = paddle.full((bs, 1), 1., dtype=paddle.float32) - for len_dec_seq in range(1, 25): - dec_seq_embed = paddle.transpose(self.embedding(dec_seq), [1, 0, 2]) + for len_dec_seq in range(1, self.max_len): + dec_seq_embed = self.embedding(dec_seq) dec_seq_embed = self.positional_encoding(dec_seq_embed) tgt_mask = self.generate_square_subsequent_mask( - paddle.shape(dec_seq_embed)[0]) - output = self.decoder( - dec_seq_embed, - memory, - tgt_mask=tgt_mask, - memory_mask=None, - tgt_key_padding_mask=None, - memory_key_padding_mask=None) - dec_output = paddle.transpose(output, [1, 0, 2]) + paddle.shape(dec_seq_embed)[1]) + tgt = dec_seq_embed + for decoder_layer in self.decoder: + tgt = decoder_layer(tgt, memory, self_mask=tgt_mask) + dec_output = tgt dec_output = dec_output[:, -1, :] - word_prob = F.softmax(self.tgt_word_prj(dec_output), axis=1) - preds_idx = paddle.argmax(word_prob, axis=1) + word_prob = F.softmax(self.tgt_word_prj(dec_output), axis=-1) + preds_idx = paddle.argmax(word_prob, axis=-1) if paddle.equal_all( preds_idx, paddle.full( paddle.shape(preds_idx), 3, dtype='int64')): break - preds_prob = paddle.max(word_prob, axis=1) + preds_prob = paddle.max(word_prob, axis=-1) dec_seq = paddle.concat( [dec_seq, paddle.reshape(preds_idx, [-1, 1])], axis=1) dec_prob = paddle.concat( @@ -194,10 +187,10 @@ class Transformer(nn.Layer): return [dec_seq, dec_prob] def forward_beam(self, images): - ''' Translation work in one batch ''' + """ Translation work in one batch """ def get_inst_idx_to_tensor_position_map(inst_idx_list): - ''' Indicate the position of an instance in a tensor. ''' + """ Indicate the position of an instance in a tensor. """ return { inst_idx: tensor_position for tensor_position, inst_idx in enumerate(inst_idx_list) @@ -205,7 +198,7 @@ class Transformer(nn.Layer): def collect_active_part(beamed_tensor, curr_active_inst_idx, n_prev_active_inst, n_bm): - ''' Collect tensor parts associated to active instances. ''' + """ Collect tensor parts associated to active instances. """ beamed_tensor_shape = paddle.shape(beamed_tensor) n_curr_active_inst = len(curr_active_inst_idx) @@ -237,9 +230,8 @@ class Transformer(nn.Layer): return active_src_enc, active_inst_idx_to_position_map def beam_decode_step(inst_dec_beams, len_dec_seq, enc_output, - inst_idx_to_position_map, n_bm, - memory_key_padding_mask): - ''' Decode and update beam status, and then return active beam idx ''' + inst_idx_to_position_map, n_bm): + """ Decode and update beam status, and then return active beam idx """ def prepare_beam_dec_seq(inst_dec_beams, len_dec_seq): dec_partial_seq = [ @@ -249,19 +241,15 @@ class Transformer(nn.Layer): dec_partial_seq = dec_partial_seq.reshape([-1, len_dec_seq]) return dec_partial_seq - def predict_word(dec_seq, enc_output, n_active_inst, n_bm, - memory_key_padding_mask): - dec_seq = paddle.transpose(self.embedding(dec_seq), [1, 0, 2]) + def predict_word(dec_seq, enc_output, n_active_inst, n_bm): + dec_seq = self.embedding(dec_seq) dec_seq = self.positional_encoding(dec_seq) tgt_mask = self.generate_square_subsequent_mask( - paddle.shape(dec_seq)[0]) - dec_output = self.decoder( - dec_seq, - enc_output, - tgt_mask=tgt_mask, - tgt_key_padding_mask=None, - memory_key_padding_mask=memory_key_padding_mask, ) - dec_output = paddle.transpose(dec_output, [1, 0, 2]) + paddle.shape(dec_seq)[1]) + tgt = dec_seq + for decoder_layer in self.decoder: + tgt = decoder_layer(tgt, enc_output, self_mask=tgt_mask) + dec_output = tgt dec_output = dec_output[:, -1, :] # Pick the last step: (bh * bm) * d_h word_prob = F.softmax(self.tgt_word_prj(dec_output), axis=1) @@ -281,8 +269,7 @@ class Transformer(nn.Layer): n_active_inst = len(inst_idx_to_position_map) dec_seq = prepare_beam_dec_seq(inst_dec_beams, len_dec_seq) - word_prob = predict_word(dec_seq, enc_output, n_active_inst, n_bm, - None) + word_prob = predict_word(dec_seq, enc_output, n_active_inst, n_bm) # Update the beam with predicted word prob information and collect incomplete instances active_inst_idx_list = collect_active_inst_idx_list( inst_dec_beams, word_prob, inst_idx_to_position_map) @@ -303,10 +290,10 @@ class Transformer(nn.Layer): with paddle.no_grad(): #-- Encode if self.encoder is not None: - src = self.positional_encoding(images.transpose([1, 0, 2])) + src = self.positional_encoding(images) src_enc = self.encoder(src) else: - src_enc = images.squeeze(2).transpose([0, 2, 1]) + src_enc = images n_bm = self.beam_size src_shape = paddle.shape(src_enc) @@ -317,11 +304,11 @@ class Transformer(nn.Layer): inst_idx_to_position_map = get_inst_idx_to_tensor_position_map( active_inst_idx_list) # Decode - for len_dec_seq in range(1, 25): + for len_dec_seq in range(1, self.max_len): src_enc_copy = src_enc.clone() active_inst_idx_list = beam_decode_step( inst_dec_beams, len_dec_seq, src_enc_copy, - inst_idx_to_position_map, n_bm, None) + inst_idx_to_position_map, n_bm) if not active_inst_idx_list: break # all instances have finished their path to src_enc, inst_idx_to_position_map = collate_active_info( @@ -354,261 +341,124 @@ class Transformer(nn.Layer): shape=[sz, sz], dtype='float32', fill_value='-inf'), diagonal=1) mask = mask + mask_inf - return mask - - def generate_padding_mask(self, x): - padding_mask = paddle.equal(x, paddle.to_tensor(0, dtype=x.dtype)) - return padding_mask - - def _reset_parameters(self): - """Initiate parameters in the transformer model.""" - - for p in self.parameters(): - if p.dim() > 1: - xavier_uniform_(p) + return mask.unsqueeze([0, 1]) -class TransformerEncoder(nn.Layer): - """TransformerEncoder is a stack of N encoder layers - Args: - encoder_layer: an instance of the TransformerEncoderLayer() class (required). - num_layers: the number of sub-encoder-layers in the encoder (required). - norm: the layer normalization component (optional). - """ +class MultiheadAttention(nn.Layer): + """Allows the model to jointly attend to information + from different representation subspaces. + See reference: Attention Is All You Need - def __init__(self, encoder_layer, num_layers): - super(TransformerEncoder, self).__init__() - self.layers = _get_clones(encoder_layer, num_layers) - self.num_layers = num_layers - - def forward(self, src): - """Pass the input through the endocder layers in turn. - Args: - src: the sequnce to the encoder (required). - mask: the mask for the src sequence (optional). - src_key_padding_mask: the mask for the src keys per batch (optional). - """ - output = src - - for i in range(self.num_layers): - output = self.layers[i](output, - src_mask=None, - src_key_padding_mask=None) - - return output - - -class TransformerDecoder(nn.Layer): - """TransformerDecoder is a stack of N decoder layers + .. math:: + \text{MultiHead}(Q, K, V) = \text{Concat}(head_1,\dots,head_h)W^O + \text{where} head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) Args: - decoder_layer: an instance of the TransformerDecoderLayer() class (required). - num_layers: the number of sub-decoder-layers in the decoder (required). - norm: the layer normalization component (optional). + embed_dim: total dimension of the model + num_heads: parallel attention layers, or heads """ - def __init__(self, decoder_layer, num_layers): - super(TransformerDecoder, self).__init__() - self.layers = _get_clones(decoder_layer, num_layers) - self.num_layers = num_layers + def __init__(self, embed_dim, num_heads, dropout=0., self_attn=False): + super(MultiheadAttention, self).__init__() + self.embed_dim = embed_dim + self.num_heads = num_heads + # self.dropout = dropout + self.head_dim = embed_dim // num_heads + assert self.head_dim * num_heads == self.embed_dim, "embed_dim must be divisible by num_heads" + self.scale = self.head_dim**-0.5 + self.self_attn = self_attn + if self_attn: + self.qkv = nn.Linear(embed_dim, embed_dim * 3) + else: + self.q = nn.Linear(embed_dim, embed_dim) + self.kv = nn.Linear(embed_dim, embed_dim * 2) + self.attn_drop = nn.Dropout(dropout) + self.out_proj = nn.Linear(embed_dim, embed_dim) - def forward(self, - tgt, - memory, - tgt_mask=None, - memory_mask=None, - tgt_key_padding_mask=None, - memory_key_padding_mask=None): - """Pass the inputs (and mask) through the decoder layer in turn. + def forward(self, query, key=None, attn_mask=None): - Args: - tgt: the sequence to the decoder (required). - memory: the sequnce from the last layer of the encoder (required). - tgt_mask: the mask for the tgt sequence (optional). - memory_mask: the mask for the memory sequence (optional). - tgt_key_padding_mask: the mask for the tgt keys per batch (optional). - memory_key_padding_mask: the mask for the memory keys per batch (optional). - """ - output = tgt - for i in range(self.num_layers): - output = self.layers[i]( - output, - memory, - tgt_mask=tgt_mask, - memory_mask=memory_mask, - tgt_key_padding_mask=tgt_key_padding_mask, - memory_key_padding_mask=memory_key_padding_mask) + qN = query.shape[1] - return output + if self.self_attn: + qkv = self.qkv(query).reshape( + (0, qN, 3, self.num_heads, self.head_dim)).transpose( + (2, 0, 3, 1, 4)) + q, k, v = qkv[0], qkv[1], qkv[2] + else: + kN = key.shape[1] + q = self.q(query).reshape( + [0, qN, self.num_heads, self.head_dim]).transpose([0, 2, 1, 3]) + kv = self.kv(key).reshape( + (0, kN, 2, self.num_heads, self.head_dim)).transpose( + (2, 0, 3, 1, 4)) + k, v = kv[0], kv[1] + + attn = (q.matmul(k.transpose((0, 1, 3, 2)))) * self.scale + + if attn_mask is not None: + attn += attn_mask + + attn = F.softmax(attn, axis=-1) + attn = self.attn_drop(attn) + + x = (attn.matmul(v)).transpose((0, 2, 1, 3)).reshape( + (0, qN, self.embed_dim)) + x = self.out_proj(x) + + return x -class TransformerEncoderLayer(nn.Layer): - """TransformerEncoderLayer is made up of self-attn and feedforward network. - This standard encoder layer is based on the paper "Attention Is All You Need". - Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez, - Lukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In Advances in - Neural Information Processing Systems, pages 6000-6010. Users may modify or implement - in a different way during application. - - Args: - d_model: the number of expected features in the input (required). - nhead: the number of heads in the multiheadattention models (required). - dim_feedforward: the dimension of the feedforward network model (default=2048). - dropout: the dropout value (default=0.1). - - """ - +class TransformerBlock(nn.Layer): def __init__(self, d_model, nhead, dim_feedforward=2048, attention_dropout_rate=0.0, - residual_dropout_rate=0.1): - super(TransformerEncoderLayer, self).__init__() - self.self_attn = MultiheadAttention( - d_model, nhead, dropout=attention_dropout_rate) + residual_dropout_rate=0.1, + with_self_attn=True, + with_cross_attn=False, + epsilon=1e-5): + super(TransformerBlock, self).__init__() + self.with_self_attn = with_self_attn + if with_self_attn: + self.self_attn = MultiheadAttention( + d_model, + nhead, + dropout=attention_dropout_rate, + self_attn=with_self_attn) + self.norm1 = LayerNorm(d_model, epsilon=epsilon) + self.dropout1 = Dropout(residual_dropout_rate) + self.with_cross_attn = with_cross_attn + if with_cross_attn: + self.cross_attn = MultiheadAttention( #for self_attn of encoder or cross_attn of decoder + d_model, + nhead, + dropout=attention_dropout_rate) + self.norm2 = LayerNorm(d_model, epsilon=epsilon) + self.dropout2 = Dropout(residual_dropout_rate) - self.conv1 = Conv2D( - in_channels=d_model, - out_channels=dim_feedforward, - kernel_size=(1, 1)) - self.conv2 = Conv2D( - in_channels=dim_feedforward, - out_channels=d_model, - kernel_size=(1, 1)) + self.mlp = Mlp(in_features=d_model, + hidden_features=dim_feedforward, + act_layer=nn.ReLU, + drop=residual_dropout_rate) - self.norm1 = LayerNorm(d_model) - self.norm2 = LayerNorm(d_model) - self.dropout1 = Dropout(residual_dropout_rate) - self.dropout2 = Dropout(residual_dropout_rate) + self.norm3 = LayerNorm(d_model, epsilon=epsilon) - def forward(self, src, src_mask=None, src_key_padding_mask=None): - """Pass the input through the endocder layer. - Args: - src: the sequnce to the encoder layer (required). - src_mask: the mask for the src sequence (optional). - src_key_padding_mask: the mask for the src keys per batch (optional). - """ - src2 = self.self_attn( - src, - src, - src, - attn_mask=src_mask, - key_padding_mask=src_key_padding_mask) - src = src + self.dropout1(src2) - src = self.norm1(src) - - src = paddle.transpose(src, [1, 2, 0]) - src = paddle.unsqueeze(src, 2) - src2 = self.conv2(F.relu(self.conv1(src))) - src2 = paddle.squeeze(src2, 2) - src2 = paddle.transpose(src2, [2, 0, 1]) - src = paddle.squeeze(src, 2) - src = paddle.transpose(src, [2, 0, 1]) - - src = src + self.dropout2(src2) - src = self.norm2(src) - return src - - -class TransformerDecoderLayer(nn.Layer): - """TransformerDecoderLayer is made up of self-attn, multi-head-attn and feedforward network. - This standard decoder layer is based on the paper "Attention Is All You Need". - Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez, - Lukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In Advances in - Neural Information Processing Systems, pages 6000-6010. Users may modify or implement - in a different way during application. - - Args: - d_model: the number of expected features in the input (required). - nhead: the number of heads in the multiheadattention models (required). - dim_feedforward: the dimension of the feedforward network model (default=2048). - dropout: the dropout value (default=0.1). - - """ - - def __init__(self, - d_model, - nhead, - dim_feedforward=2048, - attention_dropout_rate=0.0, - residual_dropout_rate=0.1): - super(TransformerDecoderLayer, self).__init__() - self.self_attn = MultiheadAttention( - d_model, nhead, dropout=attention_dropout_rate) - self.multihead_attn = MultiheadAttention( - d_model, nhead, dropout=attention_dropout_rate) - - self.conv1 = Conv2D( - in_channels=d_model, - out_channels=dim_feedforward, - kernel_size=(1, 1)) - self.conv2 = Conv2D( - in_channels=dim_feedforward, - out_channels=d_model, - kernel_size=(1, 1)) - - self.norm1 = LayerNorm(d_model) - self.norm2 = LayerNorm(d_model) - self.norm3 = LayerNorm(d_model) - self.dropout1 = Dropout(residual_dropout_rate) - self.dropout2 = Dropout(residual_dropout_rate) self.dropout3 = Dropout(residual_dropout_rate) - def forward(self, - tgt, - memory, - tgt_mask=None, - memory_mask=None, - tgt_key_padding_mask=None, - memory_key_padding_mask=None): - """Pass the inputs (and mask) through the decoder layer. + def forward(self, tgt, memory=None, self_mask=None, cross_mask=None): + if self.with_self_attn: + tgt1 = self.self_attn(tgt, attn_mask=self_mask) + tgt = self.norm1(tgt + self.dropout1(tgt1)) - Args: - tgt: the sequence to the decoder layer (required). - memory: the sequnce from the last layer of the encoder (required). - tgt_mask: the mask for the tgt sequence (optional). - memory_mask: the mask for the memory sequence (optional). - tgt_key_padding_mask: the mask for the tgt keys per batch (optional). - memory_key_padding_mask: the mask for the memory keys per batch (optional). - - """ - tgt2 = self.self_attn( - tgt, - tgt, - tgt, - attn_mask=tgt_mask, - key_padding_mask=tgt_key_padding_mask) - tgt = tgt + self.dropout1(tgt2) - tgt = self.norm1(tgt) - tgt2 = self.multihead_attn( - tgt, - memory, - memory, - attn_mask=memory_mask, - key_padding_mask=memory_key_padding_mask) - tgt = tgt + self.dropout2(tgt2) - tgt = self.norm2(tgt) - - # default - tgt = paddle.transpose(tgt, [1, 2, 0]) - tgt = paddle.unsqueeze(tgt, 2) - tgt2 = self.conv2(F.relu(self.conv1(tgt))) - tgt2 = paddle.squeeze(tgt2, 2) - tgt2 = paddle.transpose(tgt2, [2, 0, 1]) - tgt = paddle.squeeze(tgt, 2) - tgt = paddle.transpose(tgt, [2, 0, 1]) - - tgt = tgt + self.dropout3(tgt2) - tgt = self.norm3(tgt) + if self.with_cross_attn: + tgt2 = self.cross_attn(tgt, key=memory, attn_mask=cross_mask) + tgt = self.norm2(tgt + self.dropout2(tgt2)) + tgt = self.norm3(tgt + self.dropout3(self.mlp(tgt))) return tgt -def _get_clones(module, N): - return LayerList([copy.deepcopy(module) for i in range(N)]) - - class PositionalEncoding(nn.Layer): """Inject some information about the relative or absolute position of the tokens in the sequence. The positional encodings have the same dimension as @@ -651,8 +501,9 @@ class PositionalEncoding(nn.Layer): Examples: >>> output = pos_encoder(x) """ + x = x.transpose([1, 0, 2]) x = x + self.pe[:paddle.shape(x)[0], :] - return self.dropout(x) + return self.dropout(x).transpose([1, 0, 2]) class PositionalEncoding_2d(nn.Layer): @@ -725,7 +576,7 @@ class PositionalEncoding_2d(nn.Layer): class Embeddings(nn.Layer): - def __init__(self, d_model, vocab, padding_idx, scale_embedding): + def __init__(self, d_model, vocab, padding_idx=None, scale_embedding=True): super(Embeddings, self).__init__() self.embedding = nn.Embedding(vocab, d_model, padding_idx=padding_idx) w0 = np.random.normal(0.0, d_model**-0.5, @@ -742,7 +593,7 @@ class Embeddings(nn.Layer): class Beam(): - ''' Beam search ''' + """ Beam search """ def __init__(self, size, device=False): diff --git a/ppocr/postprocess/__init__.py b/ppocr/postprocess/__init__.py index f50b5f1c5f..2635117c84 100644 --- a/ppocr/postprocess/__init__.py +++ b/ppocr/postprocess/__init__.py @@ -27,7 +27,7 @@ from .sast_postprocess import SASTPostProcess from .fce_postprocess import FCEPostProcess from .rec_postprocess import CTCLabelDecode, AttnLabelDecode, SRNLabelDecode, \ DistillationCTCLabelDecode, TableLabelDecode, NRTRLabelDecode, SARLabelDecode, \ - SEEDLabelDecode, PRENLabelDecode + SEEDLabelDecode, PRENLabelDecode, ViTSTRLabelDecode, ABINetLabelDecode from .cls_postprocess import ClsPostProcess from .pg_postprocess import PGPostProcess from .vqa_token_ser_layoutlm_postprocess import VQASerTokenLayoutLMPostProcess @@ -42,7 +42,7 @@ def build_post_process(config, global_config=None): 'DistillationDBPostProcess', 'NRTRLabelDecode', 'SARLabelDecode', 'SEEDLabelDecode', 'VQASerTokenLayoutLMPostProcess', 'VQAReTokenLayoutLMPostProcess', 'PRENLabelDecode', - 'DistillationSARLabelDecode' + 'DistillationSARLabelDecode', 'ViTSTRLabelDecode', 'ABINetLabelDecode' ] if config['name'] == 'PSEPostProcess': diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index bf0fd890bf..c77420ad19 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -140,70 +140,6 @@ class DistillationCTCLabelDecode(CTCLabelDecode): return output -class NRTRLabelDecode(BaseRecLabelDecode): - """ Convert between text-label and text-index """ - - def __init__(self, character_dict_path=None, use_space_char=True, **kwargs): - super(NRTRLabelDecode, self).__init__(character_dict_path, - use_space_char) - - def __call__(self, preds, label=None, *args, **kwargs): - - if len(preds) == 2: - preds_id = preds[0] - preds_prob = preds[1] - if isinstance(preds_id, paddle.Tensor): - preds_id = preds_id.numpy() - if isinstance(preds_prob, paddle.Tensor): - preds_prob = preds_prob.numpy() - if preds_id[0][0] == 2: - preds_idx = preds_id[:, 1:] - preds_prob = preds_prob[:, 1:] - else: - preds_idx = preds_id - text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) - if label is None: - return text - label = self.decode(label[:, 1:]) - else: - if isinstance(preds, paddle.Tensor): - preds = preds.numpy() - preds_idx = preds.argmax(axis=2) - preds_prob = preds.max(axis=2) - text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) - if label is None: - return text - label = self.decode(label[:, 1:]) - return text, label - - def add_special_char(self, dict_character): - dict_character = ['blank', '', '', ''] + dict_character - return dict_character - - def decode(self, text_index, text_prob=None, is_remove_duplicate=False): - """ convert text-index into text-label. """ - result_list = [] - batch_size = len(text_index) - for batch_idx in range(batch_size): - char_list = [] - conf_list = [] - for idx in range(len(text_index[batch_idx])): - if text_index[batch_idx][idx] == 3: # end - break - try: - char_list.append(self.character[int(text_index[batch_idx][ - idx])]) - except: - continue - if text_prob is not None: - conf_list.append(text_prob[batch_idx][idx]) - else: - conf_list.append(1) - text = ''.join(char_list) - result_list.append((text.lower(), np.mean(conf_list).tolist())) - return result_list - - class AttnLabelDecode(BaseRecLabelDecode): """ Convert between text-label and text-index """ @@ -752,3 +688,122 @@ class PRENLabelDecode(BaseRecLabelDecode): return text label = self.decode(label) return text, label + + +class NRTRLabelDecode(BaseRecLabelDecode): + """ Convert between text-label and text-index """ + + def __init__(self, character_dict_path=None, use_space_char=True, **kwargs): + super(NRTRLabelDecode, self).__init__(character_dict_path, + use_space_char) + + def __call__(self, preds, label=None, *args, **kwargs): + + if len(preds) == 2: + preds_id = preds[0] + preds_prob = preds[1] + if isinstance(preds_id, paddle.Tensor): + preds_id = preds_id.numpy() + if isinstance(preds_prob, paddle.Tensor): + preds_prob = preds_prob.numpy() + if preds_id[0][0] == 2: + preds_idx = preds_id[:, 1:] + preds_prob = preds_prob[:, 1:] + else: + preds_idx = preds_id + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) + if label is None: + return text + label = self.decode(label[:, 1:]) + else: + if isinstance(preds, paddle.Tensor): + preds = preds.numpy() + preds_idx = preds.argmax(axis=2) + preds_prob = preds.max(axis=2) + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) + if label is None: + return text + label = self.decode(label[:, 1:]) + return text, label + + def add_special_char(self, dict_character): + dict_character = ['blank', '', '', ''] + dict_character + return dict_character + + def decode(self, text_index, text_prob=None, is_remove_duplicate=False): + """ convert text-index into text-label. """ + result_list = [] + batch_size = len(text_index) + for batch_idx in range(batch_size): + char_list = [] + conf_list = [] + for idx in range(len(text_index[batch_idx])): + try: + char_idx = self.character[int(text_index[batch_idx][idx])] + except: + continue + if char_idx == '': # end + break + char_list.append(char_idx) + if text_prob is not None: + conf_list.append(text_prob[batch_idx][idx]) + else: + conf_list.append(1) + text = ''.join(char_list) + result_list.append((text.lower(), np.mean(conf_list).tolist())) + return result_list + + +class ViTSTRLabelDecode(NRTRLabelDecode): + """ Convert between text-label and text-index """ + + def __init__(self, character_dict_path=None, use_space_char=False, + **kwargs): + super(ViTSTRLabelDecode, self).__init__(character_dict_path, + use_space_char) + + def __call__(self, preds, label=None, *args, **kwargs): + if isinstance(preds, paddle.Tensor): + preds = preds[:, 1:].numpy() + else: + preds = preds[:, 1:] + preds_idx = preds.argmax(axis=2) + preds_prob = preds.max(axis=2) + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) + if label is None: + return text + label = self.decode(label[:, 1:]) + return text, label + + def add_special_char(self, dict_character): + dict_character = ['', ''] + dict_character + return dict_character + + +class ABINetLabelDecode(NRTRLabelDecode): + """ Convert between text-label and text-index """ + + def __init__(self, character_dict_path=None, use_space_char=False, + **kwargs): + super(ABINetLabelDecode, self).__init__(character_dict_path, + use_space_char) + + def __call__(self, preds, label=None, *args, **kwargs): + if isinstance(preds, dict): + preds = preds['align'][-1].numpy() + elif isinstance(preds, paddle.Tensor): + preds = preds.numpy() + else: + preds = preds + + preds_idx = preds.argmax(axis=2) + preds_prob = preds.max(axis=2) + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) + if label is None: + return text + label = self.decode(label) + return text, label + + def add_special_char(self, dict_character): + dict_character = [''] + dict_character + return dict_character diff --git a/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml b/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml index 15119bb2a9..8118d58724 100644 --- a/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml +++ b/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml @@ -49,7 +49,7 @@ Architecture: Loss: - name: NRTRLoss + name: CELoss smoothing: True PostProcess: @@ -69,7 +69,7 @@ Train: img_mode: BGR channel_first: False - NRTRLabelEncode: # Class handling label - - NRTRRecResizeImg: + - GrayRecResizeImg: image_shape: [100, 32] resize_type: PIL # PIL or OpenCV - KeepKeys: @@ -90,7 +90,7 @@ Eval: img_mode: BGR channel_first: False - NRTRLabelEncode: # Class handling label - - NRTRRecResizeImg: + - GrayRecResizeImg: image_shape: [100, 32] resize_type: PIL # PIL or OpenCV - KeepKeys: @@ -99,5 +99,5 @@ Eval: shuffle: False drop_last: False batch_size_per_card: 256 - num_workers: 1 + num_workers: 4 use_shared_memory: False diff --git a/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml b/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml new file mode 100644 index 0000000000..5b5890e772 --- /dev/null +++ b/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml @@ -0,0 +1,106 @@ +Global: + use_gpu: True + epoch_num: 10 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/r45_abinet/ + save_epoch_step: 1 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: + character_type: en + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_abinet.txt + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.99 + clip_norm: 20.0 + lr: + name: Piecewise + decay_epochs: [6] + values: [0.0001, 0.00001] + regularizer: + name: 'L2' + factor: 0. + +Architecture: + model_type: rec + algorithm: ABINet + in_channels: 3 + Transform: + Backbone: + name: ResNet45 + + Head: + name: ABINetHead + use_lang: True + iter_size: 3 + + +Loss: + name: CELoss + ignore_index: &ignore_index 100 # Must be greater than the number of character classes + +PostProcess: + name: ABINetLabelDecode + +Metric: + name: RecMetric + main_indicator: acc + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data/ + label_file_list: ["./train_data/ic15_data/rec_gt_train.txt"] + transforms: + - DecodeImage: # load image + img_mode: RGB + channel_first: False + - ABINetRecAug: + - ABINetLabelEncode: # Class handling label + ignore_index: *ignore_index + - ABINetRecResizeImg: + image_shape: [3, 32, 128] + padding: False + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 96 + drop_last: True + num_workers: 4 + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data + label_file_list: ["./train_data/ic15_data/rec_gt_test.txt"] + transforms: + - DecodeImage: # load image + img_mode: RGB + channel_first: False + - ABINetLabelEncode: # Class handling label + ignore_index: *ignore_index + - ABINetRecResizeImg: + image_shape: [3, 32, 128] + padding: False + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 256 + num_workers: 4 + use_shared_memory: False diff --git a/test_tipc/configs/rec_r45_abinet/train_infer_python.txt b/test_tipc/configs/rec_r45_abinet/train_infer_python.txt new file mode 100644 index 0000000000..ecab1bcbbd --- /dev/null +++ b/test_tipc/configs/rec_r45_abinet/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:rec_abinet +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=64 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/rec_r45_abinet_train/best_accuracy +infer_export:tools/export_model.py -c test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml -o +infer_quant:False +inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,32,128" --rec_algorithm="ABINet" +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,32,128]}] diff --git a/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml b/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml new file mode 100644 index 0000000000..140b17e0e7 --- /dev/null +++ b/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml @@ -0,0 +1,117 @@ +Global: + use_gpu: True + epoch_num: 20 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/svtr/ + save_epoch_step: 1 + # evaluation is run every 2000 iterations after the 0th iteration + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: + character_type: en + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_svtr_tiny.txt + + +Optimizer: + name: AdamW + beta1: 0.9 + beta2: 0.99 + epsilon: 8.e-8 + weight_decay: 0.05 + no_weight_decay_name: norm pos_embed + one_dim_param_no_weight_decay: true + lr: + name: Cosine + learning_rate: 0.0005 + warmup_epoch: 2 + +Architecture: + model_type: rec + algorithm: SVTR + Transform: + name: STN_ON + tps_inputsize: [32, 64] + tps_outputsize: [32, 100] + num_control_points: 20 + tps_margins: [0.05,0.05] + stn_activation: none + Backbone: + name: SVTRNet + img_size: [32, 100] + out_char_num: 25 + out_channels: 192 + patch_merging: 'Conv' + embed_dim: [64, 128, 256] + depth: [3, 6, 3] + num_heads: [2, 4, 8] + mixer: ['Local','Local','Local','Local','Local','Local','Global','Global','Global','Global','Global','Global'] + local_mixer: [[7, 11], [7, 11], [7, 11]] + last_stage: True + prenorm: false + Neck: + name: SequenceEncoder + encoder_type: reshape + Head: + name: CTCHead + +Loss: + name: CTCLoss + +PostProcess: + name: CTCLabelDecode + +Metric: + name: RecMetric + main_indicator: acc + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data/ + label_file_list: ["./train_data/ic15_data/rec_gt_train.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - CTCLabelEncode: # Class handling label + - SVTRRecResizeImg: + image_shape: [3, 64, 256] + padding: False + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 512 + drop_last: True + num_workers: 4 + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data + label_file_list: ["./train_data/ic15_data/rec_gt_test.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - CTCLabelEncode: # Class handling label + - SVTRRecResizeImg: + image_shape: [3, 64, 256] + padding: False + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 256 + num_workers: 2 diff --git a/test_tipc/configs/rec_svtrnet/train_infer_python.txt b/test_tipc/configs/rec_svtrnet/train_infer_python.txt new file mode 100644 index 0000000000..a7e4a24063 --- /dev/null +++ b/test_tipc/configs/rec_svtrnet/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:rec_svtrnet +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=64 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/rec_svtrnet/rec_svtrnet.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c test_tipc/configs/rec_svtrnet/rec_svtrnet.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/rec_svtrnet/rec_svtrnet.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/rec_svtrnet_train/best_accuracy +infer_export:tools/export_model.py -c test_tipc/configs/rec_svtrnet/rec_svtrnet.yml -o +infer_quant:False +inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/ic15_dict.txt --rec_image_shape="3,64,256" --rec_algorithm="SVTR" +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[3,64,256]}] diff --git a/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml b/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml new file mode 100644 index 0000000000..a0aed48875 --- /dev/null +++ b/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml @@ -0,0 +1,104 @@ +Global: + use_gpu: True + epoch_num: 20 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec/vitstr_none_ce/ + save_epoch_step: 1 + # evaluation is run every 2000 iterations after the 0th iteration# + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: ppocr/utils/EN_symbol_dict.txt + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_vitstr.txt + + +Optimizer: + name: Adadelta + epsilon: 1.e-8 + rho: 0.95 + clip_norm: 5.0 + lr: + learning_rate: 1.0 + +Architecture: + model_type: rec + algorithm: ViTSTR + in_channels: 1 + Transform: + Backbone: + name: ViTSTR + Neck: + name: SequenceEncoder + encoder_type: reshape + Head: + name: CTCHead + +Loss: + name: CELoss + smoothing: False + with_all: True + ignore_index: &ignore_index 0 # Must be zero or greater than the number of character classes + +PostProcess: + name: ViTSTRLabelDecode + +Metric: + name: RecMetric + main_indicator: acc + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data/ + label_file_list: ["./train_data/ic15_data/rec_gt_train.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ViTSTRLabelEncode: # Class handling label + ignore_index: *ignore_index + - GrayRecResizeImg: + image_shape: [224, 224] # W H + resize_type: PIL # PIL or OpenCV + inter_type: 'Image.BICUBIC' + scale: false + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 48 + drop_last: True + num_workers: 8 + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data + label_file_list: ["./train_data/ic15_data/rec_gt_test.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - ViTSTRLabelEncode: # Class handling label + ignore_index: *ignore_index + - GrayRecResizeImg: + image_shape: [224, 224] # W H + resize_type: PIL # PIL or OpenCV + inter_type: 'Image.BICUBIC' + scale: false + - KeepKeys: + keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 256 + num_workers: 2 diff --git a/test_tipc/configs/rec_vitstr_none_ce/train_infer_python.txt b/test_tipc/configs/rec_vitstr_none_ce/train_infer_python.txt new file mode 100644 index 0000000000..04c5742ea2 --- /dev/null +++ b/test_tipc/configs/rec_vitstr_none_ce/train_infer_python.txt @@ -0,0 +1,53 @@ +===========================train_params=========================== +model_name:rec_vitstr +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:null +Global.epoch_num:lite_train_lite_infer=2|whole_train_whole_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_lite_infer=16|whole_train_whole_infer=64 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train +norm_train:tools/train.py -c test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml -o +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.checkpoints: +norm_export:tools/export_model.py -c test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml -o +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +train_model:./inference/rec_vitstr_none_ce_train/best_accuracy +infer_export:tools/export_model.py -c test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml -o +infer_quant:False +inference:tools/infer/predict_rec.py --rec_char_dict_path=./ppocr/utils/EN_symbol_dict.txt --rec_image_shape="1,224,224" --rec_algorithm="ViTSTR" +--use_gpu:True|False +--enable_mkldnn:False +--cpu_threads:6 +--rec_batch_num:1|6 +--use_tensorrt:False +--precision:fp32 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================infer_benchmark_params========================== +random_infer_input:[{float32,[1,224,224]}] diff --git a/tools/export_model.py b/tools/export_model.py index 3ea0228f85..b10d41d5b2 100755 --- a/tools/export_model.py +++ b/tools/export_model.py @@ -31,7 +31,12 @@ from ppocr.utils.logging import get_logger from tools.program import load_config, merge_config, ArgsParser -def export_single_model(model, arch_config, save_path, logger, quanter=None): +def export_single_model(model, + arch_config, + save_path, + logger, + input_shape=None, + quanter=None): if arch_config["algorithm"] == "SRN": max_text_length = arch_config["Head"]["max_text_length"] other_shape = [ @@ -64,7 +69,7 @@ def export_single_model(model, arch_config, save_path, logger, quanter=None): else: other_shape = [ paddle.static.InputSpec( - shape=[None, 3, 64, 256], dtype="float32"), + shape=[None] + input_shape, dtype="float32"), ] model = to_static(model, input_spec=other_shape) elif arch_config["algorithm"] == "PREN": @@ -73,6 +78,25 @@ def export_single_model(model, arch_config, save_path, logger, quanter=None): shape=[None, 3, 64, 512], dtype="float32"), ] model = to_static(model, input_spec=other_shape) + elif arch_config["algorithm"] == "ViTSTR": + other_shape = [ + paddle.static.InputSpec( + shape=[None, 1, 224, 224], dtype="float32"), + ] + model = to_static(model, input_spec=other_shape) + elif arch_config["algorithm"] == "ABINet": + other_shape = [ + paddle.static.InputSpec( + shape=[None, 3, 32, 128], dtype="float32"), + ] + # print([None, 3, 32, 128]) + model = to_static(model, input_spec=other_shape) + elif arch_config["algorithm"] == "NRTR": + other_shape = [ + paddle.static.InputSpec( + shape=[None, 1, 32, 100], dtype="float32"), + ] + model = to_static(model, input_spec=other_shape) else: infer_shape = [3, -1, -1] if arch_config["model_type"] == "rec": @@ -84,8 +108,6 @@ def export_single_model(model, arch_config, save_path, logger, quanter=None): "When there is tps in the network, variable length input is not supported, and the input size needs to be the same as during training" ) infer_shape[-1] = 100 - if arch_config["algorithm"] == "NRTR": - infer_shape = [1, 32, 100] elif arch_config["model_type"] == "table": infer_shape = [3, 488, 488] model = to_static( @@ -157,6 +179,13 @@ def main(): arch_config = config["Architecture"] + if arch_config["algorithm"] == "SVTR" and arch_config["Head"][ + "name"] != 'MultiHead': + input_shape = config["Eval"]["dataset"]["transforms"][-2][ + 'SVTRRecResizeImg']['image_shape'] + else: + input_shape = None + if arch_config["algorithm"] in ["Distillation", ]: # distillation model archs = list(arch_config["Models"].values()) for idx, name in enumerate(model.model_name_list): @@ -165,7 +194,8 @@ def main(): sub_model_save_path, logger) else: save_path = os.path.join(save_path, "inference") - export_single_model(model, arch_config, save_path, logger) + export_single_model( + model, arch_config, save_path, logger, input_shape=input_shape) if __name__ == "__main__": diff --git a/tools/infer/predict_rec.py b/tools/infer/predict_rec.py index 3664ef2caf..a95f555966 100755 --- a/tools/infer/predict_rec.py +++ b/tools/infer/predict_rec.py @@ -69,6 +69,18 @@ class TextRecognizer(object): "character_dict_path": args.rec_char_dict_path, "use_space_char": args.use_space_char } + elif self.rec_algorithm == 'ViTSTR': + postprocess_params = { + 'name': 'ViTSTRLabelDecode', + "character_dict_path": args.rec_char_dict_path, + "use_space_char": args.use_space_char + } + elif self.rec_algorithm == 'ABINet': + postprocess_params = { + 'name': 'ABINetLabelDecode', + "character_dict_path": args.rec_char_dict_path, + "use_space_char": args.use_space_char + } self.postprocess_op = build_post_process(postprocess_params) self.predictor, self.input_tensor, self.output_tensors, self.config = \ utility.create_predictor(args, 'rec', logger) @@ -96,15 +108,22 @@ class TextRecognizer(object): def resize_norm_img(self, img, max_wh_ratio): imgC, imgH, imgW = self.rec_image_shape - if self.rec_algorithm == 'NRTR': + if self.rec_algorithm == 'NRTR' or self.rec_algorithm == 'ViTSTR': img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # return padding_im image_pil = Image.fromarray(np.uint8(img)) - img = image_pil.resize([100, 32], Image.ANTIALIAS) + if self.rec_algorithm == 'ViTSTR': + img = image_pil.resize([imgW, imgH], Image.BICUBIC) + else: + img = image_pil.resize([imgW, imgH], Image.ANTIALIAS) img = np.array(img) norm_img = np.expand_dims(img, -1) norm_img = norm_img.transpose((2, 0, 1)) - return norm_img.astype(np.float32) / 128. - 1. + if self.rec_algorithm == 'ViTSTR': + norm_img = norm_img.astype(np.float32) / 255. + else: + norm_img = norm_img.astype(np.float32) / 128. - 1. + return norm_img assert imgC == img.shape[2] imgW = int((imgH * max_wh_ratio)) @@ -132,17 +151,6 @@ class TextRecognizer(object): padding_im[:, :, 0:resized_w] = resized_image return padding_im - def resize_norm_img_svtr(self, img, image_shape): - - imgC, imgH, imgW = image_shape - resized_image = cv2.resize( - img, (imgW, imgH), interpolation=cv2.INTER_LINEAR) - resized_image = resized_image.astype('float32') - resized_image = resized_image.transpose((2, 0, 1)) / 255 - resized_image -= 0.5 - resized_image /= 0.5 - return resized_image - def resize_norm_img_srn(self, img, image_shape): imgC, imgH, imgW = image_shape @@ -250,6 +258,35 @@ class TextRecognizer(object): return padding_im, resize_shape, pad_shape, valid_ratio + def resize_norm_img_svtr(self, img, image_shape): + + imgC, imgH, imgW = image_shape + resized_image = cv2.resize( + img, (imgW, imgH), interpolation=cv2.INTER_LINEAR) + resized_image = resized_image.astype('float32') + resized_image = resized_image.transpose((2, 0, 1)) / 255 + resized_image -= 0.5 + resized_image /= 0.5 + return resized_image + + def resize_norm_img_abinet(self, img, image_shape): + + imgC, imgH, imgW = image_shape + + resized_image = cv2.resize( + img, (imgW, imgH), interpolation=cv2.INTER_LINEAR) + resized_image = resized_image.astype('float32') + resized_image = resized_image / 255. + + mean = np.array([0.485, 0.456, 0.406]) + std = np.array([0.229, 0.224, 0.225]) + resized_image = ( + resized_image - mean[None, None, ...]) / std[None, None, ...] + resized_image = resized_image.transpose((2, 0, 1)) + resized_image = resized_image.astype('float32') + + return resized_image + def __call__(self, img_list): img_num = len(img_list) # Calculate the aspect ratio of all text bars @@ -300,6 +337,11 @@ class TextRecognizer(object): self.rec_image_shape) norm_img = norm_img[np.newaxis, :] norm_img_batch.append(norm_img) + elif self.rec_algorithm == "ABINet": + norm_img = self.resize_norm_img_abinet( + img_list[indices[ino]], self.rec_image_shape) + norm_img = norm_img[np.newaxis, :] + norm_img_batch.append(norm_img) else: norm_img = self.resize_norm_img(img_list[indices[ino]], max_wh_ratio) diff --git a/tools/program.py b/tools/program.py index 9a90eda2f8..aa3ba82c44 100755 --- a/tools/program.py +++ b/tools/program.py @@ -576,7 +576,8 @@ def preprocess(is_train=False): assert alg in [ 'EAST', 'DB', 'SAST', 'Rosetta', 'CRNN', 'STARNet', 'RARE', 'SRN', 'CLS', 'PGNet', 'Distillation', 'NRTR', 'TableAttn', 'SAR', 'PSE', - 'SEED', 'SDMGR', 'LayoutXLM', 'LayoutLM', 'PREN', 'FCE', 'SVTR' + 'SEED', 'SDMGR', 'LayoutXLM', 'LayoutLM', 'PREN', 'FCE', 'SVTR', + 'ViTSTR', 'ABINet' ] if use_xpu: From 2916625a8f88f1e6d065fbdfe064ee910712c1b4 Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Wed, 29 Jun 2022 15:31:48 +0800 Subject: [PATCH 124/129] =?UTF-8?q?Update=20=E5=85=89=E5=8A=9F=E7=8E=87?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E7=A0=81=E7=AE=A1=E5=AD=97=E7=AC=A6=E8=AF=86?= =?UTF-8?q?=E5=88=AB.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/光功率计数码管字符识别.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/applications/光功率计数码管字符识别.md b/applications/光功率计数码管字符识别.md index d6c11259bf..2a35cb170e 100644 --- a/applications/光功率计数码管字符识别.md +++ b/applications/光功率计数码管字符识别.md @@ -21,12 +21,16 @@ 第二步,使用文本识别模型获得准确的数字和单位信息。 -本项目主要介绍如何完成第二步文本识别部分,包括: +本项目主要介绍如何完成第二步文本识别部分,包括:真实评估集的建立、训练数据的合成、基于 PP-OCRv3 和 SVTR_Tiny 两个模型进行训练,以及评估和推理。 -* 真实评估集的建立 -* 训练数据的合成 -* 基于 PP-OCRv3 和 SVTR_Tiny 两个模型进行训练 -* 评估并推理 +本项目难点如下: + +- 光功率计数码管字符数据较少,难以获取。 +- 数码管中小数点占像素较少,容易漏识别。 + +针对以上问题, 本例选用 PP-OCRv3 和 SVTR_Tiny 两个高精度模型训练,同时提供了真实数据挖掘案例和数据合成案例。基于 PP-OCRv3 模型,在构建的真实评估集上精度从 52% 提升至 72%,SVTR_Tiny 模型精度可达到 78.9%。 + +aistudio项目链接: [光功率计数码管字符识别](https://aistudio.baidu.com/aistudio/projectdetail/4049044?contributionType=1) ## 2. PaddleOCR 快速使用 From 46fafa298710cf7b4555a98aa03fefa18fc16c33 Mon Sep 17 00:00:00 2001 From: an1018 <614803115@qq.com> Date: Wed, 29 Jun 2022 17:01:47 +0800 Subject: [PATCH 125/129] update --- applications/PCB字符识别/PCB字符识别.md | 6 ++++- applications/多模态表单识别.md | 36 ++++++++++++------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/applications/PCB字符识别/PCB字符识别.md b/applications/PCB字符识别/PCB字符识别.md index a5052e2897..ee13bacffd 100644 --- a/applications/PCB字符识别/PCB字符识别.md +++ b/applications/PCB字符识别/PCB字符识别.md @@ -206,7 +206,11 @@ Eval.dataset.transforms.DetResizeForTest: 尺寸 limit_type: 'min' ``` -然后执行评估代码 +如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 +
+ +
+将下载或训练完成的模型放置在对应目录下即可完成模型评估。 ```python diff --git a/applications/多模态表单识别.md b/applications/多模态表单识别.md index 27f981101a..471ca633c1 100644 --- a/applications/多模态表单识别.md +++ b/applications/多模态表单识别.md @@ -7,12 +7,12 @@ - [3.2 转换为PaddleOCR检测和识别格式](#32-转换为paddleocr检测和识别格式) - [4 OCR](#4-ocr) - [4.1 文本检测](#41-文本检测) - - [**4.1.1 方案1:预训练模型**](#411-方案1预训练模型) - - [**4.1.2 方案2:XFUND数据集+fine-tune**](#412-方案2xfund数据集fine-tune) + - [4.1.1 方案1:预训练模型](#411-方案1预训练模型) + - [4.1.2 方案2:XFUND数据集+fine-tune](#412-方案2xfund数据集fine-tune) - [4.2 文本识别](#42-文本识别) - - [**4.2.1 方案1:预训练模型**](#421-方案1预训练模型) - - [**4.2.2 方案2:XFUND数据集+finetune**](#422-方案2xfund数据集finetune) - - [**4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据**](#423-方案3xfund数据集finetune真实通用识别数据) + - [4.2.1 方案1:预训练模型](#421-方案1预训练模型) + - [4.2.2 方案2:XFUND数据集+finetune](#422-方案2xfund数据集finetune) + - [4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据](#423-方案3xfund数据集finetune真实通用识别数据) - [5 文档视觉问答(DOC-VQA)](#5-文档视觉问答doc-vqa) - [5.1 SER](#51-ser) - [5.1.1 模型训练](#511-模型训练) @@ -195,7 +195,7 @@ python trans_xfund_data.py - **PP-OCRv2中英文超轻量检测预训练模型** - **XFUND数据集+fine-tune** -#### **4.1.1 方案1:预训练模型** +#### 4.1.1 方案1:预训练模型 **1)下载预训练模型** @@ -265,7 +265,7 @@ python tools/eval.py \ 使用文本检测预训练模型在XFUND验证集上评估,达到77%左右,充分说明ppocr提供的预训练模型具有泛化能力。 -#### **4.1.2 方案2:XFUND数据集+fine-tune** +#### 4.1.2 方案2:XFUND数据集+fine-tune PaddleOCR提供的蒸馏预训练模型包含了多个模型的参数,我们提取Student模型的参数,在XFUND数据集上进行finetune,可以参考如下代码: @@ -316,7 +316,13 @@ CUDA_VISIBLE_DEVICES=0 python tools/train.py \
图8 文本检测方案2-模型评估
-使用训练好的模型进行评估,更新模型路径`Global.checkpoints`。 +使用训练好的模型进行评估,更新模型路径`Global.checkpoints`。如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 + +
+ +
+ +将下载或训练完成的模型放置在对应目录下即可完成模型评估 ```python @@ -412,7 +418,7 @@ use_gpu:是否使用GPU - XFUND数据集+fine-tune - XFUND数据集+fine-tune+真实通用识别数据 -#### **4.2.1 方案1:预训练模型** +#### 4.2.1 方案1:预训练模型 **1)下载预训练模型** @@ -461,7 +467,7 @@ CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ 使用文本预训练模型在XFUND验证集上评估,acc达到67%左右,充分说明ppocr提供的预训练模型具有泛化能力。 -#### **4.2.2 方案2:XFUND数据集+finetune** +#### 4.2.2 方案2:XFUND数据集+finetune 同检测模型,我们提取Student模型的参数,在XFUND数据集上进行finetune,可以参考如下代码: @@ -528,7 +534,7 @@ CUDA_VISIBLE_DEVICES=0 python tools/eval.py \ 使用XFUND数据集+finetune训练,在验证集上评估达到72%左右,说明 finetune会提升垂类场景效果。 -#### **4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据** +#### 4.2.3 方案3:XFUND数据集+finetune+真实通用识别数据 接着我们在上述`XFUND数据集+finetune`实验的基础上,添加真实通用识别数据,进一步提升识别效果。首先准备真实通用识别数据,并上传到AIStudio: @@ -873,14 +879,6 @@ with open('output/re/infer_results.txt', 'r', encoding='utf-8') as fin: workbook.close() ``` -## 获得模型 - -如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁 -
- -
-将下载或训练完成的模型放置在对应目录下即可完成模型推理 - ## 更多资源 - 更多深度学习知识、产业案例、面试宝典等,请参考:[awesome-DeepLearning](https://github.com/paddlepaddle/awesome-DeepLearning) From b998a95c7d8ea24af16b8406d9429885910b4900 Mon Sep 17 00:00:00 2001 From: Evezerest <50011306+Evezerest@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:54:34 +0800 Subject: [PATCH 126/129] add application.md --- doc/doc_ch/application.md | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 doc/doc_ch/application.md diff --git a/doc/doc_ch/application.md b/doc/doc_ch/application.md new file mode 100644 index 0000000000..5135dfac10 --- /dev/null +++ b/doc/doc_ch/application.md @@ -0,0 +1,41 @@ +# 场景应用 + +PaddleOCR场景应用覆盖通用,制造、金融、交通行业的主要OCR垂类应用,在PP-OCR、PP-Structure的通用能力基础之上,以notebook的形式展示利用场景数据微调、模型优化方法、数据增广等内容,为开发者快速落地OCR应用提供示范与启发。 + +> 如需下载全部垂类模型,可以扫描下方二维码,关注公众号填写问卷后,加入PaddleOCR官方交流群获取20G OCR学习大礼包(内含《动手学OCR》电子书、课程回放视频、前沿论文等重磅资料) + +
+ +
+ + +> 如果您是企业开发者且未在下述场景中找到合适的方案,可以填写[OCR应用合作调研问卷](https://paddle.wjx.cn/vj/QwF7GKw.aspx),免费与官方团队展开不同层次的合作,包括但不限于问题抽象、确定技术方案、项目答疑、共同研发等。如果您已经使用PaddleOCR落地项目,也可以填写此问卷,与飞桨平台共同宣传推广,提升企业技术品宣。期待您的提交! + +## 通用 + +| 类别 | 亮点 | 类别 | 亮点 | +| ---------------------- | -------- | ---------- | ------------ | +| 高精度中文识别模型SVTR | 新增模型 | 手写体识别 | 新增字形支持 | + +## 制造 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------------ | -------------- | -------------------- | +| 数码管识别 | 数码管数据合成、漏识别调优 | 电表识别 | 大分辨率图像检测调优 | +| 液晶屏读数识别 | 检测模型蒸馏、Serving部署 | PCB文字识别 | 小尺寸文本检测与识别 | +| 包装生产日期 | 点阵字符合成、过曝过暗文字识别 | 液晶屏缺陷检测 | 非文字形态识别 | + +## 金融 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------ | ------------ | --------------------- | +| 表单VQA | 多模态通用表单结构化提取 | 通用卡证识别 | 通用结构化提取 | +| 增值税发票 | 尽请期待 | 身份证识别 | 结构化提取、图像阴影 | +| 印章检测与识别 | 端到端弯曲文本识别 | 合同比对 | 密集文本检测、NLP串联 | + +## 交通 + +| 类别 | 亮点 | 类别 | 亮点 | +| ----------------- | ------------------------------ | ---------- | -------- | +| 车牌识别 | 多角度图像、轻量模型、端侧部署 | 快递单识别 | 尽请期待 | +| 驾驶证/行驶证识别 | 尽请期待 | | | \ No newline at end of file From 14dedcacf6dab4eda75927f1feff9177f961c932 Mon Sep 17 00:00:00 2001 From: Evezerest <50011306+Evezerest@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:56:24 +0800 Subject: [PATCH 127/129] move application.md --- applications/application.md | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 applications/application.md diff --git a/applications/application.md b/applications/application.md new file mode 100644 index 0000000000..5135dfac10 --- /dev/null +++ b/applications/application.md @@ -0,0 +1,41 @@ +# 场景应用 + +PaddleOCR场景应用覆盖通用,制造、金融、交通行业的主要OCR垂类应用,在PP-OCR、PP-Structure的通用能力基础之上,以notebook的形式展示利用场景数据微调、模型优化方法、数据增广等内容,为开发者快速落地OCR应用提供示范与启发。 + +> 如需下载全部垂类模型,可以扫描下方二维码,关注公众号填写问卷后,加入PaddleOCR官方交流群获取20G OCR学习大礼包(内含《动手学OCR》电子书、课程回放视频、前沿论文等重磅资料) + +
+ +
+ + +> 如果您是企业开发者且未在下述场景中找到合适的方案,可以填写[OCR应用合作调研问卷](https://paddle.wjx.cn/vj/QwF7GKw.aspx),免费与官方团队展开不同层次的合作,包括但不限于问题抽象、确定技术方案、项目答疑、共同研发等。如果您已经使用PaddleOCR落地项目,也可以填写此问卷,与飞桨平台共同宣传推广,提升企业技术品宣。期待您的提交! + +## 通用 + +| 类别 | 亮点 | 类别 | 亮点 | +| ---------------------- | -------- | ---------- | ------------ | +| 高精度中文识别模型SVTR | 新增模型 | 手写体识别 | 新增字形支持 | + +## 制造 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------------ | -------------- | -------------------- | +| 数码管识别 | 数码管数据合成、漏识别调优 | 电表识别 | 大分辨率图像检测调优 | +| 液晶屏读数识别 | 检测模型蒸馏、Serving部署 | PCB文字识别 | 小尺寸文本检测与识别 | +| 包装生产日期 | 点阵字符合成、过曝过暗文字识别 | 液晶屏缺陷检测 | 非文字形态识别 | + +## 金融 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------ | ------------ | --------------------- | +| 表单VQA | 多模态通用表单结构化提取 | 通用卡证识别 | 通用结构化提取 | +| 增值税发票 | 尽请期待 | 身份证识别 | 结构化提取、图像阴影 | +| 印章检测与识别 | 端到端弯曲文本识别 | 合同比对 | 密集文本检测、NLP串联 | + +## 交通 + +| 类别 | 亮点 | 类别 | 亮点 | +| ----------------- | ------------------------------ | ---------- | -------- | +| 车牌识别 | 多角度图像、轻量模型、端侧部署 | 快递单识别 | 尽请期待 | +| 驾驶证/行驶证识别 | 尽请期待 | | | \ No newline at end of file From 8dd60b566ffa4fc2697bf6b1c3dfcb1d890680d5 Mon Sep 17 00:00:00 2001 From: Evezerest <50011306+Evezerest@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:57:26 +0800 Subject: [PATCH 128/129] update name --- applications/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 applications/README.md diff --git a/applications/README.md b/applications/README.md new file mode 100644 index 0000000000..5135dfac10 --- /dev/null +++ b/applications/README.md @@ -0,0 +1,41 @@ +# 场景应用 + +PaddleOCR场景应用覆盖通用,制造、金融、交通行业的主要OCR垂类应用,在PP-OCR、PP-Structure的通用能力基础之上,以notebook的形式展示利用场景数据微调、模型优化方法、数据增广等内容,为开发者快速落地OCR应用提供示范与启发。 + +> 如需下载全部垂类模型,可以扫描下方二维码,关注公众号填写问卷后,加入PaddleOCR官方交流群获取20G OCR学习大礼包(内含《动手学OCR》电子书、课程回放视频、前沿论文等重磅资料) + +
+ +
+ + +> 如果您是企业开发者且未在下述场景中找到合适的方案,可以填写[OCR应用合作调研问卷](https://paddle.wjx.cn/vj/QwF7GKw.aspx),免费与官方团队展开不同层次的合作,包括但不限于问题抽象、确定技术方案、项目答疑、共同研发等。如果您已经使用PaddleOCR落地项目,也可以填写此问卷,与飞桨平台共同宣传推广,提升企业技术品宣。期待您的提交! + +## 通用 + +| 类别 | 亮点 | 类别 | 亮点 | +| ---------------------- | -------- | ---------- | ------------ | +| 高精度中文识别模型SVTR | 新增模型 | 手写体识别 | 新增字形支持 | + +## 制造 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------------ | -------------- | -------------------- | +| 数码管识别 | 数码管数据合成、漏识别调优 | 电表识别 | 大分辨率图像检测调优 | +| 液晶屏读数识别 | 检测模型蒸馏、Serving部署 | PCB文字识别 | 小尺寸文本检测与识别 | +| 包装生产日期 | 点阵字符合成、过曝过暗文字识别 | 液晶屏缺陷检测 | 非文字形态识别 | + +## 金融 + +| 类别 | 亮点 | 类别 | 亮点 | +| -------------- | ------------------------ | ------------ | --------------------- | +| 表单VQA | 多模态通用表单结构化提取 | 通用卡证识别 | 通用结构化提取 | +| 增值税发票 | 尽请期待 | 身份证识别 | 结构化提取、图像阴影 | +| 印章检测与识别 | 端到端弯曲文本识别 | 合同比对 | 密集文本检测、NLP串联 | + +## 交通 + +| 类别 | 亮点 | 类别 | 亮点 | +| ----------------- | ------------------------------ | ---------- | -------- | +| 车牌识别 | 多角度图像、轻量模型、端侧部署 | 快递单识别 | 尽请期待 | +| 驾驶证/行驶证识别 | 尽请期待 | | | \ No newline at end of file From ab13b42f91527cf6224ef18e81104105c45a4a73 Mon Sep 17 00:00:00 2001 From: Evezerest <50011306+Evezerest@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:58:05 +0800 Subject: [PATCH 129/129] Delete application.md --- applications/application.md | 41 ------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 applications/application.md diff --git a/applications/application.md b/applications/application.md deleted file mode 100644 index 5135dfac10..0000000000 --- a/applications/application.md +++ /dev/null @@ -1,41 +0,0 @@ -# 场景应用 - -PaddleOCR场景应用覆盖通用,制造、金融、交通行业的主要OCR垂类应用,在PP-OCR、PP-Structure的通用能力基础之上,以notebook的形式展示利用场景数据微调、模型优化方法、数据增广等内容,为开发者快速落地OCR应用提供示范与启发。 - -> 如需下载全部垂类模型,可以扫描下方二维码,关注公众号填写问卷后,加入PaddleOCR官方交流群获取20G OCR学习大礼包(内含《动手学OCR》电子书、课程回放视频、前沿论文等重磅资料) - -
- -
- - -> 如果您是企业开发者且未在下述场景中找到合适的方案,可以填写[OCR应用合作调研问卷](https://paddle.wjx.cn/vj/QwF7GKw.aspx),免费与官方团队展开不同层次的合作,包括但不限于问题抽象、确定技术方案、项目答疑、共同研发等。如果您已经使用PaddleOCR落地项目,也可以填写此问卷,与飞桨平台共同宣传推广,提升企业技术品宣。期待您的提交! - -## 通用 - -| 类别 | 亮点 | 类别 | 亮点 | -| ---------------------- | -------- | ---------- | ------------ | -| 高精度中文识别模型SVTR | 新增模型 | 手写体识别 | 新增字形支持 | - -## 制造 - -| 类别 | 亮点 | 类别 | 亮点 | -| -------------- | ------------------------------ | -------------- | -------------------- | -| 数码管识别 | 数码管数据合成、漏识别调优 | 电表识别 | 大分辨率图像检测调优 | -| 液晶屏读数识别 | 检测模型蒸馏、Serving部署 | PCB文字识别 | 小尺寸文本检测与识别 | -| 包装生产日期 | 点阵字符合成、过曝过暗文字识别 | 液晶屏缺陷检测 | 非文字形态识别 | - -## 金融 - -| 类别 | 亮点 | 类别 | 亮点 | -| -------------- | ------------------------ | ------------ | --------------------- | -| 表单VQA | 多模态通用表单结构化提取 | 通用卡证识别 | 通用结构化提取 | -| 增值税发票 | 尽请期待 | 身份证识别 | 结构化提取、图像阴影 | -| 印章检测与识别 | 端到端弯曲文本识别 | 合同比对 | 密集文本检测、NLP串联 | - -## 交通 - -| 类别 | 亮点 | 类别 | 亮点 | -| ----------------- | ------------------------------ | ---------- | -------- | -| 车牌识别 | 多角度图像、轻量模型、端侧部署 | 快递单识别 | 尽请期待 | -| 驾驶证/行驶证识别 | 尽请期待 | | | \ No newline at end of file