From 8ecaf41e8264b89e02a4499ca2628f67887d1896 Mon Sep 17 00:00:00 2001
From: xmy0916 <863299715@qq.com>
Date: Thu, 3 Dec 2020 17:29:29 +0800
Subject: [PATCH 01/51] fix doc algorithm_overview ch&en
---
doc/doc_ch/algorithm_overview.md | 30 ++++++++++++++---------------
doc/doc_en/algorithm_overview_en.md | 30 ++++++++++++++---------------
2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md
index c4a3b3255..475db6793 100644
--- a/doc/doc_ch/algorithm_overview.md
+++ b/doc/doc_ch/algorithm_overview.md
@@ -17,17 +17,17 @@ PaddleOCR开源的文本检测算法列表:
|模型|骨干网络|precision|recall|Hmean|下载链接|
|-|-|-|-|-|-|
-|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[下载链接](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)|
-|EAST|MobileNetV3|81.67%|79.83%|80.74%|[下载链接](https://paddleocr.bj.bcebos.com/det_mv3_east.tar)|
-|DB|ResNet50_vd|83.79%|80.65%|82.19%|[下载链接](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)|
-|DB|MobileNetV3|75.92%|73.18%|74.53%|[下载链接](https://paddleocr.bj.bcebos.com/det_mv3_db.tar)|
-|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[下载链接](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)|
+|EAST|ResNet50_vd||||[敬请期待]()|
+|EAST|MobileNetV3||||[敬请期待]()|
+|DB|ResNet50_vd||||[敬请期待]()|
+|DB|MobileNetV3||||[敬请期待]()|
+|SAST|ResNet50_vd||||[敬请期待]()|
在Total-text文本检测公开数据集上,算法效果如下:
|模型|骨干网络|precision|recall|Hmean|下载链接|
|-|-|-|-|-|-|
-|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[下载链接](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)|
+|SAST|ResNet50_vd||||[敬请期待]()|
**说明:** SAST模型训练额外加入了icdar2013、icdar2017、COCO-Text、ArT等公开数据集进行调优。PaddleOCR用到的经过整理格式的英文公开数据集下载:[百度云地址](https://pan.baidu.com/s/12cPnZcVuV1zn5DOd4mqjVw) (提取码: 2bpi)
@@ -48,15 +48,15 @@ PaddleOCR开源的文本识别算法列表:
|模型|骨干网络|Avg Accuracy|模型存储命名|下载链接|
|-|-|-|-|-|
-|Rosetta|Resnet34_vd|80.24%|rec_r34_vd_none_none_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_none_ctc.tar)|
-|Rosetta|MobileNetV3|78.16%|rec_mv3_none_none_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_none_none_ctc.tar)|
-|CRNN|Resnet34_vd|82.20%|rec_r34_vd_none_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_bilstm_ctc.tar)|
-|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar)|
-|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)|
-|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_ctc.tar)|
-|RARE|Resnet34_vd|84.90%|rec_r34_vd_tps_bilstm_attn|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_attn.tar)|
-|RARE|MobileNetV3|83.32%|rec_mv3_tps_bilstm_attn|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar)|
-|SRN|Resnet50_vd_fpn|88.33%|rec_r50fpn_vd_none_srn|[下载链接](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)|
+|Rosetta|Resnet34_vd||rec_r34_vd_none_none_ctc|[敬请期待]()|
+|Rosetta|MobileNetV3||rec_mv3_none_none_ctc|[敬请期待]()|
+|CRNN|Resnet34_vd||rec_r34_vd_none_bilstm_ctc|[敬请期待]()|
+|CRNN|MobileNetV3||rec_mv3_none_bilstm_ctc|[敬请期待]()|
+|STAR-Net|Resnet34_vd||rec_r34_vd_tps_bilstm_ctc|[敬请期待]()|
+|STAR-Net|MobileNetV3||rec_mv3_tps_bilstm_ctc|[敬请期待]()|
+|RARE|Resnet34_vd||rec_r34_vd_tps_bilstm_attn|[敬请期待]()|
+|RARE|MobileNetV3||rec_mv3_tps_bilstm_attn|[敬请期待]()|
+|SRN|Resnet50_vd_fpn||rec_r50fpn_vd_none_srn|[敬请期待]()|
**说明:** SRN模型使用了数据扰动方法对上述提到对两个训练集进行增广,增广后的数据可以在[百度网盘](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA)上下载,提取码: y3ry。
原始论文使用两阶段训练平均精度为89.74%,PaddleOCR中使用one-stage训练,平均精度为88.33%。两种预训练权重均在[下载链接](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)中。
diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md
index 2e21fd621..6cdf310f0 100644
--- a/doc/doc_en/algorithm_overview_en.md
+++ b/doc/doc_en/algorithm_overview_en.md
@@ -19,17 +19,17 @@ On the ICDAR2015 dataset, the text detection result is as follows:
|Model|Backbone|precision|recall|Hmean|Download link|
|-|-|-|-|-|-|
-|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)|
-|EAST|MobileNetV3|81.67%|79.83%|80.74%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_east.tar)|
-|DB|ResNet50_vd|83.79%|80.65%|82.19%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)|
-|DB|MobileNetV3|75.92%|73.18%|74.53%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_db.tar)|
-|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)|
+|EAST|ResNet50_vd||||[Coming soon]()|
+|EAST|MobileNetV3||||[Coming soon]()|
+|DB|ResNet50_vd||||[Coming soon]()|
+|DB|MobileNetV3||||[Coming soon]()|
+|SAST|ResNet50_vd||||[Coming soon]()|
On Total-Text dataset, the text detection result is as follows:
|Model|Backbone|precision|recall|Hmean|Download link|
|-|-|-|-|-|-|
-|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)|
+|SAST|ResNet50_vd||||[Coming soon]()|
**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).
@@ -49,15 +49,15 @@ Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation r
|Model|Backbone|Avg Accuracy|Module combination|Download link|
|-|-|-|-|-|
-|Rosetta|Resnet34_vd|80.24%|rec_r34_vd_none_none_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_none_ctc.tar)|
-|Rosetta|MobileNetV3|78.16%|rec_mv3_none_none_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_none_none_ctc.tar)|
-|CRNN|Resnet34_vd|82.20%|rec_r34_vd_none_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_bilstm_ctc.tar)|
-|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar)|
-|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)|
-|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_ctc.tar)|
-|RARE|Resnet34_vd|84.90%|rec_r34_vd_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_attn.tar)|
-|RARE|MobileNetV3|83.32%|rec_mv3_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar)|
-|SRN|Resnet50_vd_fpn|88.33%|rec_r50fpn_vd_none_srn|[Download link](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)|
+|Rosetta|Resnet34_vd||rec_r34_vd_none_none_ctc|[Coming soon]()|
+|Rosetta|MobileNetV3||rec_mv3_none_none_ctc|[Coming soon]()|
+|CRNN|Resnet34_vd||rec_r34_vd_none_bilstm_ctc|[Coming soon]()|
+|CRNN|MobileNetV3||rec_mv3_none_bilstm_ctc|[Coming soon]()|
+|STAR-Net|Resnet34_vd||rec_r34_vd_tps_bilstm_ctc|[Coming soon]()|
+|STAR-Net|MobileNetV3||rec_mv3_tps_bilstm_ctc|[Coming soon]()|
+|RARE|Resnet34_vd||rec_r34_vd_tps_bilstm_attn|[Coming soon]()|
+|RARE|MobileNetV3||rec_mv3_tps_bilstm_attn|[Coming soon]()|
+|SRN|Resnet50_vd_fpn||rec_r50fpn_vd_none_srn|[Coming soon]()|
**Note:** SRN model uses data expansion method to expand the two training sets mentioned above, and the expanded data can be downloaded from [Baidu Drive](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA) (download code: y3ry).
From 1e15b1d1c2e9579b7e391d72814096effa5165c5 Mon Sep 17 00:00:00 2001
From: xmy0916 <863299715@qq.com>
Date: Thu, 3 Dec 2020 19:58:35 +0800
Subject: [PATCH 02/51] fix doc recognition ch&en
---
doc/doc_ch/recognition.md | 119 ++++++++++++++++++++++++--------------
1 file changed, 75 insertions(+), 44 deletions(-)
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 71be1e89d..6c5ea02fb 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -144,7 +144,6 @@ word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,
如果希望支持识别"空格"类别, 请将yml文件中的 `use_space_char` 字段设置为 `true`。
-**注意:`use_space_char` 仅在 `character_type=ch` 时生效**
### 启动训练
@@ -167,10 +166,9 @@ tar -xf rec_mv3_none_bilstm_ctc.tar && rm -rf rec_mv3_none_bilstm_ctc.tar
*如果您安装的是cpu版本,请将配置文件中的 `use_gpu` 字段修改为false*
```
-# GPU训练 支持单卡,多卡训练,通过CUDA_VISIBLE_DEVICES指定卡号
-export CUDA_VISIBLE_DEVICES=0,1,2,3
+# GPU训练 支持单卡,多卡训练,通过selected_gpus参数指定卡号
# 训练icdar15英文数据 并将训练日志保存为 tain_rec.log
-python3 tools/train.py -c configs/rec/rec_icdar15_train.yml 2>&1 | tee train_rec.log
+python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3' tools/train.py -c configs/rec/rec_icdar15_train.yml 2>&1 | tee train_rec.log
```
- 数据增强
@@ -212,37 +210,67 @@ PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/rec_icdar15_t
训练中文数据,推荐使用[rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml),如您希望尝试其他算法在中文数据集上的效果,请参考下列说明修改配置文件:
-以 `rec_mv3_none_none_ctc.yml` 为例:
+以 `rec_chinese_lite_train_v1.1.yml` 为例:
```
Global:
...
- # 修改 image_shape 以适应长文本
- image_shape: [3, 32, 320]
- ...
+ # 添加自定义字典,如修改字典请将路径指向新字典
+ character_dict_path: ppocr/utils/ppocr_keys_v1.txt
# 修改字符类型
character_type: ch
- # 添加自定义字典,如修改字典请将路径指向新字典
- character_dict_path: ./ppocr/utils/ppocr_keys_v1.txt
- # 训练时添加数据增强
- distort: true
+ ...
# 识别空格
- use_space_char: true
- ...
- # 修改reader类型
- reader_yml: ./configs/rec/rec_chinese_reader.yml
- ...
+ use_space_char: False
-...
Optimizer:
...
# 添加学习率衰减策略
- decay:
- function: cosine_decay
- # 每个 epoch 包含 iter 数
- step_each_epoch: 20
- # 总共训练epoch数
- total_epoch: 1000
+ lr:
+ name: Cosine
+ learning_rate: 0.001
+ ...
+
+...
+
+Train:
+ dataset:
+ # 数据集格式,支持LMDBDateSet以及SimpleDataSet
+ name: SimpleDataSet
+ # 数据集路径
+ data_dir: ./train_data/
+ # 训练集标签文件
+ label_file_list: ["./train_data/train_list.txt"]
+ transforms:
+ ...
+ - RecResizeImg:
+ # 修改 image_shape 以适应长文本
+ image_shape: [3, 32, 320]
+ ...
+ loader:
+ ...
+ # 单卡训练的batch_size
+ batch_size_per_card: 256
+ ...
+
+Eval:
+ dataset:
+ # 数据集格式,支持LMDBDateSet以及SimpleDataSet
+ name: SimpleDataSet
+ # 数据集路径
+ data_dir: ./train_data
+ # 验证集标签文件
+ label_file_list: ["./train_data/val_list.txt"]
+ transforms:
+ ...
+ - RecResizeImg:
+ # 修改 image_shape 以适应长文本
+ image_shape: [3, 32, 320]
+ ...
+ loader:
+ # 单卡验证的batch_size
+ batch_size_per_card: 256
+ ...
```
**注意,预测/评估时的配置文件请务必与训练一致。**
@@ -270,33 +298,36 @@ Global:
...
# 添加自定义字典,如修改字典请将路径指向新字典
character_dict_path: ./ppocr/utils/dict/french_dict.txt
- # 训练时添加数据增强
- distort: true
+ ...
# 识别空格
- use_space_char: true
- ...
- # 修改reader类型
- reader_yml: ./configs/rec/multi_languages/rec_french_reader.yml
- ...
-...
-```
-
-同时需要修改数据读取文件 `rec_french_reader.yml`:
-
-```
-TrainReader:
- ...
- # 修改训练数据存放的目录名
- img_set_dir: ./train_data
- # 修改 label 文件名称
- label_file_path: ./train_data/french_train.txt
+ use_space_char: False
...
+
+Train:
+ dataset:
+ # 数据集格式,支持LMDBDateSet以及SimpleDataSet
+ name: SimpleDataSet
+ # 数据集路径
+ data_dir: ./train_data/
+ # 训练集标签文件
+ label_file_list: ["./train_data/french_train.txt"]
+ ...
+
+Eval:
+ dataset:
+ # 数据集格式,支持LMDBDateSet以及SimpleDataSet
+ name: SimpleDataSet
+ # 数据集路径
+ data_dir: ./train_data
+ # 验证集标签文件
+ label_file_list: ["./train_data/french_val.txt"]
+ ...
```
### 评估
-评估数据集可以通过 `configs/rec/rec_icdar15_reader.yml` 修改EvalReader中的 `label_file_path` 设置。
+评估数据集可以通过 `configs/rec/rec_icdar15_train.yml` 修改Eval中的 `label_file_path` 设置。
*注意* 评估时必须确保配置文件中 infer_img 字段为空
```
From cb371c1eccf6c5f856e01b99d15fe51c532c3931 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Fri, 4 Dec 2020 17:09:28 +0800
Subject: [PATCH 03/51] first update inference.md
---
doc/doc_ch/inference.md | 123 ++++++++++++++++++++--------------------
1 file changed, 61 insertions(+), 62 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index 0432695a3..bcd078b9d 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -1,11 +1,11 @@
# 基于Python预测引擎推理
-inference 模型(`fluid.io.save_inference_model`保存的模型)
+inference 模型(`paddle.jit.save`保存的模型)
一般是模型训练完成后保存的固化模型,多用于预测部署。训练过程中保存的模型是checkpoints模型,保存的是模型的参数,多用于恢复训练等。
-与checkpoints模型相比,inference 模型会额外保存模型的结构信息,在预测部署、加速推理上性能优越,灵活方便,适合与实际系统集成。更详细的介绍请参考文档[分类预测框架](https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/extension/paddle_inference.md).
+与checkpoints模型相比,inference 模型会额外保存模型的结构信息,在预测部署、加速推理上性能优越,灵活方便,适合与实际系统集成。
-接下来首先介绍如何将训练的模型转换成inference模型,然后将依次介绍文本检测、文本识别以及两者串联基于预测引擎推理。
+接下来首先介绍如何将训练的模型转换成inference模型,然后将依次介绍文本检测、文本角度分类器、文本识别以及三者串联基于预测引擎推理。
- [一、训练模型转inference模型](#训练模型转inference模型)
@@ -42,24 +42,22 @@ inference 模型(`fluid.io.save_inference_model`保存的模型)
下载超轻量级中文检测模型:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_train.tar && tar xf ./ch_lite/ch_ppocr_mobile_v1.1_det_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
上述模型是以MobileNetV3为backbone训练的DB算法,将训练好的模型转换成inference模型只需要运行如下命令:
```
-# -c后面设置训练算法的yml配置文件
-# -o配置可选参数
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下, 不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_det_train/best_accuracy Global.save_inference_dir=./inference/det_db/
+python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
```
-转inference模型时,使用的配置文件和训练时使用的配置文件相同。另外,还需要设置配置文件中的`Global.checkpoints`、`Global.save_inference_dir`参数。
-其中`Global.checkpoints`指向训练中保存的模型参数文件,`Global.save_inference_dir`是生成的inference模型要保存的目录。
-转换成功后,在`save_inference_dir`目录下有两个文件:
+转inference模型时,使用的配置文件和训练时使用的配置文件相同。另外,还需要设置配置文件中的`Global.checkpoints`参数,其指向训练中保存的模型参数文件。
+转换成功后,在模型保存目录下有三个文件:
```
inference/det_db/
- └─ model 检测inference模型的program文件
- └─ params 检测inference模型的参数文件
+ ├── det.pdiparams # 检测inference模型的参数文件,需要重命名为params
+ ├── det.pdiparams.info # 检测inference模型的参数信息,可忽略
+ └── det.pdmodel # 检测inference模型的program文件,需要重命名为model
```
@@ -67,27 +65,24 @@ inference/det_db/
下载超轻量中文识别模型:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_train.tar && tar xf ./ch_lite/ch_ppocr_mobile_v1.1_rec_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
识别模型转inference模型与检测的方式相同,如下:
```
-# -c后面设置训练算法的yml配置文件
-# -o配置可选参数
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
-
-python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_rec_train/best_accuracy \
- Global.save_inference_dir=./inference/rec_crnn/
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
+python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o ./inference/rec_crnn/
```
**注意:**如果您是在自己的数据集上训练的模型,并且调整了中文字符的字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。
-转换成功后,在目录下有两个文件:
+转换成功后,在目录下有三个文件:
```
/inference/rec_crnn/
- └─ model 识别inference模型的program文件
- └─ params 识别inference模型的参数文件
+ ├── rec.pdiparams # 识别inference模型的参数文件,需要重命名为params
+ ├── rec.pdiparams.info # 识别inference模型的参数信息,可忽略
+ └── rec.pdmodel # 识别inference模型的program文件,需要重命名为model
```
@@ -95,25 +90,23 @@ python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_trai
下载方向分类模型:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar && tar xf ./ch_lite/ch_ppocr_mobile_v1.1_cls_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
方向分类模型转inference模型与检测的方式相同,如下:
```
-# -c后面设置训练算法的yml配置文件
-# -o配置可选参数
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_cls_train/best_accuracy \
- Global.save_inference_dir=./inference/cls/
+python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
```
-转换成功后,在目录下有两个文件:
+转换成功后,在目录下有三个文件:
```
/inference/cls/
- └─ model 识别inference模型的program文件
- └─ params 识别inference模型的参数文件
+ ├── cls.pdiparams # 分类inference模型的参数文件,需要重命名为params
+ ├── cls.pdiparams.info # 分类inference模型的参数信息,可忽略
+ └── cls.pdmodel # 分类inference模型的program文件,需要重命名为model
```
@@ -134,7 +127,9 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di

-通过设置参数`det_max_side_len`的大小,改变检测算法中图片规范化的最大值。当图片的长宽都小于`det_max_side_len`,则使用原图预测,否则将图片等比例缩放到最大值,进行预测。该参数默认设置为`det_max_side_len=960`。 如果输入图片的分辨率比较大,而且想使用更大的分辨率预测,可以执行如下命令:
+通过参数`limit_type`和`det_limit_side_len`来对图片的尺寸进行限制限,`max`为限制长边长度<`det_limit_side_len`,`min`为限制短边长度>`det_limit_side_len`,
+图片不满足限制条件时(`max`时>`det_limit_side_len`或`min`时<`det_limit_side_len`),将对图片进行等比例缩放。
+该参数默认设置为`limit_type='max',det_max_side_len=960`。 如果输入图片的分辨率比较大,而且想使用更大的分辨率预测,可以执行如下命令:
```
python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_dir="./inference/det_db/" --det_max_side_len=1200
@@ -148,14 +143,13 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
### 2. DB文本检测模型推理
-首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)),可以使用如下命令进行转换:
+首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
```
-# -c后面设置训练算法的yml配置文件
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o Global.checkpoints="./models/det_r50_vd_db/best_accuracy" Global.save_inference_dir="./inference/det_db"
+python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
```
DB文本检测模型推理,可以执行如下命令:
@@ -173,12 +167,11 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs_en/img_10.jpg" --det_
### 3. EAST文本检测模型推理
-首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)),可以使用如下命令进行转换:
+首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
```
-# -c后面设置训练算法的yml配置文件
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
```
@@ -198,9 +191,12 @@ python3 tools/infer/predict_det.py --det_algorithm="EAST" --image_dir="./doc/img
### 4. SAST文本检测模型推理
#### (1). 四边形文本检测模型(ICDAR2015)
-首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)),可以使用如下命令进行转换:
+首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
```
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o Global.checkpoints="./models/sast_r50_vd_icdar2015/best_accuracy" Global.save_inference_dir="./inference/det_sast_ic15"
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
+
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
```
**SAST文本检测模型推理,需要设置参数`--det_algorithm="SAST"`**,可以执行如下命令:
```
@@ -211,10 +207,13 @@ python3 tools/infer/predict_det.py --det_algorithm="SAST" --image_dir="./doc/img

#### (2). 弯曲文本检测模型(Total-Text)
-首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)),可以使用如下命令进行转换:
+首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
```
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o Global.checkpoints="./models/sast_r50_vd_total_text/best_accuracy" Global.save_inference_dir="./inference/det_sast_tt"
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
+
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o "./inference/det_sast_tt"
```
**SAST文本检测模型推理,需要设置参数`--det_algorithm="SAST"`,同时,还需要增加参数`--det_sast_polygon=True`,**可以执行如下命令:
@@ -256,14 +255,13 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
我们以STAR-Net为例,介绍基于CTC损失的识别模型推理。 CRNN和Rosetta使用方式类似,不用设置识别算法参数rec_algorithm。
首先将STAR-Net文本识别训练过程中保存的模型,转换成inference model。以基于Resnet34_vd骨干网络,使用MJSynth和SynthText两个英文文本识别合成数据集训练
-的模型为例([模型下载地址](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)),可以使用如下命令进行转换:
+的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
```
-# -c后面设置训练算法的yml配置文件
-# Global.checkpoints参数设置待转换的训练模型地址,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# Global.save_inference_dir参数设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -o 后面设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o Global.checkpoints="./models/rec_r34_vd_tps_bilstm_ctc/best_accuracy" Global.save_inference_dir="./inference/starnet"
+python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
```
STAR-Net文本识别模型推理,可以执行如下命令:
@@ -275,11 +273,9 @@ python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png
### 3. 基于Attention损失的识别模型推理
-基于Attention损失的识别模型与ctc不同,需要额外设置识别算法参数 --rec_algorithm="RARE"
-
RARE 文本识别模型推理,可以执行如下命令:
```
-python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rare/" --rec_image_shape="3, 32, 100" --rec_char_type="en" --rec_algorithm="RARE"
+python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rare/" --rec_image_shape="3, 32, 100" --rec_char_type="en"
```

@@ -298,17 +294,17 @@ Predicts of ./doc/imgs_words_en/word_336.png:['super', 0.9999555]
self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz"
dict_character = list(self.character_str)
```
+
### 4. 基于SRN损失的识别模型推理
-基于SRN损失的识别模型,需要额外设置识别算法参数 --rec_algorithm="SRN"。 同时需要保证预测shape与训练时一致,如: --rec_image_shape="1, 64, 256"
+基于SRN损失的识别模型需要保证预测shape与训练时一致,如: --rec_image_shape="1, 64, 256"
```
python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" \
--rec_model_dir="./inference/srn/" \
--rec_image_shape="1, 64, 256" \
- --rec_char_type="en" \
- --rec_algorithm="SRN"
+ --rec_char_type="en"
```
@@ -350,11 +346,14 @@ python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words/korean/1.jpg" -
python3 tools/infer/predict_cls.py --image_dir="./doc/imgs_words/ch/word_4.jpg" --cls_model_dir="./inference/cls/"
```
-
+
执行命令后,上面图像的预测结果(分类的方向和得分)会打印到屏幕上,示例如下:
-Predicts of ./doc/imgs_words/ch/word_4.jpg:['0', 0.9999963]
+```
+infer_img: doc/imgs_words/ch/word_1.jpg
+ result: ('0', 0.9998784)
+```
## 五、文本检测、方向分类和文字识别串联推理
From d986c2208569c063a040e7add805da8e03c314d9 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Mon, 7 Dec 2020 15:48:46 +0800
Subject: [PATCH 04/51] update inference doc
---
doc/doc_ch/inference.md | 6 +--
doc/doc_en/inference_en.md | 107 ++++++++++++++++++-------------------
2 files changed, 54 insertions(+), 59 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index bcd078b9d..3af84807e 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -127,12 +127,12 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di

-通过参数`limit_type`和`det_limit_side_len`来对图片的尺寸进行限制限,`max`为限制长边长度<`det_limit_side_len`,`min`为限制短边长度>`det_limit_side_len`,
-图片不满足限制条件时(`max`时>`det_limit_side_len`或`min`时<`det_limit_side_len`),将对图片进行等比例缩放。
+通过参数`limit_type`和`det_limit_side_len`来对图片的尺寸进行限制限,`limit_type=max`为限制长边长度<`det_limit_side_len`,`limit_type=min`为限制短边长度>`det_limit_side_len`,
+图片不满足限制条件时(`limit_type=max`时长边长度>`det_limit_side_len`或`limit_type=min`时短边长度<`det_limit_side_len`),将对图片进行等比例缩放。
该参数默认设置为`limit_type='max',det_max_side_len=960`。 如果输入图片的分辨率比较大,而且想使用更大的分辨率预测,可以执行如下命令:
```
-python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_dir="./inference/det_db/" --det_max_side_len=1200
+python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_dir="./inference/det_db/" --det_limit_type=max --det_limit_side_len=1200
```
如果想使用CPU进行预测,执行命令如下
diff --git a/doc/doc_en/inference_en.md b/doc/doc_en/inference_en.md
index 609b65fa5..31f6b1e5b 100644
--- a/doc/doc_en/inference_en.md
+++ b/doc/doc_en/inference_en.md
@@ -1,13 +1,13 @@
# Reasoning based on Python prediction engine
-The inference model (the model saved by `fluid.io.save_inference_model`) is generally a solidified model saved after the model training is completed, and is mostly used to give prediction in deployment.
+The inference model (the model saved by `paddle.jit.save`) is generally a solidified model saved after the model training is completed, and is mostly used to give prediction in deployment.
The model saved during the training process is the checkpoints model, which saves the parameters of the model and is mostly used to resume training.
Compared with the checkpoints model, the inference model will additionally save the structural information of the model. It has superior performance in predicting in deployment and accelerating inferencing, is flexible and convenient, and is suitable for integration with actual systems. For more details, please refer to the document [Classification Framework](https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/extension/paddle_inference.md).
-Next, we first introduce how to convert a trained model into an inference model, and then we will introduce text detection, text recognition, and the concatenation of them based on inference model.
+Next, we first introduce how to convert a trained model into an inference model, and then we will introduce text detection, text recognition, angle class, and the concatenation of them based on inference model.
- [CONVERT TRAINING MODEL TO INFERENCE MODEL](#CONVERT)
- [Convert detection model to inference model](#Convert_detection_model)
@@ -44,26 +44,24 @@ Next, we first introduce how to convert a trained model into an inference model,
Download the lightweight Chinese detection model:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_train.tar && tar xf ./ch_lite/ch_ppocr_mobile_v1.1_det_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
The above model is a DB algorithm trained with MobileNetV3 as the backbone. To convert the trained model into an inference model, just run the following command:
```
-# -c Set the training algorithm yml configuration file
-# -o Set optional parameters
-# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# Global.save_inference_dir Set the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_det_train/best_accuracy Global.save_inference_dir=./inference/det_db/
+python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
```
-When converting to an inference model, the configuration file used is the same as the configuration file used during training. In addition, you also need to set the `Global.checkpoints` and `Global.save_inference_dir` parameters in the configuration file.
-`Global.checkpoints` points to the model parameter file saved during training, and `Global.save_inference_dir` is the directory where the generated inference model is saved.
-After the conversion is successful, there are two files in the `save_inference_dir` directory:
+When converting to an inference model, the configuration file used is the same as the configuration file used during training. In addition, you also need to set the `Global.checkpoints` parameter in the configuration file.
+After the conversion is successful, there are three files in the model save directory:
```
inference/det_db/
- └─ model Check the program file of inference model
- └─ params Check the parameter file of the inference model
+ ├── det.pdiparams # The parameter file of detection inference model which needs to be renamed to params
+ ├── det.pdiparams.info # The parameter information of detection inference model, which can be ignored
+ └── det.pdmodel # The program file of detection inference model which needs to be renamed to model
```
@@ -71,26 +69,25 @@ inference/det_db/
Download the lightweight Chinese recognition model:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_train.tar && tar xf ch_ppocr_mobile_v1.1_rec_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
The recognition model is converted to the inference model in the same way as the detection, as follows:
```
-# -c Set the training algorithm yml configuration file
-# -o Set optional parameters
-# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# Global.save_inference_dir Set the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_rec_train/best_accuracy \
+python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
```
If you have a model trained on your own dataset with a different dictionary file, please make sure that you modify the `character_dict_path` in the configuration file to your dictionary file path.
-After the conversion is successful, there are two files in the directory:
+After the conversion is successful, there are three files in the model save directory:
```
-/inference/rec_crnn/
- └─ model Identify the saved model files
- └─ params Identify the parameter files of the inference model
+inference/det_db/
+ ├── rec.pdiparams # The parameter file of recognition inference model which needs to be renamed to params
+ ├── rec.pdiparams.info # The parameter information of recognition inference model, which can be ignored
+ └── rec.pdmodel # The program file of detection recognition model which needs to be renamed to model
```
@@ -98,18 +95,15 @@ After the conversion is successful, there are two files in the directory:
Download the angle classification model:
```
-wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar && tar xf ./ch_lite/ch_ppocr_mobile_v1.1_cls_train.tar -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
The angle classification model is converted to the inference model in the same way as the detection, as follows:
```
-# -c Set the training algorithm yml configuration file
-# -o Set optional parameters
-# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# Global.save_inference_dir Set the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v1.1_cls_train/best_accuracy \
- Global.save_inference_dir=./inference/cls/
+python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
```
After the conversion is successful, there are two files in the directory:
@@ -139,10 +133,12 @@ The visual text detection results are saved to the ./inference_results folder by

-By setting the size of the parameter `det_max_side_len`, the maximum value of picture normalization in the detection algorithm is changed. When the length and width of the picture are less than det_max_side_len, the original picture is used for prediction, otherwise the picture is scaled to the maximum value for prediction. This parameter is set to det_max_side_len=960 by default. If the resolution of the input picture is relatively large and you want to use a larger resolution for prediction, you can execute the following command:
+The size of the image is limited by the parameters `limit_type` and `det_limit_side_len`, `limit_type=max` is to limit the length of the long side <`det_limit_side_len`, and `limit_type=min` is to limit the length of the short side>`det_limit_side_len`,
+When the picture does not meet the restriction conditions (for `limit_type=max`and long side >`det_limit_side_len` or for `min` and short side <`det_limit_side_len`), the image will be scaled proportionally.
+This parameter is set to `limit_type='max', det_max_side_len=960` by default. If the resolution of the input picture is relatively large, and you want to use a larger resolution prediction, you can execute the following command:
```
-python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_dir="./inference/det_db/" --det_max_side_len=1200
+python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_dir="./inference/det_db/" --det_limit_type=max --det_limit_side_len=1200
```
If you want to use the CPU for prediction, execute the command as follows
@@ -153,14 +149,13 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
### 2. DB TEXT DETECTION MODEL INFERENCE
-First, convert the model saved in the DB text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)), you can use the following command to convert:
+First, convert the model saved in the DB text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-# Set the yml configuration file of the training algorithm after -c
-# The Global.checkpoints parameter sets the address of the training model to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# The Global.save_inference_dir parameter sets the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o Global.checkpoints="./models/det_r50_vd_db/best_accuracy" Global.save_inference_dir="./inference/det_db"
+python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
```
DB text detection model inference, you can execute the following command:
@@ -178,16 +173,14 @@ The visualized text detection results are saved to the `./inference_results` fol
### 3. EAST TEXT DETECTION MODEL INFERENCE
-First, convert the model saved in the EAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)), you can use the following command to convert:
+First, convert the model saved in the EAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-# Set the yml configuration file of the training algorithm after -c
-# The Global.checkpoints parameter sets the address of the training model to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# The Global.save_inference_dir parameter sets the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
```
-
**For EAST text detection model inference, you need to set the parameter ``--det_algorithm="EAST"``**, run the following command:
```
@@ -204,10 +197,13 @@ The visualized text detection results are saved to the `./inference_results` fol
### 4. SAST TEXT DETECTION MODEL INFERENCE
#### (1). Quadrangle text detection model (ICDAR2015)
-First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)), you can use the following command to convert:
+First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o Global.checkpoints="./models/sast_r50_vd_icdar2015/best_accuracy" Global.save_inference_dir="./inference/det_sast_ic15"
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
+
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
```
**For SAST quadrangle text detection model inference, you need to set the parameter `--det_algorithm="SAST"`**, run the following command:
@@ -266,14 +262,13 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
Taking STAR-Net as an example, we introduce the recognition model inference based on CTC loss. CRNN and Rosetta are used in a similar way, by setting the recognition algorithm parameter `rec_algorithm`.
-First, convert the model saved in the STAR-Net text recognition training process into an inference model. Taking the model based on Resnet34_vd backbone network, using MJSynth and SynthText (two English text recognition synthetic datasets) for training, as an example ([model download address](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)). It can be converted as follow:
+First, convert the model saved in the STAR-Net text recognition training process into an inference model. Taking the model based on Resnet34_vd backbone network, using MJSynth and SynthText (two English text recognition synthetic datasets) for training, as an example ([model download address](link)). It can be converted as follow:
```
-# Set the yml configuration file of the training algorithm after -c
-# The Global.checkpoints parameter sets the address of the training model to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# The Global.save_inference_dir parameter sets the address where the converted model will be saved.
+# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o Global.checkpoints="./models/rec_r34_vd_tps_bilstm_ctc/best_accuracy" Global.save_inference_dir="./inference/starnet"
+python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
```
For STAR-Net text recognition model inference, execute the following commands:
@@ -304,15 +299,13 @@ dict_character = list(self.character_str)
### 4. SRN-BASED TEXT RECOGNITION MODEL INFERENCE
-The recognition model based on SRN requires additional setting of the recognition algorithm parameter --rec_algorithm="SRN".
-At the same time, it is necessary to ensure that the predicted shape is consistent with the training, such as: --rec_image_shape="1, 64, 256"
+The recognition model based on SRN need to ensure that the predicted shape is consistent with the training, such as: --rec_image_shape="1, 64, 256"
```
python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" \
--rec_model_dir="./inference/srn/" \
--rec_image_shape="1, 64, 256" \
- --rec_char_type="en" \
- --rec_algorithm="SRN"
+ --rec_char_type="en"
```
@@ -357,12 +350,14 @@ For angle classification model inference, you can execute the following commands
python3 tools/infer/predict_cls.py --image_dir="./doc/imgs_words/ch/word_4.jpg" --cls_model_dir="./inference/cls/"
```
-
+
After executing the command, the prediction results (classification angle and score) of the above image will be printed on the screen.
-Predicts of ./doc/imgs_words/ch/word_4.jpg:['0', 0.9999963]
-
+```
+infer_img: doc/imgs_words_en/word_10.png
+ result: ('0', 0.9999995)
+```
## TEXT DETECTION ANGLE CLASSIFICATION AND RECOGNITION INFERENCE CONCATENATION
From bccb261228fd2fe21534f8b9eabf21fc8856974b Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Mon, 7 Dec 2020 16:32:57 +0800
Subject: [PATCH 05/51] =?UTF-8?q?rename=20=E5=9C=B0=E5=9D=80=20to=20link?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/doc_ch/inference.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index 3af84807e..1b8554b92 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -143,7 +143,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
### 2. DB文本检测模型推理
-首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
+首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
@@ -167,7 +167,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs_en/img_10.jpg" --det_
### 3. EAST文本检测模型推理
-首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
+首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
@@ -191,7 +191,7 @@ python3 tools/infer/predict_det.py --det_algorithm="EAST" --image_dir="./doc/img
### 4. SAST文本检测模型推理
#### (1). 四边形文本检测模型(ICDAR2015)
-首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
+首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
@@ -207,7 +207,7 @@ python3 tools/infer/predict_det.py --det_algorithm="SAST" --image_dir="./doc/img

#### (2). 弯曲文本检测模型(Total-Text)
-首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
+首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
@@ -255,7 +255,7 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
我们以STAR-Net为例,介绍基于CTC损失的识别模型推理。 CRNN和Rosetta使用方式类似,不用设置识别算法参数rec_algorithm。
首先将STAR-Net文本识别训练过程中保存的模型,转换成inference model。以基于Resnet34_vd骨干网络,使用MJSynth和SynthText两个英文文本识别合成数据集训练
-的模型为例([模型下载地址](地址)),可以使用如下命令进行转换:
+的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
From 2af8f2a011c67fdc44d31358666acf51e4728fc9 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Wed, 9 Dec 2020 16:35:55 +0800
Subject: [PATCH 06/51] update quickstart doc, model link uses link as a
placeholder
---
doc/doc_ch/quickstart.md | 14 +++++++-------
doc/doc_en/quickstart_en.md | 14 +++++++-------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/doc/doc_ch/quickstart.md b/doc/doc_ch/quickstart.md
index 97c3d41da..b10258857 100644
--- a/doc/doc_ch/quickstart.md
+++ b/doc/doc_ch/quickstart.md
@@ -5,7 +5,7 @@
请先参考[快速安装](./installation.md)配置PaddleOCR运行环境。
-*注意:也可以通过 whl 包安装使用PaddleOCR,具体参考[Paddleocr Package使用说明](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md)。*
+*注意:也可以通过 whl 包安装使用PaddleOCR,具体参考[Paddleocr Package使用说明](./whl.md)。*
## 2.inference模型下载
@@ -13,8 +13,8 @@
| 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 |
| ------------ | --------------- | ----------------|---- | ---------- | -------- |
-| 中英文超轻量OCR模型(8.1M) | ch_ppocr_mobile_v1.1_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_pre.tar) |
-| 中英文通用OCR模型(155.1M) |ch_ppocr_server_v1.1_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_pre.tar) |
+| 中英文超轻量OCR模型(xM) | |移动端&服务器端|[推理模型](link) / [预训练模型](link)|[推理模型]({}) / [预训练模型]({}) |[推理模型]({}) / [预训练模型]({}) |
+| 中英文通用OCR模型(xM) | |服务器端 |[推理模型]({}) / [预训练模型]({}) |[推理模型]({}) / [预训练模型]({}) |[推理模型]({}) / [预训练模型]({}}) |
* windows 环境下如果没有安装wget,下载模型时可将链接复制到浏览器中下载,并解压放置在相应目录下
@@ -37,11 +37,11 @@ cd ..
```
mkdir inference && cd inference
# 下载超轻量级中文OCR模型的检测模型并解压
-wget https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_infer.tar && tar xf ch_ppocr_mobile_v1.1_det_infer.tar
+wget {} && tar xf ch_ppocr_mobile_v1.1_det_infer.tar
# 下载超轻量级中文OCR模型的识别模型并解压
-wget https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_infer.tar && tar xf ch_ppocr_mobile_v1.1_rec_infer.tar
+wget {} && tar xf ch_ppocr_mobile_v1.1_rec_infer.tar
# 下载超轻量级中文OCR模型的文本方向分类器模型并解压
-wget https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar && tar xf ch_ppocr_mobile_v1.1_cls_infer.tar
+wget {} && tar xf ch_ppocr_mobile_v1.1_cls_infer.tar
cd ..
```
@@ -63,7 +63,7 @@ cd ..
## 3.单张图像或者图像集合预测
-以下代码实现了文本检测、识别串联推理,在执行预测时,需要通过参数image_dir指定单张图像或者图像集合的路径、参数`det_model_dir`指定检测inference模型的路径、参数`rec_model_dir`指定识别inference模型的路径、参数`use_angle_cls`指定是否使用方向分类器、参数`cls_model_dir`指定方向分类器inference模型的路径、参数`use_space_char`指定是否预测空格字符。可视化识别结果默认保存到`./inference_results`文件夹里面。
+以下代码实现了文本检测、方向分类器和识别串联推理,在执行预测时,需要通过参数image_dir指定单张图像或者图像集合的路径、参数`det_model_dir`指定检测inference模型的路径、参数`rec_model_dir`指定识别inference模型的路径、参数`use_angle_cls`指定是否使用方向分类器、参数`cls_model_dir`指定方向分类器inference模型的路径、参数`use_space_char`指定是否预测空格字符。可视化识别结果默认保存到`./inference_results`文件夹里面。
```bash
diff --git a/doc/doc_en/quickstart_en.md b/doc/doc_en/quickstart_en.md
index 6a5f36934..6d4ce95d3 100644
--- a/doc/doc_en/quickstart_en.md
+++ b/doc/doc_en/quickstart_en.md
@@ -5,7 +5,7 @@
Please refer to [quick installation](./installation_en.md) to configure the PaddleOCR operating environment.
-* Note: Support the use of PaddleOCR through whl package installation,pelease refer [PaddleOCR Package](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/whl_en.md).
+* Note: Support the use of PaddleOCR through whl package installation,pelease refer [PaddleOCR Package](./whl_en.md).
## 2.inference models
@@ -14,8 +14,8 @@ The detection and recognition models on the mobile and server sides are as follo
| Model introduction | Model name | Recommended scene | Detection model | Direction Classifier | Recognition model |
| ------------ | --------------- | ----------------|---- | ---------- | -------- |
-| Ultra-lightweight Chinese OCR model(8.1M) | ch_ppocr_mobile_v1.1_xx |Mobile-side/Server-side|[inference model](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_train.tar)|[inference model](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_pre.tar) |
-| Universal Chinese OCR model(155.1M) |ch_ppocr_server_v1.1_xx|Server-side |[inference model](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_infer.tar) / [pretrained model](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_pre.tar) |
+| Ultra-lightweight Chinese OCR model(xM) | ch_ppocr_mobile_v1.1_xx |Mobile-side/Server-side|[inference model](link) / [pretrained model](link)|[inference model](link) / [pretrained model](link) |[inference model](link) / [pretrained model](link) |
+| Universal Chinese OCR model(xM) |ch_ppocr_server_v1.1_xx|Server-side |[inference model](link) / [pretrained model](link) |[inference model](link) / [pretrained model](link) |[inference model](link) / [pretrained model](link) |
* If `wget` is not installed in the windows environment, you can copy the link to the browser to download when downloading the model, then uncompress it and place it in the corresponding directory.
@@ -37,11 +37,11 @@ Take the ultra-lightweight model as an example:
```
mkdir inference && cd inference
# Download the detection model of the ultra-lightweight Chinese OCR model and uncompress it
-wget https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_infer.tar && tar xf ch_ppocr_mobile_v1.1_det_infer.tar
+wget link && tar xf ch_ppocr_mobile_v1.1_det_infer.tar
# Download the recognition model of the ultra-lightweight Chinese OCR model and uncompress it
-wget https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_infer.tar && tar xf ch_ppocr_mobile_v1.1_rec_infer.tar
+wget link && tar xf ch_ppocr_mobile_v1.1_rec_infer.tar
# Download the direction classifier model of the ultra-lightweight Chinese OCR model and uncompress it
-wget https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar && tar xf ch_ppocr_mobile_v1.1_cls_infer.tar
+wget link && tar xf ch_ppocr_mobile_v1.1_cls_infer.tar
cd ..
```
@@ -63,7 +63,7 @@ After decompression, the file structure should be as follows:
## 3. Single image or image set prediction
-* The following code implements text detection and recognition process. When performing prediction, you need to specify the path of a single image or image set through the parameter `image_dir`, the parameter `det_model_dir` specifies the path to detect the inference model, the parameter `rec_model_dir` specifies the path to identify the inference model, the parameter `use_angle_cls` specifies whether to use the direction classifier, the parameter `cls_model_dir` specifies the path to identify the direction classifier model, the parameter `use_space_char` specifies whether to predict the space char. The visual results are saved to the `./inference_results` folder by default.
+* The following code implements text detection、angle class and recognition process. When performing prediction, you need to specify the path of a single image or image set through the parameter `image_dir`, the parameter `det_model_dir` specifies the path to detect the inference model, the parameter `rec_model_dir` specifies the path to identify the inference model, the parameter `use_angle_cls` specifies whether to use the direction classifier, the parameter `cls_model_dir` specifies the path to identify the direction classifier model, the parameter `use_space_char` specifies whether to predict the space char. The visual results are saved to the `./inference_results` folder by default.
From 72cbcc23e1b88be4db8871932372f54ed0934097 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Wed, 9 Dec 2020 17:42:14 +0800
Subject: [PATCH 07/51] delete srn
---
doc/doc_ch/inference.md | 22 ++++------------------
doc/doc_en/inference_en.md | 22 ++++------------------
2 files changed, 8 insertions(+), 36 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index 1b8554b92..805414d32 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -23,9 +23,8 @@ inference 模型(`paddle.jit.save`保存的模型)
- [1. 超轻量中文识别模型推理](#超轻量中文识别模型推理)
- [2. 基于CTC损失的识别模型推理](#基于CTC损失的识别模型推理)
- [3. 基于Attention损失的识别模型推理](#基于Attention损失的识别模型推理)
- - [4. 基于SRN损失的识别模型推理](#基于SRN损失的识别模型推理)
- - [5. 自定义文本识别字典的推理](#自定义文本识别字典的推理)
- - [6. 多语言模型的推理](#多语言模型的推理)
+ - [4. 自定义文本识别字典的推理](#自定义文本识别字典的推理)
+ - [5. 多语言模型的推理](#多语言模型的推理)
- [四、方向分类模型推理](#方向识别模型推理)
- [1. 方向分类模型推理](#方向分类模型推理)
@@ -295,20 +294,7 @@ self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz"
dict_character = list(self.character_str)
```
-
-### 4. 基于SRN损失的识别模型推理
-
-基于SRN损失的识别模型需要保证预测shape与训练时一致,如: --rec_image_shape="1, 64, 256"
-
-```
-python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" \
- --rec_model_dir="./inference/srn/" \
- --rec_image_shape="1, 64, 256" \
- --rec_char_type="en"
-```
-
-
-### 5. 自定义文本识别字典的推理
+### 4. 自定义文本识别字典的推理
如果训练时修改了文本的字典,在使用inference模型预测时,需要通过`--rec_char_dict_path`指定使用的字典路径
```
@@ -316,7 +302,7 @@ python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png
```
-### 6. 多语言模型的推理
+### 5. 多语言模型的推理
如果您需要预测的是其他语言模型,在使用inference模型预测时,需要通过`--rec_char_dict_path`指定使用的字典路径, 同时为了得到正确的可视化结果,
需要通过 `--vis_font_path` 指定可视化的字体路径,`doc/` 路径下有默认提供的小语种字体,例如韩文识别:
diff --git a/doc/doc_en/inference_en.md b/doc/doc_en/inference_en.md
index 31f6b1e5b..8ce0ea4d2 100644
--- a/doc/doc_en/inference_en.md
+++ b/doc/doc_en/inference_en.md
@@ -26,9 +26,8 @@ Next, we first introduce how to convert a trained model into an inference model,
- [1. LIGHTWEIGHT CHINESE MODEL](#LIGHTWEIGHT_RECOGNITION)
- [2. CTC-BASED TEXT RECOGNITION MODEL INFERENCE](#CTC-BASED_RECOGNITION)
- [3. ATTENTION-BASED TEXT RECOGNITION MODEL INFERENCE](#ATTENTION-BASED_RECOGNITION)
- - [4. SRN-BASED TEXT RECOGNITION MODEL INFERENCE](#SRN-BASED_RECOGNITION)
- - [5. TEXT RECOGNITION MODEL INFERENCE USING CUSTOM CHARACTERS DICTIONARY](#USING_CUSTOM_CHARACTERS)
- - [6. MULTILINGUAL MODEL INFERENCE](MULTILINGUAL_MODEL_INFERENCE)
+ - [4. TEXT RECOGNITION MODEL INFERENCE USING CUSTOM CHARACTERS DICTIONARY](#USING_CUSTOM_CHARACTERS)
+ - [5. MULTILINGUAL MODEL INFERENCE](MULTILINGUAL_MODEL_INFERENCE)
- [ANGLE CLASSIFICATION MODEL INFERENCE](#ANGLE_CLASS_MODEL_INFERENCE)
- [1. ANGLE CLASSIFICATION MODEL INFERENCE](#ANGLE_CLASS_MODEL_INFERENCE)
@@ -296,21 +295,8 @@ self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz"
dict_character = list(self.character_str)
```
-
-### 4. SRN-BASED TEXT RECOGNITION MODEL INFERENCE
-
-The recognition model based on SRN need to ensure that the predicted shape is consistent with the training, such as: --rec_image_shape="1, 64, 256"
-
-```
-python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" \
- --rec_model_dir="./inference/srn/" \
- --rec_image_shape="1, 64, 256" \
- --rec_char_type="en"
-```
-
-
-### 5. TEXT RECOGNITION MODEL INFERENCE USING CUSTOM CHARACTERS DICTIONARY
+### 4. TEXT RECOGNITION MODEL INFERENCE USING CUSTOM CHARACTERS DICTIONARY
If the chars dictionary is modified during training, you need to specify the new dictionary path by setting the parameter `rec_char_dict_path` when using your inference model to predict.
```
@@ -318,7 +304,7 @@ python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png
```
-### 6. MULTILINGAUL MODEL INFERENCE
+### 5. MULTILINGAUL MODEL INFERENCE
If you need to predict other language models, when using inference model prediction, you need to specify the dictionary path used by `--rec_char_dict_path`. At the same time, in order to get the correct visualization results,
You need to specify the visual font path through `--vis_font_path`. There are small language fonts provided by default under the `doc/` path, such as Korean recognition:
From 13cc1f3c41c97447342ebd4fe753100ebcd95bc8 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Wed, 9 Dec 2020 18:38:27 +0800
Subject: [PATCH 08/51] delete rename
---
doc/doc_ch/inference.md | 8 ++++----
doc/doc_en/inference_en.md | 15 ++++++++-------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index 805414d32..a37b50df6 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -79,9 +79,9 @@ python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_trai
转换成功后,在目录下有三个文件:
```
/inference/rec_crnn/
- ├── rec.pdiparams # 识别inference模型的参数文件,需要重命名为params
+ ├── rec.pdiparams # 识别inference模型的参数文件
├── rec.pdiparams.info # 识别inference模型的参数信息,可忽略
- └── rec.pdmodel # 识别inference模型的program文件,需要重命名为model
+ └── rec.pdmodel # 识别inference模型的program文件
```
@@ -103,9 +103,9 @@ python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
转换成功后,在目录下有三个文件:
```
/inference/cls/
- ├── cls.pdiparams # 分类inference模型的参数文件,需要重命名为params
+ ├── cls.pdiparams # 分类inference模型的参数文件
├── cls.pdiparams.info # 分类inference模型的参数信息,可忽略
- └── cls.pdmodel # 分类inference模型的program文件,需要重命名为model
+ └── cls.pdmodel # 分类inference模型的program文件
```
diff --git a/doc/doc_en/inference_en.md b/doc/doc_en/inference_en.md
index 8ce0ea4d2..e103c6c64 100644
--- a/doc/doc_en/inference_en.md
+++ b/doc/doc_en/inference_en.md
@@ -58,9 +58,9 @@ When converting to an inference model, the configuration file used is the same a
After the conversion is successful, there are three files in the model save directory:
```
inference/det_db/
- ├── det.pdiparams # The parameter file of detection inference model which needs to be renamed to params
+ ├── det.pdiparams # The parameter file of detection inference model
├── det.pdiparams.info # The parameter information of detection inference model, which can be ignored
- └── det.pdmodel # The program file of detection inference model which needs to be renamed to model
+ └── det.pdmodel # The program file of detection inference model
```
@@ -84,9 +84,9 @@ If you have a model trained on your own dataset with a different dictionary file
After the conversion is successful, there are three files in the model save directory:
```
inference/det_db/
- ├── rec.pdiparams # The parameter file of recognition inference model which needs to be renamed to params
+ ├── rec.pdiparams # The parameter file of recognition inference model
├── rec.pdiparams.info # The parameter information of recognition inference model, which can be ignored
- └── rec.pdmodel # The program file of detection recognition model which needs to be renamed to model
+ └── rec.pdmodel # The program file of recognition model
```
@@ -107,9 +107,10 @@ python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
After the conversion is successful, there are two files in the directory:
```
-/inference/cls/
- └─ model Identify the saved model files
- └─ params Identify the parameter files of the inference model
+inference/det_db/
+ ├── rec.pdiparams # The parameter file of angle class inference model
+ ├── rec.pdiparams.info # The parameter information of angle class inference model, which can be ignored
+ └── rec.pdmodel # The program file of angle class model
```
From fa0ad0f4fd7b45bbf750b83b4bf51ffbce1c5e3e Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Wed, 9 Dec 2020 18:40:44 +0800
Subject: [PATCH 09/51] rename inference model name
---
deploy/cpp_infer/src/ocr_cls.cpp | 2 +-
deploy/cpp_infer/src/ocr_det.cpp | 2 +-
deploy/cpp_infer/src/ocr_rec.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/deploy/cpp_infer/src/ocr_cls.cpp b/deploy/cpp_infer/src/ocr_cls.cpp
index 40debaa78..679397275 100644
--- a/deploy/cpp_infer/src/ocr_cls.cpp
+++ b/deploy/cpp_infer/src/ocr_cls.cpp
@@ -81,7 +81,7 @@ cv::Mat Classifier::Run(cv::Mat &img) {
void Classifier::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + "/cls.pdmodel", model_dir + "/cls.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_det.cpp b/deploy/cpp_infer/src/ocr_det.cpp
index 1e1aaa1bf..3ca4cc26b 100644
--- a/deploy/cpp_infer/src/ocr_det.cpp
+++ b/deploy/cpp_infer/src/ocr_det.cpp
@@ -18,7 +18,7 @@ namespace PaddleOCR {
void DBDetector::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + "/det.pdmodel", model_dir + "/det.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp
index 009b6b75f..0b6d0532b 100644
--- a/deploy/cpp_infer/src/ocr_rec.cpp
+++ b/deploy/cpp_infer/src/ocr_rec.cpp
@@ -103,7 +103,7 @@ void CRNNRecognizer::Run(std::vector>> boxes,
void CRNNRecognizer::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + "/rec.pdmodel", model_dir + "/rec.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
From 204ab814f1b65fbd9eda56028d824d702817ebcc Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Wed, 9 Dec 2020 18:42:47 +0800
Subject: [PATCH 10/51] delete rename
---
doc/doc_ch/inference.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index a37b50df6..ae1429d86 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -54,9 +54,9 @@ python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/
转换成功后,在模型保存目录下有三个文件:
```
inference/det_db/
- ├── det.pdiparams # 检测inference模型的参数文件,需要重命名为params
+ ├── det.pdiparams # 检测inference模型的参数文件
├── det.pdiparams.info # 检测inference模型的参数信息,可忽略
- └── det.pdmodel # 检测inference模型的program文件,需要重命名为model
+ └── det.pdmodel # 检测inference模型的program文件
```
From 7eeef5933c359258b02835ca5e06b406dd6de407 Mon Sep 17 00:00:00 2001
From: tink2123
Date: Wed, 9 Dec 2020 11:56:37 +0000
Subject: [PATCH 11/51] update multi dic and export
---
.../rec_en_number_lite_train.yml | 4 +-
.../multi_language/rec_french_lite_train.yml | 8 +--
.../multi_language/rec_german_lite_train.yml | 4 +-
.../multi_language/rec_japan_lite_train.yml | 4 +-
.../multi_language/rec_korean_lite_train.yml | 4 +-
deploy/cpp_infer/src/ocr_cls.cpp | 2 +-
deploy/cpp_infer/src/ocr_det.cpp | 2 +-
deploy/cpp_infer/src/ocr_rec.cpp | 4 +-
ppocr/utils/dict/en_dict.txt | 63 +++++++++++++++++++
ppocr/utils/dict/french_dict.txt | 3 +-
ppocr/utils/dict/german_dict.txt | 3 +-
ppocr/utils/dict/japan_dict.txt | 3 +-
ppocr/utils/dict/korean_dict.txt | 5 +-
tools/export_model.py | 29 ++++-----
tools/infer/utility.py | 12 ++--
15 files changed, 105 insertions(+), 45 deletions(-)
create mode 100644 ppocr/utils/dict/en_dict.txt
diff --git a/configs/rec/multi_language/rec_en_number_lite_train.yml b/configs/rec/multi_language/rec_en_number_lite_train.yml
index 70d825e61..cee051211 100644
--- a/configs/rec/multi_language/rec_en_number_lite_train.yml
+++ b/configs/rec/multi_language/rec_en_number_lite_train.yml
@@ -1,5 +1,5 @@
Global:
- use_gpu: true
+ use_gpu: True
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
@@ -15,7 +15,7 @@ Global:
use_visualdl: False
infer_img:
# for data or label process
- character_dict_path: ppocr/utils/dict/ic15_dict.txt
+ character_dict_path: ppocr/utils/dict/en_dict.txt
character_type: ch
max_text_length: 25
infer_mode: False
diff --git a/configs/rec/multi_language/rec_french_lite_train.yml b/configs/rec/multi_language/rec_french_lite_train.yml
index 0e8f4eb3a..63378d38a 100644
--- a/configs/rec/multi_language/rec_french_lite_train.yml
+++ b/configs/rec/multi_language/rec_french_lite_train.yml
@@ -1,5 +1,5 @@
Global:
- use_gpu: true
+ use_gpu: True
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
@@ -9,9 +9,9 @@ Global:
eval_batch_step: [0, 2000]
# if pretrained_model is saved in static mode, load_static_weights must set to True
cal_metric_during_train: True
- pretrained_model:
+ pretrained_model:
checkpoints:
- save_inference_dir:
+ save_inference_dir:
use_visualdl: False
infer_img:
# for data or label process
@@ -19,7 +19,7 @@ Global:
character_type: french
max_text_length: 25
infer_mode: False
- use_space_char: True
+ use_space_char: False
Optimizer:
diff --git a/configs/rec/multi_language/rec_german_lite_train.yml b/configs/rec/multi_language/rec_german_lite_train.yml
index 9978a21e1..1651510c5 100644
--- a/configs/rec/multi_language/rec_german_lite_train.yml
+++ b/configs/rec/multi_language/rec_german_lite_train.yml
@@ -1,5 +1,5 @@
Global:
- use_gpu: true
+ use_gpu: True
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
@@ -19,7 +19,7 @@ Global:
character_type: german
max_text_length: 25
infer_mode: False
- use_space_char: True
+ use_space_char: False
Optimizer:
diff --git a/configs/rec/multi_language/rec_japan_lite_train.yml b/configs/rec/multi_language/rec_japan_lite_train.yml
index 938d377e5..bb47584ed 100644
--- a/configs/rec/multi_language/rec_japan_lite_train.yml
+++ b/configs/rec/multi_language/rec_japan_lite_train.yml
@@ -1,5 +1,5 @@
Global:
- use_gpu: true
+ use_gpu: True
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
@@ -19,7 +19,7 @@ Global:
character_type: japan
max_text_length: 25
infer_mode: False
- use_space_char: True
+ use_space_char: False
Optimizer:
diff --git a/configs/rec/multi_language/rec_korean_lite_train.yml b/configs/rec/multi_language/rec_korean_lite_train.yml
index 7b070c449..77f15524f 100644
--- a/configs/rec/multi_language/rec_korean_lite_train.yml
+++ b/configs/rec/multi_language/rec_korean_lite_train.yml
@@ -1,5 +1,5 @@
Global:
- use_gpu: true
+ use_gpu: True
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
@@ -19,7 +19,7 @@ Global:
character_type: korean
max_text_length: 25
infer_mode: False
- use_space_char: True
+ use_space_char: False
Optimizer:
diff --git a/deploy/cpp_infer/src/ocr_cls.cpp b/deploy/cpp_infer/src/ocr_cls.cpp
index 40debaa78..2c85712b4 100644
--- a/deploy/cpp_infer/src/ocr_cls.cpp
+++ b/deploy/cpp_infer/src/ocr_cls.cpp
@@ -81,7 +81,7 @@ cv::Mat Classifier::Run(cv::Mat &img) {
void Classifier::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + ".pdmodel", model_dir + ".pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_det.cpp b/deploy/cpp_infer/src/ocr_det.cpp
index 1e1aaa1bf..ef6f96a29 100644
--- a/deploy/cpp_infer/src/ocr_det.cpp
+++ b/deploy/cpp_infer/src/ocr_det.cpp
@@ -18,7 +18,7 @@ namespace PaddleOCR {
void DBDetector::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + ".pdmodel", model_dir + ".pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp
index 009b6b75f..335d201b2 100644
--- a/deploy/cpp_infer/src/ocr_rec.cpp
+++ b/deploy/cpp_infer/src/ocr_rec.cpp
@@ -103,7 +103,7 @@ void CRNNRecognizer::Run(std::vector>> boxes,
void CRNNRecognizer::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/model", model_dir + "/params");
+ config.SetModel(model_dir + ".pdmodel", model_dir + ".pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
@@ -186,4 +186,4 @@ cv::Mat CRNNRecognizer::GetRotateCropImage(const cv::Mat &srcimage,
}
}
-} // namespace PaddleOCR
\ No newline at end of file
+} // namespace PaddleOCR
diff --git a/ppocr/utils/dict/en_dict.txt b/ppocr/utils/dict/en_dict.txt
new file mode 100644
index 000000000..6fbd99f46
--- /dev/null
+++ b/ppocr/utils/dict/en_dict.txt
@@ -0,0 +1,63 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+
diff --git a/ppocr/utils/dict/french_dict.txt b/ppocr/utils/dict/french_dict.txt
index a74c60ad3..e8f657db3 100644
--- a/ppocr/utils/dict/french_dict.txt
+++ b/ppocr/utils/dict/french_dict.txt
@@ -132,4 +132,5 @@ j
³
Å
$
-#
\ No newline at end of file
+#
+
diff --git a/ppocr/utils/dict/german_dict.txt b/ppocr/utils/dict/german_dict.txt
index ba9d472ad..af0b01ebc 100644
--- a/ppocr/utils/dict/german_dict.txt
+++ b/ppocr/utils/dict/german_dict.txt
@@ -123,4 +123,5 @@ z
â
å
æ
-é
\ No newline at end of file
+é
+
diff --git a/ppocr/utils/dict/japan_dict.txt b/ppocr/utils/dict/japan_dict.txt
index 926979bc6..339d4b89e 100644
--- a/ppocr/utils/dict/japan_dict.txt
+++ b/ppocr/utils/dict/japan_dict.txt
@@ -4395,4 +4395,5 @@ z
y
z
~
-・
\ No newline at end of file
+・
+
diff --git a/ppocr/utils/dict/korean_dict.txt b/ppocr/utils/dict/korean_dict.txt
index 77ae5c301..a13899f14 100644
--- a/ppocr/utils/dict/korean_dict.txt
+++ b/ppocr/utils/dict/korean_dict.txt
@@ -179,7 +179,7 @@ z
с
т
я
-
+
’
“
”
@@ -3684,4 +3684,5 @@ z
立
茶
切
-宅
\ No newline at end of file
+宅
+
diff --git a/tools/export_model.py b/tools/export_model.py
index cf568884f..46a8a8b8d 100755
--- a/tools/export_model.py
+++ b/tools/export_model.py
@@ -39,26 +39,12 @@ def parse_args():
return parser.parse_args()
-class Model(paddle.nn.Layer):
- def __init__(self, model):
- super(Model, self).__init__()
- self.pre_model = model
-
- # Please modify the 'shape' according to actual needs
- @to_static(input_spec=[
- paddle.static.InputSpec(
- shape=[None, 3, 640, 640], dtype='float32')
- ])
- def forward(self, inputs):
- x = self.pre_model(inputs)
- return x
-
-
def main():
FLAGS = parse_args()
config = load_config(FLAGS.config)
logger = get_logger()
# build post process
+
post_process_class = build_post_process(config['PostProcess'],
config['Global'])
@@ -71,9 +57,16 @@ def main():
init_model(config, model, logger)
model.eval()
- model = Model(model)
- save_path = '{}/{}'.format(FLAGS.output_path,
- config['Architecture']['model_type'])
+ save_path = '{}/{}/inference'.format(FLAGS.output_path,
+ config['Architecture']['model_type'])
+ infer_shape = [3, 32, 100] if config['Architecture'][
+ 'model_type'] != "det" else [3, 640, 640]
+ model = to_static(
+ model,
+ input_spec=[
+ paddle.static.InputSpec(
+ shape=[None] + infer_shape, dtype='float32')
+ ])
paddle.jit.save(model, save_path)
logger.info('inference model is saved to {}'.format(save_path))
diff --git a/tools/infer/utility.py b/tools/infer/utility.py
index ee1f954dc..75b725a7a 100755
--- a/tools/infer/utility.py
+++ b/tools/infer/utility.py
@@ -100,8 +100,8 @@ def create_predictor(args, mode, logger):
if model_dir is None:
logger.info("not find {} model file path {}".format(mode, model_dir))
sys.exit(0)
- model_file_path = model_dir + "/model"
- params_file_path = model_dir + "/params"
+ model_file_path = model_dir + ".pdmodel"
+ params_file_path = model_dir + ".pdiparams"
if not os.path.exists(model_file_path):
logger.info("not find model file path {}".format(model_file_path))
sys.exit(0)
@@ -230,10 +230,10 @@ def draw_ocr_box_txt(image,
box[2][1], box[3][0], box[3][1]
],
outline=color)
- box_height = math.sqrt((box[0][0] - box[3][0]) ** 2 + (box[0][1] - box[3][
- 1]) ** 2)
- box_width = math.sqrt((box[0][0] - box[1][0]) ** 2 + (box[0][1] - box[1][
- 1]) ** 2)
+ box_height = math.sqrt((box[0][0] - box[3][0])**2 + (box[0][1] - box[3][
+ 1])**2)
+ box_width = math.sqrt((box[0][0] - box[1][0])**2 + (box[0][1] - box[1][
+ 1])**2)
if box_height > 2 * box_width:
font_size = max(int(box_width * 0.9), 10)
font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
From a31626759cf67f00e4c3ca102afec56ad01d59a2 Mon Sep 17 00:00:00 2001
From: tink2123
Date: Wed, 9 Dec 2020 20:18:10 +0800
Subject: [PATCH 12/51] update reademe for dygraph
---
README_ch.md | 18 +-
README_en.md | 259 ++++++++++++----------------
doc/doc_ch/algorithm_overview.md | 36 ++--
doc/doc_en/algorithm_overview_en.md | 23 +--
4 files changed, 141 insertions(+), 195 deletions(-)
diff --git a/README_ch.md b/README_ch.md
index 7d29a6a37..a97614cfb 100644
--- a/README_ch.md
+++ b/README_ch.md
@@ -4,16 +4,18 @@
PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力使用者训练出更好的模型,并应用落地。
**近期更新**
+- 2020.12.07 [FAQ](./doc/doc_ch/FAQ.md)新增5个高频问题,总数124个,并且计划以后每周一都会更新,欢迎大家持续关注。
+- 2020.11.25 更新半自动标注工具[PPOCRLabel](./PPOCRLabel/README.md),辅助开发者高效完成标注任务,输出格式与PP-OCR训练任务完美衔接。
- 2020.9.22 更新PP-OCR技术文章,https://arxiv.org/abs/2009.09941
-- 2020.9.19 更新超轻量压缩ppocr_mobile_slim系列模型,整体模型3.5M(详见[PP-OCR Pipline](#PP-OCR)),适合在移动端部署使用。[模型下载](#模型下载)
+- 2020.9.19 更新超轻量压缩ppocr_mobile_slim系列模型,整体模型3.5M(详见[PP-OCR Pipeline](#PP-OCR)),适合在移动端部署使用。[模型下载](#模型下载)
- 2020.9.17 更新超轻量ppocr_mobile系列和通用ppocr_server系列中英文ocr模型,媲美商业效果。[模型下载](#模型下载)
- 2020.9.17 更新[英文识别模型](./doc/doc_ch/models_list.md#英文识别模型)和[多语言识别模型](doc/doc_ch/models_list.md#多语言识别模型),已支持`德语、法语、日语、韩语`,更多语种识别模型将持续更新。
-- 2020.8.26 更新OCR相关的84个常见问题及解答,具体参考[FAQ](./doc/doc_ch/FAQ.md)
- 2020.8.24 支持通过whl包安装使用PaddleOCR,具体参考[Paddleocr Package使用说明](./doc/doc_ch/whl.md)
- 2020.8.21 更新8月18日B站直播课回放和PPT,课节2,易学易用的OCR工具大礼包,[获取地址](https://aistudio.baidu.com/aistudio/education/group/info/1519)
- [More](./doc/doc_ch/update.md)
+
## 特性
- PPOCR系列高质量预训练模型,准确的识别效果
@@ -48,13 +50,13 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力
- 代码体验:从[快速安装](./doc/doc_ch/installation.md) 开始
-## PP-OCR 1.1系列模型列表(9月17日更新)
+## PP-OCR 1.1系列模型列表(更新中)
| 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 |
| ------------ | --------------- | ----------------|---- | ---------- | -------- |
-| 中英文超轻量OCR模型(8.1M) | ch_ppocr_mobile_v1.1_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/det/ch_ppocr_mobile_v1.1_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/rec/ch_ppocr_mobile_v1.1_rec_pre.tar) |
-| 中英文通用OCR模型(155.1M) |ch_ppocr_server_v1.1_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/server/det/ch_ppocr_server_v1.1_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/20-09-22/server/rec/ch_ppocr_server_v1.1_rec_pre.tar) |
-| 中英文超轻量压缩OCR模型(3.5M) | ch_ppocr_mobile_slim_v1.1_xx| 移动端 |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile-slim/det/ch_ppocr_mobile_v1.1_det_prune_infer.tar) / [slim模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/lite/ch_ppocr_mobile_v1.1_det_prune_opt.nb) |[推理模型](https://paddleocr.bj.bcebos.com/20-09-22/cls/ch_ppocr_mobile_v1.1_cls_quant_infer.tar) / [slim模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/lite/ch_ppocr_mobile_v1.1_cls_quant_opt.nb)| [推理模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile-slim/rec/ch_ppocr_mobile_v1.1_rec_quant_infer.tar) / [slim模型](https://paddleocr.bj.bcebos.com/20-09-22/mobile/lite/ch_ppocr_mobile_v1.1_rec_quant_opt.nb)|
+| 中英文超轻量OCR模型(8.1M) | ch_ppocr_mobile_v1.1_xx |移动端&服务器端|[推理模型](link) / [预训练模型](link)|[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |
+| 中英文通用OCR模型(155.1M) |ch_ppocr_server_v1.1_xx|服务器端 |[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |
+| 中英文超轻量压缩OCR模型(3.5M) | ch_ppocr_mobile_slim_v1.1_xx| 移动端 |[推理模型](link) / [slim模型](link) |[推理模型](link) / [slim模型](link)| [推理模型](link) / [slim模型](link)|
更多模型下载(包括多语言),可以参考[PP-OCR v1.1 系列模型下载](./doc/doc_ch/models_list.md)
@@ -141,6 +143,7 @@ PP-OCR是一个实用的超轻量OCR系统。主要由DB文本检测、检测框
## 贡献代码
我们非常欢迎你为PaddleOCR贡献代码,也十分感谢你的反馈。
+
- 非常感谢 [Khanh Tran](https://github.com/xxxpsyduck) 和 [Karl Horky](https://github.com/karlhorky) 贡献修改英文文档
- 非常感谢 [zhangxin](https://github.com/ZhangXinNan)([Blog](https://blog.csdn.net/sdlypyzq)) 贡献新的可视化方式、添加.gitgnore、处理手动设置PYTHONPATH环境变量的问题
- 非常感谢 [lyl120117](https://github.com/lyl120117) 贡献打印网络结构的代码
@@ -148,3 +151,6 @@ PP-OCR是一个实用的超轻量OCR系统。主要由DB文本检测、检测框
- 非常感谢 [authorfu](https://github.com/authorfu) 贡献Android和[xiadeye](https://github.com/xiadeye) 贡献IOS的demo代码
- 非常感谢 [BeyondYourself](https://github.com/BeyondYourself) 给PaddleOCR提了很多非常棒的建议,并简化了PaddleOCR的部分代码风格。
- 非常感谢 [tangmq](https://gitee.com/tangmq) 给PaddleOCR增加Docker化部署服务,支持快速发布可调用的Restful API服务。
+- 非常感谢 [lijinhan](https://github.com/lijinhan) 给PaddleOCR增加java SpringBoot 调用OCR Hubserving接口完成对OCR服务化部署的使用。
+- 非常感谢 [Mejans](https://github.com/Mejans) 给PaddleOCR增加新语言奥克西坦语Occitan的字典和语料。
+- 非常感谢 [Evezerest](https://github.com/Evezerest), [ninetailskim](https://github.com/ninetailskim), [edencfc](https://github.com/edencfc), [BeyondYourself](https://github.com/BeyondYourself), [1084667371](https://github.com/1084667371) 贡献了PPOCRLabel的完整代码。
diff --git a/README_en.md b/README_en.md
index 37250da2c..ddde11b21 100644
--- a/README_en.md
+++ b/README_en.md
@@ -1,32 +1,48 @@
-English | [简体中文](README.md)
+English | [简体中文](README_ch.md)
## Introduction
-PaddleOCR aims to create rich, leading, and practical OCR tools that help users train better models and apply them into practice.
+PaddleOCR aims to create multilingual, awesome, leading, and practical OCR tools that help users train better models and apply them into practice.
**Recent updates**
-- 2020.8.24 Support the use of PaddleOCR through whl package installation,pelease refer [PaddleOCR Package](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/whl_en.md)
-- 2020.8.16, Release text detection algorithm [SAST](https://arxiv.org/abs/1908.05498) and text recognition algorithm [SRN](https://arxiv.org/abs/2003.12294)
-- 2020.7.23, Release the playback and PPT of live class on BiliBili station, PaddleOCR Introduction, [address](https://aistudio.baidu.com/aistudio/course/introduce/1519)
-- 2020.7.15, Add mobile App demo , support both iOS and Android ( based on easyedge and Paddle Lite)
-- 2020.7.15, Improve the deployment ability, add the C + + inference , serving deployment. In addition, the benchmarks of the ultra-lightweight OCR model are provided.
-- 2020.7.15, Add several related datasets, data annotation and synthesis tools.
+- 2020.11.25 Update a new data annotation tool, i.e., [PPOCRLabel](./PPOCRLabel/README_en.md), which is helpful to improve the labeling efficiency. Moreover, the labeling results can be used in training of the PP-OCR system directly.
+- 2020.9.22 Update the PP-OCR technical article, https://arxiv.org/abs/2009.09941
+- 2020.9.19 Update the ultra lightweight compressed ppocr_mobile_slim series models, the overall model size is 3.5M (see [PP-OCR Pipeline](#PP-OCR-Pipeline)), suitable for mobile deployment. [Model Downloads](#Supported-Chinese-model-list)
+- 2020.9.17 Update the ultra lightweight ppocr_mobile series and general ppocr_server series Chinese and English ocr models, which are comparable to commercial effects. [Model Downloads](#Supported-Chinese-model-list)
+- 2020.9.17 update [English recognition model](./doc/doc_en/models_list_en.md#english-recognition-model) and [Multilingual recognition model](doc/doc_en/models_list_en.md#english-recognition-model), `English`, `Chinese`, `German`, `French`, `Japanese` and `Korean` have been supported. Models for more languages will continue to be updated.
+- 2020.8.24 Support the use of PaddleOCR through whl package installation,please refer [PaddleOCR Package](./doc/doc_en/whl_en.md)
+- 2020.8.21 Update the replay and PPT of the live lesson at Bilibili on August 18, lesson 2, easy to learn and use OCR tool spree. [Get Address](https://aistudio.baidu.com/aistudio/education/group/info/1519)
- [more](./doc/doc_en/update_en.md)
## Features
-- Ultra-lightweight OCR model, total model size is only 8.6M
- - Single model supports Chinese/English numbers combination recognition, vertical text recognition, long text recognition
- - Detection model DB (4.1M) + recognition model CRNN (4.5M)
-- Various text detection algorithms: EAST, DB
-- Various text recognition algorithms: Rosetta, CRNN, STAR-Net, RARE
-- Support Linux, Windows, macOS and other systems.
+- PPOCR series of high-quality pre-trained models, comparable to commercial effects
+ - Ultra lightweight ppocr_mobile series models: detection (2.6M) + direction classifier (0.9M) + recognition (4.6M) = 8.1M
+ - General ppocr_server series models: detection (47.2M) + direction classifier (0.9M) + recognition (107M) = 155.1M
+ - Ultra lightweight compression ppocr_mobile_slim series models: detection (1.4M) + direction classifier (0.5M) + recognition (1.6M) = 3.5M
+- Support Chinese, English, and digit recognition, vertical text recognition, and long text recognition
+- Support multi-language recognition: Korean, Japanese, German, French
+- Support user-defined training, provides rich predictive inference deployment solutions
+- Support PIP installation, easy to use
+- Support Linux, Windows, MacOS and other systems
## Visualization
-
+
+

+

+
-
+The above pictures are the visualizations of the general ppocr_server model. For more effect pictures, please see [More visualizations](./doc/doc_en/visualization_en.md).
-[More visualization](./doc/doc_en/visualization_en.md)
+
+## Community
+- Scan the QR code below with your Wechat, you can access to official technical exchange group. Look forward to your participation.
+
+
+

+
+
+
+## Quick Experience
You can also quickly experience the ultra-lightweight OCR : [Online Experience](https://www.paddlepaddle.org.cn/hub/scene/ocr)
@@ -42,178 +58,111 @@ Mobile DEMO experience (based on EasyEdge and Paddle-Lite, supports iOS and Andr
-### Supported Models:
+## PP-OCR 1.1 series model list(Update on Sep 17)
-|Model Name|Description |Detection Model link|Recognition Model link| Support for space Recognition Model link|
-|-|-|-|-|-|
-|db_crnn_mobile|ultra-lightweight OCR model|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_det_mv3_db_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_det_mv3_db.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_enhance_infer.tar) / [pre-train model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_enhance.tar)
-|db_crnn_server|General OCR model|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_det_r50_vd_db_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_det_r50_vd_db.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_enhance_infer.tar) / [pre-train model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_enhance.tar)
+| Model introduction | Model name | Recommended scene | Detection model | Direction classifier | Recognition model |
+| ------------------------------------------------------------ | ---------------------------- | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| Chinese and English ultra-lightweight OCR model (8.1M) | ch_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) |
+| Chinese and English general OCR model (155.1M) | ch_ppocr_server_v1.1_xx | Server | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) |
+| Chinese and English ultra-lightweight compressed OCR model (3.5M) | ch_ppocr_mobile_slim_v1.1_xx | Mobile | [inference model](link) / [slim model](link) | [inference model](link) / [slim model](link) | [inference model](link) / [slim model](link) |
+| French ultra-lightweight OCR model (4.6M) | french_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - | [inference model](link) / [pre-trained model](link) |
+| German ultra-lightweight OCR model (4.6M) | german_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link) |
+| Korean ultra-lightweight OCR model (5.9M) | korean_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link)|
+| Japan ultra-lightweight OCR model (6.2M) | japan_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link) |
+For more model downloads (including multiple languages), please refer to [PP-OCR v1.1 series model downloads](./doc/doc_en/models_list_en.md).
+
+For a new language request, please refer to [Guideline for new language_requests](#language_requests).
## Tutorials
- [Installation](./doc/doc_en/installation_en.md)
- [Quick Start](./doc/doc_en/quickstart_en.md)
-- Algorithm introduction
- - [Text Detection Algorithm](#TEXTDETECTIONALGORITHM)
- - [Text Recognition Algorithm](#TEXTRECOGNITIONALGORITHM)
- - [END-TO-END OCR Algorithm](#ENDENDOCRALGORITHM)
-- Model training/evaluation
+- [Code Structure](./doc/doc_en/tree_en.md)
+- Algorithm Introduction
+ - [Text Detection Algorithm](./doc/doc_en/algorithm_overview_en.md)
+ - [Text Recognition Algorithm](./doc/doc_en/algorithm_overview_en.md)
+ - [PP-OCR Pipeline](#PP-OCR-Pipeline)
+- Model Training/Evaluation
- [Text Detection](./doc/doc_en/detection_en.md)
- [Text Recognition](./doc/doc_en/recognition_en.md)
+ - [Direction Classification](./doc/doc_en/angle_class_en.md)
- [Yml Configuration](./doc/doc_en/config_en.md)
- - [Tricks](./doc/doc_en/tricks_en.md)
-- Deployment
+- Inference and Deployment
+ - [Quick Inference Based on PIP](./doc/doc_en/whl_en.md)
- [Python Inference](./doc/doc_en/inference_en.md)
- [C++ Inference](./deploy/cpp_infer/readme_en.md)
- - [Serving](./doc/doc_en/serving_en.md)
+ - [Serving](./deploy/hubserving/readme_en.md)
- [Mobile](./deploy/lite/readme_en.md)
- - Model Quantization and Compression (coming soon)
- - [Benchmark](./doc/doc_en/benchmark_en.md)
+ - [Model Quantization](./deploy/slim/quantization/README_en.md)
+ - [Model Compression](./deploy/slim/prune/README_en.md)
+ - [Benchmark](./doc/doc_en/benchmark_en.md)
+- Data Annotation and Synthesis
+ - [Semi-automatic Annotation Tool](./PPOCRLabel/README_en.md)
+ - [Data Annotation Tools](./doc/doc_en/data_annotation_en.md)
+ - [Data Synthesis Tools](./doc/doc_en/data_synthesis_en.md)
- Datasets
- [General OCR Datasets(Chinese/English)](./doc/doc_en/datasets_en.md)
- [HandWritten_OCR_Datasets(Chinese)](./doc/doc_en/handwritten_datasets_en.md)
- [Various OCR Datasets(multilingual)](./doc/doc_en/vertical_and_multilingual_datasets_en.md)
- - [Data Annotation Tools](./doc/doc_en/data_annotation_en.md)
- - [Data Synthesis Tools](./doc/doc_en/data_synthesis_en.md)
-- [FAQ](#FAQ)
-- Visualization
- - [Ultra-lightweight Chinese/English OCR Visualization](#UCOCRVIS)
- - [General Chinese/English OCR Visualization](#GeOCRVIS)
- - [Chinese/English OCR Visualization (Support Space Recognition )](#SpaceOCRVIS)
+- [Visualization](#Visualization)
+- [New language requests](#language_requests)
+- [FAQ](./doc/doc_en/FAQ_en.md)
- [Community](#Community)
- [References](./doc/doc_en/reference_en.md)
- [License](#LICENSE)
- [Contribution](#CONTRIBUTION)
-
-## Text Detection Algorithm
+
-PaddleOCR open source text detection algorithms list:
-- [x] EAST([paper](https://arxiv.org/abs/1704.03155))
-- [x] DB([paper](https://arxiv.org/abs/1911.08947))
-- [x] SAST([paper](https://arxiv.org/abs/1908.05498))(Baidu Self-Research)
-
-On the ICDAR2015 dataset, the text detection result is as follows:
-
-|Model|Backbone|precision|recall|Hmean|Download link|
-|-|-|-|-|-|-|
-|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)|
-|EAST|MobileNetV3|81.67%|79.83%|80.74%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_east.tar)|
-|DB|ResNet50_vd|83.79%|80.65%|82.19%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)|
-|DB|MobileNetV3|75.92%|73.18%|74.53%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_db.tar)|
-|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)|
-
-On Total-Text dataset, the text detection result is as follows:
-
-|Model|Backbone|precision|recall|Hmean|Download link|
-|-|-|-|-|-|-|
-|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.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).
-
-For use of [LSVT](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/datasets_en.md#1-icdar2019-lsvt) street view dataset with a total of 3w training data,the related configuration and pre-trained models for text detection task are as follows:
-|Model|Backbone|Configuration file|Pre-trained model|
-|-|-|-|-|
-|ultra-lightweight OCR model|MobileNetV3|det_mv3_db.yml|[Download link](https://paddleocr.bj.bcebos.com/ch_models/ch_det_mv3_db.tar)|
-|General OCR model|ResNet50_vd|det_r50_vd_db.yml|[Download link](https://paddleocr.bj.bcebos.com/ch_models/ch_det_r50_vd_db.tar)|
-
-* Note: For the training and evaluation of the above DB model, post-processing parameters box_thresh=0.6 and unclip_ratio=1.5 need to be set. If using different datasets and different models for training, these two parameters can be adjusted for better result.
-
-For the training guide and use of PaddleOCR text detection algorithms, please refer to the document [Text detection model training/evaluation/prediction](./doc/doc_en/detection_en.md)
-
-
-## Text Recognition Algorithm
-
-PaddleOCR open-source text recognition algorithms list:
-- [x] CRNN([paper](https://arxiv.org/abs/1507.05717))
-- [x] Rosetta([paper](https://arxiv.org/abs/1910.05085))
-- [x] STAR-Net([paper](http://www.bmva.org/bmvc/2016/papers/paper043/index.html))
-- [x] RARE([paper](https://arxiv.org/abs/1603.03915v1))
-- [x] SRN([paper](https://arxiv.org/abs/2003.12294))(Baidu Self-Research)
-
-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:
-
-|Model|Backbone|Avg Accuracy|Module combination|Download link|
-|-|-|-|-|-|
-|Rosetta|Resnet34_vd|80.24%|rec_r34_vd_none_none_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_none_ctc.tar)|
-|Rosetta|MobileNetV3|78.16%|rec_mv3_none_none_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_none_none_ctc.tar)|
-|CRNN|Resnet34_vd|82.20%|rec_r34_vd_none_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_bilstm_ctc.tar)|
-|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar)|
-|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)|
-|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_ctc.tar)|
-|RARE|Resnet34_vd|84.90%|rec_r34_vd_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_attn.tar)|
-|RARE|MobileNetV3|83.32%|rec_mv3_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar)|
-|SRN|Resnet50_vd_fpn|88.33%|rec_r50fpn_vd_none_srn|[Download link](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)|
-
-**Note:** SRN model uses data expansion method to expand the two training sets mentioned above, and the expanded data can be downloaded from [Baidu Drive](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA) (download code: y3ry).
-
-The average accuracy of the two-stage training in the original paper is 89.74%, and that of one stage training in paddleocr is 88.33%. Both pre-trained weights can be downloaded [here](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar).
-
-We use [LSVT](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/datasets_en.md#1-icdar2019-lsvt) dataset and cropout 30w training data from original photos by using position groundtruth and make some calibration needed. In addition, based on the LSVT corpus, 500w synthetic data is generated to train the model. The related configuration and pre-trained models are as follows:
-
-|Model|Backbone|Configuration file|Pre-trained model|
-|-|-|-|-|
-|ultra-lightweight OCR model|MobileNetV3|rec_chinese_lite_train.yml|[Download link](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_enhance_infer.tar) & [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_enhance.tar)|
-|General OCR model|Resnet34_vd|rec_chinese_common_train.yml|[Download link](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn.tar)|[inference model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_enhance_infer.tar) & [pre-trained model](https://paddleocr.bj.bcebos.com/ch_models/ch_rec_r34_vd_crnn_enhance.tar)|
-
-Please refer to the document for training guide and use of PaddleOCR text recognition algorithms [Text recognition model training/evaluation/prediction](./doc/doc_en/recognition_en.md)
-
-
-## END-TO-END OCR Algorithm
-- [ ] [End2End-PSL](https://arxiv.org/abs/1909.07808)(Baidu Self-Research, coming soon)
-
-## Visualization
-
-
-### 1.Ultra-lightweight Chinese/English OCR Visualization [more](./doc/doc_en/visualization_en.md)
+## PP-OCR Pipeline
-

+
-
-### 2. General Chinese/English OCR Visualization [more](./doc/doc_en/visualization_en.md)
+PP-OCR is a practical ultra-lightweight OCR system. It is mainly composed of three parts: DB text detection, detection frame correction and CRNN text recognition. The system 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. 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). Besides, The implementation of the FPGM Pruner and PACT quantization is based on [PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim).
+
+
+## Visualization [more](./doc/doc_en/visualization_en.md)
+- Chinese OCR model
-
-### 3.Chinese/English OCR Visualization (Space_support) [more](./doc/doc_en/visualization_en.md)
-
+- English OCR model
-

+
-
-
-## FAQ
-1. Error when using attention-based recognition model: KeyError: 'predict'
-
- The inference of recognition model based on attention loss is still being debugged. For Chinese text recognition, it is recommended to choose the recognition model based on CTC loss first. In practice, it is also found that the recognition model based on attention loss is not as effective as the one based on CTC loss.
-
-2. About inference speed
-
- When there are a lot of texts in the picture, the prediction time will increase. You can use `--rec_batch_num` to set a smaller prediction batch size. The default value is 30, which can be changed to 10 or other values.
-
-3. Service deployment and mobile deployment
-
- It is expected that the service deployment based on Serving and the mobile deployment based on Paddle Lite will be released successively in mid-to-late June. Stay tuned for more updates.
-
-4. Release time of self-developed algorithm
-
- Baidu Self-developed algorithms such as SAST, SRN and end2end PSL will be released in June or July. Please be patient.
-
-[more](./doc/doc_en/FAQ_en.md)
-
-
-## Community
-Scan the QR code below with your wechat and completing the questionnaire, you can access to offical technical exchange group.
-
+- Multilingual OCR model
+
+
+## Guideline for new language requests
+
+If you want to request a new language support, a PR with 2 following files are needed:
+
+1. In folder [ppocr/utils/dict](https://github.com/PaddlePaddle/PaddleOCR/tree/develop/ppocr/utils/dict),
+it is necessary to submit the dict text to this path and name it with `{language}_dict.txt` that contains a list of all characters. Please see the format example from other files in that folder.
+
+2. In folder [ppocr/utils/corpus](https://github.com/PaddlePaddle/PaddleOCR/tree/develop/ppocr/utils/corpus),
+it is necessary to submit the corpus to this path and name it with `{language}_corpus.txt` that contains a list of words in your language.
+Maybe, 50000 words per language is necessary at least.
+Of course, the more, the better.
+
+If your language has unique elements, please tell me in advance within any way, such as useful links, wikipedia and so on.
+
+More details, please refer to [Multilingual OCR Development Plan](https://github.com/PaddlePaddle/PaddleOCR/issues/1048).
+
+
## License
This project is released under Apache 2.0 license
@@ -229,3 +178,7 @@ We welcome all the contributions to PaddleOCR and appreciate for your feedback v
- Thanks [authorfu](https://github.com/authorfu) for contributing Android demo and [xiadeye](https://github.com/xiadeye) contributing iOS demo, respectively.
- Thanks [BeyondYourself](https://github.com/BeyondYourself) for contributing many great suggestions and simplifying part of the code style.
- Thanks [tangmq](https://gitee.com/tangmq) for contributing Dockerized deployment services to PaddleOCR and supporting the rapid release of callable Restful API services.
+- Thanks [lijinhan](https://github.com/lijinhan) for contributing a new way, i.e., java SpringBoot, to achieve the request for the Hubserving deployment.
+- Thanks [Mejans](https://github.com/Mejans) for contributing the Occitan corpus and character set.
+- Thanks [LKKlein](https://github.com/LKKlein) for contributing a new deploying package with the Golang program language.
+- Thanks [Evezerest](https://github.com/Evezerest), [ninetailskim](https://github.com/ninetailskim), [edencfc](https://github.com/edencfc), [BeyondYourself](https://github.com/BeyondYourself) and [1084667371](https://github.com/1084667371) for contributing a new data annotation tool, i.e., PPOCRLabel。
diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md
index c4a3b3255..01570f30c 100644
--- a/doc/doc_ch/algorithm_overview.md
+++ b/doc/doc_ch/algorithm_overview.md
@@ -17,17 +17,17 @@ PaddleOCR开源的文本检测算法列表:
|模型|骨干网络|precision|recall|Hmean|下载链接|
|-|-|-|-|-|-|
-|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[下载链接](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)|
-|EAST|MobileNetV3|81.67%|79.83%|80.74%|[下载链接](https://paddleocr.bj.bcebos.com/det_mv3_east.tar)|
-|DB|ResNet50_vd|83.79%|80.65%|82.19%|[下载链接](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)|
-|DB|MobileNetV3|75.92%|73.18%|74.53%|[下载链接](https://paddleocr.bj.bcebos.com/det_mv3_db.tar)|
-|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[下载链接](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)|
+|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[下载链接](link)|
+|EAST|MobileNetV3|81.67%|79.83%|80.74%|[下载链接](link)|
+|DB|ResNet50_vd|83.79%|80.65%|82.19%|[下载链接](link)|
+|DB|MobileNetV3|75.92%|73.18%|74.53%|[下载链接](link)|
+|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[下载链接](link))|
在Total-text文本检测公开数据集上,算法效果如下:
|模型|骨干网络|precision|recall|Hmean|下载链接|
|-|-|-|-|-|-|
-|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[下载链接](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)|
+|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[下载链接](link)|
**说明:** SAST模型训练额外加入了icdar2013、icdar2017、COCO-Text、ArT等公开数据集进行调优。PaddleOCR用到的经过整理格式的英文公开数据集下载:[百度云地址](https://pan.baidu.com/s/12cPnZcVuV1zn5DOd4mqjVw) (提取码: 2bpi)
@@ -37,28 +37,22 @@ PaddleOCR文本检测算法的训练和使用请参考文档教程中[模型训
### 2.文本识别算法
-PaddleOCR开源的文本识别算法列表:
+PaddleOCR基于动态图开源的文本识别算法列表:
- [x] CRNN([paper](https://arxiv.org/abs/1507.05717))(ppocr推荐)
- [x] Rosetta([paper](https://arxiv.org/abs/1910.05085))
- [x] STAR-Net([paper](http://www.bmva.org/bmvc/2016/papers/paper043/index.html))
-- [x] RARE([paper](https://arxiv.org/abs/1603.03915v1))
-- [x] SRN([paper](https://arxiv.org/abs/2003.12294))
+- [ ] RARE([paper](https://arxiv.org/abs/1603.03915v1))
+- [ ] SRN([paper](https://arxiv.org/abs/2003.12294))
参考[DTRB](https://arxiv.org/abs/1904.01906)文字识别训练和评估流程,使用MJSynth和SynthText两个文字识别数据集训练,在IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE数据集上进行评估,算法效果如下:
|模型|骨干网络|Avg Accuracy|模型存储命名|下载链接|
|-|-|-|-|-|
-|Rosetta|Resnet34_vd|80.24%|rec_r34_vd_none_none_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_none_ctc.tar)|
-|Rosetta|MobileNetV3|78.16%|rec_mv3_none_none_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_none_none_ctc.tar)|
-|CRNN|Resnet34_vd|82.20%|rec_r34_vd_none_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_none_bilstm_ctc.tar)|
-|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar)|
-|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)|
-|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_ctc.tar)|
-|RARE|Resnet34_vd|84.90%|rec_r34_vd_tps_bilstm_attn|[下载链接](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_attn.tar)|
-|RARE|MobileNetV3|83.32%|rec_mv3_tps_bilstm_attn|[下载链接](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar)|
-|SRN|Resnet50_vd_fpn|88.33%|rec_r50fpn_vd_none_srn|[下载链接](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)|
-
-**说明:** SRN模型使用了数据扰动方法对上述提到对两个训练集进行增广,增广后的数据可以在[百度网盘](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA)上下载,提取码: y3ry。
-原始论文使用两阶段训练平均精度为89.74%,PaddleOCR中使用one-stage训练,平均精度为88.33%。两种预训练权重均在[下载链接](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)中。
+|Rosetta|Resnet34_vd|80.24%|rec_r34_vd_none_none_ctc|[下载链接](link)|
+|Rosetta|MobileNetV3|78.16%|rec_mv3_none_none_ctc|[下载链接](link)|
+|CRNN|Resnet34_vd|82.20%|rec_r34_vd_none_bilstm_ctc|[下载链接](link)|
+|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[下载链接](link)|
+|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[下载链接](link)|
+|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[下载链接](link)|
PaddleOCR文本识别算法的训练和使用请参考文档教程中[模型训练/评估中的文本识别部分](./recognition.md)。
diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md
index 2e21fd621..998ef08f5 100644
--- a/doc/doc_en/algorithm_overview_en.md
+++ b/doc/doc_en/algorithm_overview_en.md
@@ -19,17 +19,17 @@ On the ICDAR2015 dataset, the text detection result is as follows:
|Model|Backbone|precision|recall|Hmean|Download link|
|-|-|-|-|-|-|
-|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_east.tar)|
-|EAST|MobileNetV3|81.67%|79.83%|80.74%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_east.tar)|
-|DB|ResNet50_vd|83.79%|80.65%|82.19%|[Download link](https://paddleocr.bj.bcebos.com/det_r50_vd_db.tar)|
-|DB|MobileNetV3|75.92%|73.18%|74.53%|[Download link](https://paddleocr.bj.bcebos.com/det_mv3_db.tar)|
-|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_icdar2015.tar)|
+|EAST|ResNet50_vd|88.18%|85.51%|86.82%|[Download link](link)|
+|EAST|MobileNetV3|81.67%|79.83%|80.74%|[Download link](link)|
+|DB|ResNet50_vd|83.79%|80.65%|82.19%|[Download link](link)|
+|DB|MobileNetV3|75.92%|73.18%|74.53%|[Download link](link)|
+|SAST|ResNet50_vd|92.18%|82.96%|87.33%|[Download link](link)|
On Total-Text dataset, the text detection result is as follows:
|Model|Backbone|precision|recall|Hmean|Download link|
|-|-|-|-|-|-|
-|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[Download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)|
+|SAST|ResNet50_vd|88.74%|79.80%|84.03%|[Download link](link)|
**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).
@@ -42,8 +42,8 @@ PaddleOCR open-source text recognition algorithms list:
- [x] CRNN([paper](https://arxiv.org/abs/1507.05717))
- [x] Rosetta([paper](https://arxiv.org/abs/1910.05085))
- [x] STAR-Net([paper](http://www.bmva.org/bmvc/2016/papers/paper043/index.html))
-- [x] RARE([paper](https://arxiv.org/abs/1603.03915v1))
-- [x] SRN([paper](https://arxiv.org/abs/2003.12294))(Baidu Self-Research)
+- [ ] RARE([paper](https://arxiv.org/abs/1603.03915v1))
+- [ ] SRN([paper](https://arxiv.org/abs/2003.12294))(Baidu Self-Research)
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:
@@ -55,12 +55,5 @@ Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation r
|CRNN|MobileNetV3|79.37%|rec_mv3_none_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar)|
|STAR-Net|Resnet34_vd|83.93%|rec_r34_vd_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_ctc.tar)|
|STAR-Net|MobileNetV3|81.56%|rec_mv3_tps_bilstm_ctc|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_ctc.tar)|
-|RARE|Resnet34_vd|84.90%|rec_r34_vd_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_r34_vd_tps_bilstm_attn.tar)|
-|RARE|MobileNetV3|83.32%|rec_mv3_tps_bilstm_attn|[Download link](https://paddleocr.bj.bcebos.com/rec_mv3_tps_bilstm_attn.tar)|
-|SRN|Resnet50_vd_fpn|88.33%|rec_r50fpn_vd_none_srn|[Download link](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)|
-
-**Note:** SRN model uses data expansion method to expand the two training sets mentioned above, and the expanded data can be downloaded from [Baidu Drive](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA) (download code: y3ry).
-
-The average accuracy of the two-stage training in the original paper is 89.74%, and that of one stage training in paddleocr is 88.33%. Both pre-trained weights can be downloaded [here](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar).
Please refer to the document for training guide and use of PaddleOCR text recognition algorithms [Text recognition model training/evaluation/prediction](./doc/doc_en/recognition_en.md)
From ce518e552cebfd98f1ba7372ea066bbc54aa7e3c Mon Sep 17 00:00:00 2001
From: xmy0916 <863299715@qq.com>
Date: Wed, 9 Dec 2020 20:45:56 +0800
Subject: [PATCH 13/51] fix doc algorithm&recognition en&ch
---
doc/doc_ch/algorithm_overview.md | 5 --
doc/doc_ch/recognition.md | 7 +-
doc/doc_en/algorithm_overview_en.md | 6 --
doc/doc_en/recognition_en.md | 111 +++++++++++++++++++---------
4 files changed, 80 insertions(+), 49 deletions(-)
diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md
index 475db6793..d047959db 100644
--- a/doc/doc_ch/algorithm_overview.md
+++ b/doc/doc_ch/algorithm_overview.md
@@ -54,11 +54,6 @@ PaddleOCR开源的文本识别算法列表:
|CRNN|MobileNetV3||rec_mv3_none_bilstm_ctc|[敬请期待]()|
|STAR-Net|Resnet34_vd||rec_r34_vd_tps_bilstm_ctc|[敬请期待]()|
|STAR-Net|MobileNetV3||rec_mv3_tps_bilstm_ctc|[敬请期待]()|
-|RARE|Resnet34_vd||rec_r34_vd_tps_bilstm_attn|[敬请期待]()|
-|RARE|MobileNetV3||rec_mv3_tps_bilstm_attn|[敬请期待]()|
-|SRN|Resnet50_vd_fpn||rec_r50fpn_vd_none_srn|[敬请期待]()|
-**说明:** SRN模型使用了数据扰动方法对上述提到对两个训练集进行增广,增广后的数据可以在[百度网盘](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA)上下载,提取码: y3ry。
-原始论文使用两阶段训练平均精度为89.74%,PaddleOCR中使用one-stage训练,平均精度为88.33%。两种预训练权重均在[下载链接](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar)中。
PaddleOCR文本识别算法的训练和使用请参考文档教程中[模型训练/评估中的文本识别部分](./recognition.md)。
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 6c5ea02fb..6c5efc067 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -166,9 +166,9 @@ tar -xf rec_mv3_none_bilstm_ctc.tar && rm -rf rec_mv3_none_bilstm_ctc.tar
*如果您安装的是cpu版本,请将配置文件中的 `use_gpu` 字段修改为false*
```
-# GPU训练 支持单卡,多卡训练,通过selected_gpus参数指定卡号
+# GPU训练 支持单卡,多卡训练,通过--gpus参数指定卡号
# 训练icdar15英文数据 并将训练日志保存为 tain_rec.log
-python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3' tools/train.py -c configs/rec/rec_icdar15_train.yml 2>&1 | tee train_rec.log
+python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_icdar15_train.yml
```
- 数据增强
@@ -331,9 +331,8 @@ Eval:
*注意* 评估时必须确保配置文件中 infer_img 字段为空
```
-export CUDA_VISIBLE_DEVICES=0
# GPU 评估, Global.checkpoints 为待测权重
-python3 tools/eval.py -c configs/rec/rec_icdar15_train.yml -o Global.checkpoints={path/to/weights}/best_accuracy
+python3 --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_train.yml -o Global.checkpoints={path/to/weights}/best_accuracy
```
diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md
index 6cdf310f0..60c44865a 100644
--- a/doc/doc_en/algorithm_overview_en.md
+++ b/doc/doc_en/algorithm_overview_en.md
@@ -55,12 +55,6 @@ Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation r
|CRNN|MobileNetV3||rec_mv3_none_bilstm_ctc|[Coming soon]()|
|STAR-Net|Resnet34_vd||rec_r34_vd_tps_bilstm_ctc|[Coming soon]()|
|STAR-Net|MobileNetV3||rec_mv3_tps_bilstm_ctc|[Coming soon]()|
-|RARE|Resnet34_vd||rec_r34_vd_tps_bilstm_attn|[Coming soon]()|
-|RARE|MobileNetV3||rec_mv3_tps_bilstm_attn|[Coming soon]()|
-|SRN|Resnet50_vd_fpn||rec_r50fpn_vd_none_srn|[Coming soon]()|
-**Note:** SRN model uses data expansion method to expand the two training sets mentioned above, and the expanded data can be downloaded from [Baidu Drive](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA) (download code: y3ry).
-
-The average accuracy of the two-stage training in the original paper is 89.74%, and that of one stage training in paddleocr is 88.33%. Both pre-trained weights can be downloaded [here](https://paddleocr.bj.bcebos.com/SRN/rec_r50fpn_vd_none_srn.tar).
Please refer to the document for training guide and use of PaddleOCR text recognition algorithms [Text recognition model training/evaluation/prediction](./doc/doc_en/recognition_en.md)
diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md
index 41b00c52a..daa12820f 100644
--- a/doc/doc_en/recognition_en.md
+++ b/doc/doc_en/recognition_en.md
@@ -158,10 +158,9 @@ tar -xf rec_mv3_none_bilstm_ctc.tar && rm -rf rec_mv3_none_bilstm_ctc.tar
Start training:
```
-# GPU training Support single card and multi-card training, specify the card number through CUDA_VISIBLE_DEVICES
-export CUDA_VISIBLE_DEVICES=0,1,2,3
+# GPU training Support single card and multi-card training, specify the card number through --gpus
# Training icdar15 English data and saving the log as train_rec.log
-python3 tools/train.py -c configs/rec/rec_icdar15_train.yml 2>&1 | tee train_rec.log
+python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_icdar15_train.yml
```
- Data Augmentation
@@ -199,39 +198,69 @@ If the evaluation set is large, the test will be time-consuming. It is recommend
| rec_r34_vd_tps_bilstm_ctc.yml | STARNet | Resnet34_vd | tps | BiLSTM | ctc |
For training Chinese data, it is recommended to use
-训练中文数据,推荐使用[rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml). If you want to try the result of other algorithms on the Chinese data set, please refer to the following instructions to modify the configuration file:
+[rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml). If you want to try the result of other algorithms on the Chinese data set, please refer to the following instructions to modify the configuration file:
co
-Take `rec_mv3_none_none_ctc.yml` as an example:
+Take `rec_chinese_lite_train_v1.1.yml` as an example:
```
Global:
...
- # Modify image_shape to fit long text
- image_shape: [3, 32, 320]
- ...
+ # Add a custom dictionary, such as modify the dictionary, please point the path to the new dictionary
+ character_dict_path: ppocr/utils/ppocr_keys_v1.txt
# Modify character type
character_type: ch
- # Add a custom dictionary, such as modify the dictionary, please point the path to the new dictionary
- character_dict_path: ./ppocr/utils/ppocr_keys_v1.txt
...
- # Modify reader type
- reader_yml: ./configs/rec/rec_chinese_reader.yml
- # Whether to use data augmentation
- distort: true
# Whether to recognize spaces
- use_space_char: true
- ...
+ use_space_char: False
-...
Optimizer:
...
# Add learning rate decay strategy
- decay:
- function: cosine_decay
- # Each epoch contains iter number
- step_each_epoch: 20
- # Total epoch number
- total_epoch: 1000
+ lr:
+ name: Cosine
+ learning_rate: 0.001
+ ...
+
+...
+
+Train:
+ dataset:
+ # Type of dataset,we support LMDBDateSet and SimpleDataSet
+ name: SimpleDataSet
+ # Path of dataset
+ data_dir: ./train_data/
+ # Path of train list
+ label_file_list: ["./train_data/train_list.txt"]
+ transforms:
+ ...
+ - RecResizeImg:
+ # Modify image_shape to fit long text
+ image_shape: [3, 32, 320]
+ ...
+ loader:
+ ...
+ # Train batch_size for Single card
+ batch_size_per_card: 256
+ ...
+
+Eval:
+ dataset:
+ # Type of dataset,we support LMDBDateSet and SimpleDataSet
+ name: SimpleDataSet
+ # Path of dataset
+ data_dir: ./train_data
+ # Path of eval list
+ label_file_list: ["./train_data/val_list.txt"]
+ transforms:
+ ...
+ - RecResizeImg:
+ # Modify image_shape to fit long text
+ image_shape: [3, 32, 320]
+ ...
+ loader:
+ # Eval batch_size for Single card
+ batch_size_per_card: 256
+ ...
```
**Note that the configuration file for prediction/evaluation must be consistent with the training.**
@@ -257,18 +286,33 @@ Take `rec_french_lite_train` as an example:
```
Global:
...
- # Add a custom dictionary, if you modify the dictionary
- # please point the path to the new dictionary
+ # Add a custom dictionary, such as modify the dictionary, please point the path to the new dictionary
character_dict_path: ./ppocr/utils/dict/french_dict.txt
- # Add data augmentation during training
- distort: true
- # Identify spaces
- use_space_char: true
- ...
- # Modify reader type
- reader_yml: ./configs/rec/multi_languages/rec_french_reader.yml
...
+ # Whether to recognize spaces
+ use_space_char: False
+
...
+
+Train:
+ dataset:
+ # Type of dataset,we support LMDBDateSet and SimpleDataSet
+ name: SimpleDataSet
+ # Path of dataset
+ data_dir: ./train_data/
+ # Path of train list
+ label_file_list: ["./train_data/french_train.txt"]
+ ...
+
+Eval:
+ dataset:
+ # Type of dataset,we support LMDBDateSet and SimpleDataSet
+ name: SimpleDataSet
+ # Path of dataset
+ data_dir: ./train_data
+ # Path of eval list
+ label_file_list: ["./train_data/french_val.txt"]
+ ...
```
@@ -277,9 +321,8 @@ Global:
The evaluation data set can be modified via `configs/rec/rec_icdar15_reader.yml` setting of `label_file_path` in EvalReader.
```
-export CUDA_VISIBLE_DEVICES=0
# GPU evaluation, Global.checkpoints is the weight to be tested
-python3 tools/eval.py -c configs/rec/rec_icdar15_reader.yml -o Global.checkpoints={path/to/weights}/best_accuracy
+python3 --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_reader.yml -o Global.checkpoints={path/to/weights}/best_accuracy
```
From c1ca9e3769c6c86d7485e1eca84ad8d1e04658ba Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Wed, 9 Dec 2020 23:32:12 +0800
Subject: [PATCH 14/51] add docker depoly
---
deploy/docker/hubserving/README.md | 54 +++++++++++++++++++++
deploy/docker/hubserving/README_cn.md | 53 ++++++++++++++++++++
deploy/docker/hubserving/cpu/Dockerfile | 32 ++++++++++++
deploy/docker/hubserving/gpu/Dockerfile | 32 ++++++++++++
deploy/docker/hubserving/sample_request.txt | 1 +
5 files changed, 172 insertions(+)
create mode 100644 deploy/docker/hubserving/README.md
create mode 100644 deploy/docker/hubserving/README_cn.md
create mode 100644 deploy/docker/hubserving/cpu/Dockerfile
create mode 100644 deploy/docker/hubserving/gpu/Dockerfile
create mode 100644 deploy/docker/hubserving/sample_request.txt
diff --git a/deploy/docker/hubserving/README.md b/deploy/docker/hubserving/README.md
new file mode 100644
index 000000000..fff882753
--- /dev/null
+++ b/deploy/docker/hubserving/README.md
@@ -0,0 +1,54 @@
+English | [简体中文](README_cn.md)
+
+## Introduction
+Many user hopes package the PaddleOCR service into an docker image, so that it can be quickly released and used in the docker or k8s environment.
+
+This page provide some standardized code to achieve this goal. You can quickly publish the PaddleOCR project into a callable Restful API service through the following steps. (At present, the deployment based on the HubServing mode is implemented first, and author plans to increase the deployment of the PaddleServing mode in the futrue)
+
+## 1. Prerequisites
+
+You need to install the following basic components first:
+a. Docker
+b. Graphics driver and CUDA 10.0+(GPU)
+c. NVIDIA Container Toolkit(GPU,Docker 19.03+ can skip this)
+d. cuDNN 7.6+(GPU)
+
+## 2. Build Image
+a. Goto Dockerfile directory(ps:Need to distinguish between cpu and gpu version, the following takes cpu as an example, gpu version needs to replace the keyword)
+```
+cd deploy/docker/hubserving/cpu
+```
+c. Build image
+```
+docker build -t paddleocr:cpu .
+```
+
+## 3. Start container
+a. CPU version
+```
+sudo docker run -dp 8868:8868 --name paddle_ocr paddleocr:cpu
+```
+b. GPU version (base on NVIDIA Container Toolkit)
+```
+sudo nvidia-docker run -dp 8868:8868 --name paddle_ocr paddleocr:gpu
+```
+c. GPU version (Docker 19.03++)
+```
+sudo docker run -dp 8868:8868 --gpus all --name paddle_ocr paddleocr:gpu
+```
+d. Check service status(If you can see the following statement then it means completed:Successfully installed ocr_system && Running on http://0.0.0.0:8868/)
+```
+docker logs -f paddle_ocr
+```
+
+## 4. Test
+a. Calculate the Base64 encoding of the picture to be recognized (if you just test, you can use a free online tool, like:https://freeonlinetools24.com/base64-image/)
+b. Post a service request(sample request in sample_request.txt)
+
+```
+curl -H "Content-Type:application/json" -X POST --data "{\"images\": [\"Input image Base64 encode(need to delete the code 'data:image/jpg;base64,')\"]}" http://localhost:8868/predict/ocr_system
+```
+c. Get resposne(If the call is successful, the following result will be returned)
+```
+{"msg":"","results":[[{"confidence":0.8403433561325073,"text":"约定","text_region":[[345,377],[641,390],[634,540],[339,528]]},{"confidence":0.8131805658340454,"text":"最终相遇","text_region":[[356,532],[624,530],[624,596],[356,598]]}]],"status":"0"}
+```
diff --git a/deploy/docker/hubserving/README_cn.md b/deploy/docker/hubserving/README_cn.md
new file mode 100644
index 000000000..046903c4c
--- /dev/null
+++ b/deploy/docker/hubserving/README_cn.md
@@ -0,0 +1,53 @@
+[English](README.md) | 简体中文
+
+## Docker化部署服务
+在日常项目应用中,相信大家一般都会希望能通过Docker技术,把PaddleOCR服务打包成一个镜像,以便在Docker或k8s环境里,快速发布上线使用。
+
+本文将提供一些标准化的代码来实现这样的目标。大家通过如下步骤可以把PaddleOCR项目快速发布成可调用的Restful API服务。(目前暂时先实现了基于HubServing模式的部署,后续作者计划增加PaddleServing模式的部署)
+
+## 1.实施前提准备
+
+需要先完成如下基本组件的安装:
+a. Docker环境
+b. 显卡驱动和CUDA 10.0+(GPU)
+c. NVIDIA Container Toolkit(GPU,Docker 19.03以上版本可以跳过此步)
+d. cuDNN 7.6+(GPU)
+
+## 2.制作镜像
+a.切换至Dockerfile目录(注:需要区分cpu或gpu版本,下文以cpu为例,gpu版本需要替换一下关键字即可)
+```
+cd deploy/docker/hubserving/cpu
+```
+c.生成镜像
+```
+docker build -t paddleocr:cpu .
+```
+
+## 3.启动Docker容器
+a. CPU 版本
+```
+sudo docker run -dp 8868:8868 --name paddle_ocr paddleocr:cpu
+```
+b. GPU 版本 (通过NVIDIA Container Toolkit)
+```
+sudo nvidia-docker run -dp 8868:8868 --name paddle_ocr paddleocr:gpu
+```
+c. GPU 版本 (Docker 19.03以上版本,可以直接用如下命令)
+```
+sudo docker run -dp 8868:8869 --gpus all --name paddle_ocr paddleocr:gpu
+```
+d. 检查服务运行情况(出现:Successfully installed ocr_system和Running on http://0.0.0.0:8868 等信息,表示运行成功)
+```
+docker logs -f paddle_ocr
+```
+
+## 4.测试服务
+a. 计算待识别图片的Base64编码(如果只是测试一下效果,可以通过免费的在线工具实现,如:http://tool.chinaz.com/tools/imgtobase/)
+b. 发送服务请求(可参见sample_request.txt中的值)
+```
+curl -H "Content-Type:application/json" -X POST --data "{\"images\": [\"填入图片Base64编码(需要删除'data:image/jpg;base64,')\"]}" http://localhost:8868/predict/ocr_system
+```
+c. 返回结果(如果调用成功,会返回如下结果)
+```
+{"msg":"","results":[[{"confidence":0.8403433561325073,"text":"约定","text_region":[[345,377],[641,390],[634,540],[339,528]]},{"confidence":0.8131805658340454,"text":"最终相遇","text_region":[[356,532],[624,530],[624,596],[356,598]]}]],"status":"0"}
+```
diff --git a/deploy/docker/hubserving/cpu/Dockerfile b/deploy/docker/hubserving/cpu/Dockerfile
new file mode 100644
index 000000000..342f1e819
--- /dev/null
+++ b/deploy/docker/hubserving/cpu/Dockerfile
@@ -0,0 +1,32 @@
+# Version: 1.0.0
+FROM hub.baidubce.com/paddlepaddle/paddle:latest-gpu-cuda10.0-cudnn7-dev
+
+# PaddleOCR base on Python3.7
+RUN pip3.7 install --upgrade pip -i https://mirror.baidu.com/pypi/simple
+
+RUN python3.7 -m pip install paddlepaddle==2.0.0rc0 -i https://mirror.baidu.com/pypi/simple
+
+RUN pip3.7 install paddlehub --upgrade -i https://mirror.baidu.com/pypi/simple
+
+RUN git clone https://github.com/PaddlePaddle/PaddleOCR.git /PaddleOCR
+
+WORKDIR /PaddleOCR
+
+RUN pip3.7 install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
+
+RUN mkdir -p /PaddleOCR/inference/
+# Download orc detect model(light version). if you want to change normal version, you can change ch_ppocr_mobile_v1.1_det_infer to ch_ppocr_server_v1.1_det_infer, also remember change det_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file} -C /PaddleOCR/inference/
+
+# Download direction classifier(light version). If you want to change normal version, you can change ch_ppocr_mobile_v1.1_cls_infer to ch_ppocr_mobile_v1.1_cls_infer, also remember change cls_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file}.tar -C /PaddleOCR/inference/
+
+# Download orc recognition model(light version). If you want to change normal version, you can change ch_ppocr_mobile_v1.1_rec_infer to ch_ppocr_server_v1.1_rec_infer, also remember change rec_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file}.tar -C /PaddleOCR/inference/
+
+EXPOSE 8868
+
+CMD ["/bin/bash","-c","hub install deploy/hubserving/ocr_system/ && hub serving start -m ocr_system"]
\ No newline at end of file
diff --git a/deploy/docker/hubserving/gpu/Dockerfile b/deploy/docker/hubserving/gpu/Dockerfile
new file mode 100644
index 000000000..222d053d9
--- /dev/null
+++ b/deploy/docker/hubserving/gpu/Dockerfile
@@ -0,0 +1,32 @@
+# Version: 1.0.0
+FROM hub.baidubce.com/paddlepaddle/paddle:latest-gpu-cuda10.0-cudnn7-dev
+
+# PaddleOCR base on Python3.7
+RUN pip3.7 install --upgrade pip -i https://mirror.baidu.com/pypi/simple
+
+RUN python3.7 -m pip install paddlepaddle-gpu==2.0.0rc0 -i https://mirror.baidu.com/pypi/simple
+
+RUN pip3.7 install paddlehub --upgrade -i https://mirror.baidu.com/pypi/simple
+
+RUN git clone https://github.com/PaddlePaddle/PaddleOCR.git /PaddleOCR
+
+WORKDIR /PaddleOCR
+
+RUN pip3.7 install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
+
+RUN mkdir -p /PaddleOCR/inference/
+# Download orc detect model(light version). if you want to change normal version, you can change ch_ppocr_mobile_v1.1_det_infer to ch_ppocr_server_v1.1_det_infer, also remember change det_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file}.tar -C /PaddleOCR/inference/
+
+# Download direction classifier(light version). If you want to change normal version, you can change ch_ppocr_mobile_v1.1_cls_infer to ch_ppocr_mobile_v1.1_cls_infer, also remember change cls_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file} -C /PaddleOCR/inference/
+
+# Download orc recognition model(light version). If you want to change normal version, you can change ch_ppocr_mobile_v1.1_rec_infer to ch_ppocr_server_v1.1_rec_infer, also remember change rec_model_dir in deploy/hubserving/ocr_system/params.py)
+ADD {link} /PaddleOCR/inference/
+RUN tar xf /PaddleOCR/inference/{file}.tar -C /PaddleOCR/inference/
+
+EXPOSE 8868
+
+CMD ["/bin/bash","-c","hub install deploy/hubserving/ocr_system/ && hub serving start -m ocr_system"]
\ No newline at end of file
diff --git a/deploy/docker/hubserving/sample_request.txt b/deploy/docker/hubserving/sample_request.txt
new file mode 100644
index 000000000..ec2b25b1f
--- /dev/null
+++ b/deploy/docker/hubserving/sample_request.txt
@@ -0,0 +1 @@
+curl -H "Content-Type:application/json" -X POST --data "{\"images\": [\"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\"]}" http://localhost:8866/predict/ocr_system
\ No newline at end of file
From 2f67f2c839532765e5d76b60fb1d224c45e3cf09 Mon Sep 17 00:00:00 2001
From: littletomatodonkey <2120160898@bit.edu.cn>
Date: Wed, 9 Dec 2020 23:47:06 +0800
Subject: [PATCH 15/51] fix config (#1373)
---
.../rec_chinese_common_train_v2.0.yaml} | 2 +-
.../rec_chinese_lite_train_v2.0.yaml} | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
rename configs/rec/{ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yaml => ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yaml} (97%)
rename configs/rec/{ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yaml => ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml} (96%)
diff --git a/configs/rec/ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yaml b/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yaml
similarity index 97%
rename from configs/rec/ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yaml
rename to configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yaml
index 6d53ce8b0..1db3e1cb8 100644
--- a/configs/rec/ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yaml
+++ b/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yaml
@@ -3,7 +3,7 @@ Global:
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
- save_model_dir: ./output/rec_chinese_common_v1.1
+ save_model_dir: ./output/rec_chinese_common_v2.0
save_epoch_step: 3
# evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [0, 2000]
diff --git a/configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yaml b/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml
similarity index 96%
rename from configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yaml
rename to configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml
index 94a22e5c6..dc9d650f3 100644
--- a/configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yaml
+++ b/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml
@@ -3,7 +3,7 @@ Global:
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
- save_model_dir: ./output/rec_chinese_lite_v1.1
+ save_model_dir: ./output/rec_chinese_lite_v2.0
save_epoch_step: 3
# evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [0, 2000]
@@ -19,7 +19,7 @@ Global:
character_type: ch
max_text_length: 25
infer_mode: False
- use_space_char: False
+ use_space_char: True
Optimizer:
From 4fd696ccdf657457e396cd790156cbf1eeaddf30 Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Wed, 9 Dec 2020 23:55:38 +0800
Subject: [PATCH 16/51] update inference model name
---
deploy/cpp_infer/src/ocr_cls.cpp | 3 ++-
deploy/cpp_infer/src/ocr_det.cpp | 3 ++-
deploy/cpp_infer/src/ocr_rec.cpp | 3 ++-
tools/infer/utility.py | 4 ++--
4 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/deploy/cpp_infer/src/ocr_cls.cpp b/deploy/cpp_infer/src/ocr_cls.cpp
index 679397275..fed2023f9 100644
--- a/deploy/cpp_infer/src/ocr_cls.cpp
+++ b/deploy/cpp_infer/src/ocr_cls.cpp
@@ -81,7 +81,8 @@ cv::Mat Classifier::Run(cv::Mat &img) {
void Classifier::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/cls.pdmodel", model_dir + "/cls.pdiparams");
+ config.SetModel(model_dir + "/inference.pdmodel",
+ model_dir + "/inference.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_det.cpp b/deploy/cpp_infer/src/ocr_det.cpp
index 3ca4cc26b..e253f9cc8 100644
--- a/deploy/cpp_infer/src/ocr_det.cpp
+++ b/deploy/cpp_infer/src/ocr_det.cpp
@@ -18,7 +18,8 @@ namespace PaddleOCR {
void DBDetector::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/det.pdmodel", model_dir + "/det.pdiparams");
+ config.SetModel(model_dir + "/inference.pdmodel",
+ model_dir + "/inference.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp
index 0b6d0532b..d4deb5a17 100644
--- a/deploy/cpp_infer/src/ocr_rec.cpp
+++ b/deploy/cpp_infer/src/ocr_rec.cpp
@@ -103,7 +103,8 @@ void CRNNRecognizer::Run(std::vector>> boxes,
void CRNNRecognizer::LoadModel(const std::string &model_dir) {
AnalysisConfig config;
- config.SetModel(model_dir + "/rec.pdmodel", model_dir + "/rec.pdiparams");
+ config.SetModel(model_dir + "/inference.pdmodel",
+ model_dir + "/inference.pdiparams");
if (this->use_gpu_) {
config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
diff --git a/tools/infer/utility.py b/tools/infer/utility.py
index 35b031e13..4b06b60b9 100755
--- a/tools/infer/utility.py
+++ b/tools/infer/utility.py
@@ -100,8 +100,8 @@ def create_predictor(args, mode, logger):
if model_dir is None:
logger.info("not find {} model file path {}".format(mode, model_dir))
sys.exit(0)
- model_file_path = model_dir + ".pdmodel"
- params_file_path = model_dir + ".pdiparams"
+ model_file_path = model_dir + "/inference.pdmodel"
+ params_file_path = model_dir + "/inference.pdiparams"
if not os.path.exists(model_file_path):
logger.info("not find model file path {}".format(model_file_path))
sys.exit(0)
From 0ff2aef299b319edc2b783246e0b42e45a23b890 Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Wed, 9 Dec 2020 23:59:29 +0800
Subject: [PATCH 17/51] rename inference model save path
---
tools/export_model.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/export_model.py b/tools/export_model.py
index 46a8a8b8d..b6c03efba 100755
--- a/tools/export_model.py
+++ b/tools/export_model.py
@@ -57,8 +57,7 @@ def main():
init_model(config, model, logger)
model.eval()
- save_path = '{}/{}/inference'.format(FLAGS.output_path,
- config['Architecture']['model_type'])
+ save_path = '{}/inference'.format(FLAGS.output_path)
infer_shape = [3, 32, 100] if config['Architecture'][
'model_type'] != "det" else [3, 640, 640]
model = to_static(
From 0a28221d763beeba72ae62171ac0f0c75c52dd90 Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Thu, 10 Dec 2020 00:26:19 +0800
Subject: [PATCH 18/51] Update model conversion instructions
---
doc/doc_ch/inference.md | 36 ++++++++++++++++++------------------
doc/doc_en/inference_en.md | 35 +++++++++++++++++++----------------
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index ae1429d86..bab54bf92 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -45,7 +45,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
```
上述模型是以MobileNetV3为backbone训练的DB算法,将训练好的模型转换成inference模型只需要运行如下命令:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下, 不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
@@ -54,9 +54,9 @@ python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/
转换成功后,在模型保存目录下有三个文件:
```
inference/det_db/
- ├── det.pdiparams # 检测inference模型的参数文件
- ├── det.pdiparams.info # 检测inference模型的参数信息,可忽略
- └── det.pdmodel # 检测inference模型的program文件
+ ├── inference.pdiparams # 检测inference模型的参数文件
+ ├── inference.pdiparams.info # 检测inference模型的参数信息,可忽略
+ └── inference.pdmodel # 检测inference模型的program文件
```
@@ -69,7 +69,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
识别模型转inference模型与检测的方式相同,如下:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o ./inference/rec_crnn/
```
@@ -79,9 +79,9 @@ python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_trai
转换成功后,在目录下有三个文件:
```
/inference/rec_crnn/
- ├── rec.pdiparams # 识别inference模型的参数文件
- ├── rec.pdiparams.info # 识别inference模型的参数信息,可忽略
- └── rec.pdmodel # 识别inference模型的program文件
+ ├── inference.pdiparams # 识别inference模型的参数文件
+ ├── inference.pdiparams.info # 识别inference模型的参数信息,可忽略
+ └── inference.pdmodel # 识别inference模型的program文件
```
@@ -94,7 +94,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
方向分类模型转inference模型与检测的方式相同,如下:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
@@ -103,9 +103,9 @@ python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
转换成功后,在目录下有三个文件:
```
/inference/cls/
- ├── cls.pdiparams # 分类inference模型的参数文件
- ├── cls.pdiparams.info # 分类inference模型的参数信息,可忽略
- └── cls.pdmodel # 分类inference模型的program文件
+ ├── inference.pdiparams # 分类inference模型的参数文件
+ ├── inference.pdiparams.info # 分类inference模型的参数信息,可忽略
+ └── inference.pdmodel # 分类inference模型的program文件
```
@@ -126,7 +126,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di

-通过参数`limit_type`和`det_limit_side_len`来对图片的尺寸进行限制限,`limit_type=max`为限制长边长度<`det_limit_side_len`,`limit_type=min`为限制短边长度>`det_limit_side_len`,
+通过参数`limit_type`和`det_limit_side_len`来对图片的尺寸进行限制限,`limit_type=max`为限制长边长度<`det_limit_side_len`,`limit_type=min`为限制短边长度>`det_limit_side_len`,
图片不满足限制条件时(`limit_type=max`时长边长度>`det_limit_side_len`或`limit_type=min`时短边长度<`det_limit_side_len`),将对图片进行等比例缩放。
该参数默认设置为`limit_type='max',det_max_side_len=960`。 如果输入图片的分辨率比较大,而且想使用更大的分辨率预测,可以执行如下命令:
@@ -145,7 +145,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
@@ -169,7 +169,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs_en/img_10.jpg" --det_
首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
@@ -192,7 +192,7 @@ python3 tools/infer/predict_det.py --det_algorithm="EAST" --image_dir="./doc/img
#### (1). 四边形文本检测模型(ICDAR2015)
首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
@@ -209,7 +209,7 @@ python3 tools/infer/predict_det.py --det_algorithm="SAST" --image_dir="./doc/img
首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o "./inference/det_sast_tt"
@@ -257,7 +257,7 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需将待转换的训练模型地址写入配置文件里的Global.checkpoints字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
+# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
# -o 后面设置转换的模型将保存的地址。
python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
diff --git a/doc/doc_en/inference_en.md b/doc/doc_en/inference_en.md
index e103c6c64..40ac3d8c6 100644
--- a/doc/doc_en/inference_en.md
+++ b/doc/doc_en/inference_en.md
@@ -48,7 +48,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
The above model is a DB algorithm trained with MobileNetV3 as the backbone. To convert the trained model into an inference model, just run the following command:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
@@ -58,9 +58,9 @@ When converting to an inference model, the configuration file used is the same a
After the conversion is successful, there are three files in the model save directory:
```
inference/det_db/
- ├── det.pdiparams # The parameter file of detection inference model
- ├── det.pdiparams.info # The parameter information of detection inference model, which can be ignored
- └── det.pdmodel # The program file of detection inference model
+ ├── inference.pdiparams # The parameter file of detection inference model
+ ├── inference.pdiparams.info # The parameter information of detection inference model, which can be ignored
+ └── inference.pdmodel # The program file of detection inference model
```
@@ -73,7 +73,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
The recognition model is converted to the inference model in the same way as the detection, as follows:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
@@ -84,9 +84,9 @@ If you have a model trained on your own dataset with a different dictionary file
After the conversion is successful, there are three files in the model save directory:
```
inference/det_db/
- ├── rec.pdiparams # The parameter file of recognition inference model
- ├── rec.pdiparams.info # The parameter information of recognition inference model, which can be ignored
- └── rec.pdmodel # The program file of recognition model
+ ├── inference.pdiparams # The parameter file of recognition inference model
+ ├── inference.pdiparams.info # The parameter information of recognition inference model, which can be ignored
+ └── inference.pdmodel # The program file of recognition model
```
@@ -99,7 +99,7 @@ wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
The angle classification model is converted to the inference model in the same way as the detection, as follows:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
@@ -108,9 +108,9 @@ python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
After the conversion is successful, there are two files in the directory:
```
inference/det_db/
- ├── rec.pdiparams # The parameter file of angle class inference model
- ├── rec.pdiparams.info # The parameter information of angle class inference model, which can be ignored
- └── rec.pdmodel # The program file of angle class model
+ ├── inference.pdiparams # The parameter file of angle class inference model
+ ├── inference.pdiparams.info # The parameter information of angle class inference model, which can be ignored
+ └── inference.pdmodel # The program file of angle class model
```
@@ -152,7 +152,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
First, convert the model saved in the DB text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
@@ -176,7 +176,7 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the EAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
@@ -200,7 +200,7 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
@@ -220,6 +220,9 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the Total-Text English dataset as an example ([model download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)), you can use the following command to convert:
```
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
+# -o Set the address where the converted model will be saved.
+
python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o Global.checkpoints="./models/sast_r50_vd_total_text/best_accuracy" Global.save_inference_dir="./inference/det_sast_tt"
```
@@ -265,7 +268,7 @@ Taking STAR-Net as an example, we introduce the recognition model inference base
First, convert the model saved in the STAR-Net text recognition training process into an inference model. Taking the model based on Resnet34_vd backbone network, using MJSynth and SynthText (two English text recognition synthetic datasets) for training, as an example ([model download address](link)). It can be converted as follow:
```
-# -c Set the yml configuration file of the training algorithm, you need to write the path of the training model to be converted into the Global.checkpoints parameter in the configuration file, without adding the file suffixes .pdmodel, .pdopt or .pdparams.
+-c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
# -o Set the address where the converted model will be saved.
python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
From 7e0324a4de449b3129754a433009d64b9626175b Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Thu, 10 Dec 2020 00:28:57 +0800
Subject: [PATCH 19/51] reomve load_static_weights
---
configs/cls/cls_mv3.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/configs/cls/cls_mv3.yml b/configs/cls/cls_mv3.yml
index c2b171590..b165bc483 100644
--- a/configs/cls/cls_mv3.yml
+++ b/configs/cls/cls_mv3.yml
@@ -8,7 +8,6 @@ Global:
# evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [0, 1000]
# if pretrained_model is saved in static mode, load_static_weights must set to True
- load_static_weights: True
cal_metric_during_train: True
pretrained_model:
checkpoints:
From 81a1087ece7f1033b8a5c5ed13681be0d520b987 Mon Sep 17 00:00:00 2001
From: WenmuZhou <572459439@qq.com>
Date: Thu, 10 Dec 2020 00:58:24 +0800
Subject: [PATCH 20/51] Fix spelling errors
---
deploy/docker/hubserving/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/deploy/docker/hubserving/README.md b/deploy/docker/hubserving/README.md
index fff882753..d4db277ff 100644
--- a/deploy/docker/hubserving/README.md
+++ b/deploy/docker/hubserving/README.md
@@ -1,9 +1,9 @@
English | [简体中文](README_cn.md)
## Introduction
-Many user hopes package the PaddleOCR service into an docker image, so that it can be quickly released and used in the docker or k8s environment.
+Many users hope package the PaddleOCR service into a docker image, so that it can be quickly released and used in the docker or k8s environment.
-This page provide some standardized code to achieve this goal. You can quickly publish the PaddleOCR project into a callable Restful API service through the following steps. (At present, the deployment based on the HubServing mode is implemented first, and author plans to increase the deployment of the PaddleServing mode in the futrue)
+This page provides some standardized code to achieve this goal. You can quickly publish the PaddleOCR project into a callable Restful API service through the following steps. (At present, the deployment based on the HubServing mode is implemented first, and author plans to increase the deployment of the PaddleServing mode in the futrue)
## 1. Prerequisites
From 8520dd1e8c222bef242561add2d918ed69d457b5 Mon Sep 17 00:00:00 2001
From: tink2123
Date: Thu, 10 Dec 2020 14:21:23 +0800
Subject: [PATCH 21/51] update readme
---
README_ch.md | 2 +-
README_en.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README_ch.md b/README_ch.md
index a97614cfb..b1f07e293 100644
--- a/README_ch.md
+++ b/README_ch.md
@@ -50,7 +50,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力
- 代码体验:从[快速安装](./doc/doc_ch/installation.md) 开始
-## PP-OCR 1.1系列模型列表(更新中)
+## PP-OCR 2.0系列模型列表(更新中)
| 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 |
| ------------ | --------------- | ----------------|---- | ---------- | -------- |
diff --git a/README_en.md b/README_en.md
index ddde11b21..d74c97aee 100644
--- a/README_en.md
+++ b/README_en.md
@@ -58,7 +58,7 @@ Mobile DEMO experience (based on EasyEdge and Paddle-Lite, supports iOS and Andr
-## PP-OCR 1.1 series model list(Update on Sep 17)
+## PP-OCR 2.0 series model list(Update on Sep 17)
| Model introduction | Model name | Recommended scene | Detection model | Direction classifier | Recognition model |
| ------------------------------------------------------------ | ---------------------------- | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
From 042034b61d3f6e1961db11ecafe60649b9e95b94 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Thu, 10 Dec 2020 17:14:58 +0800
Subject: [PATCH 22/51] The parameters of export are consistent with the static
image
---
tools/export_model.py | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/tools/export_model.py b/tools/export_model.py
index b6c03efba..51c061788 100755
--- a/tools/export_model.py
+++ b/tools/export_model.py
@@ -28,21 +28,15 @@ from ppocr.modeling.architectures import build_model
from ppocr.postprocess import build_post_process
from ppocr.utils.save_load import init_model
from ppocr.utils.logging import get_logger
-from tools.program import load_config
-
-
-def parse_args():
- parser = argparse.ArgumentParser()
- parser.add_argument("-c", "--config", help="configuration file to use")
- parser.add_argument(
- "-o", "--output_path", type=str, default='./output/infer/')
- return parser.parse_args()
+from tools.program import load_config, merge_config,ArgsParser
def main():
- FLAGS = parse_args()
+ FLAGS = ArgsParser().parse_args()
config = load_config(FLAGS.config)
+ merge_config(FLAGS.opt)
logger = get_logger()
+ print(config)
# build post process
post_process_class = build_post_process(config['PostProcess'],
@@ -57,7 +51,7 @@ def main():
init_model(config, model, logger)
model.eval()
- save_path = '{}/inference'.format(FLAGS.output_path)
+ save_path = '{}/inference'.format(config['Global']['save_inference_dir'])
infer_shape = [3, 32, 100] if config['Architecture'][
'model_type'] != "det" else [3, 640, 640]
model = to_static(
From 4561ec9798ca0df69da78e00f58c910851acb0f8 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Thu, 10 Dec 2020 17:15:05 +0800
Subject: [PATCH 23/51] update doc
---
doc/doc_ch/inference.md | 66 ++++++++++++++++++------------------
doc/doc_en/inference_en.md | 68 ++++++++++++++++++--------------------
2 files changed, 66 insertions(+), 68 deletions(-)
diff --git a/doc/doc_ch/inference.md b/doc/doc_ch/inference.md
index bab54bf92..dfd84cccb 100644
--- a/doc/doc_ch/inference.md
+++ b/doc/doc_ch/inference.md
@@ -41,14 +41,17 @@ inference 模型(`paddle.jit.save`保存的模型)
下载超轻量级中文检测模型:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_det_train.tar -C ./ch_lite/
```
上述模型是以MobileNetV3为backbone训练的DB算法,将训练好的模型转换成inference模型只需要运行如下命令:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件
+# -o 配置可选参数
+# Global.pretrained_model 参数设置待转换的训练模型地址,不用添加文件后缀 .pdmodel,.pdopt或.pdparams。
+# Global.load_static_weights 参数需要设置为 False。
+# Global.save_inference_dir参数设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
+python3 tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_det_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_db/
```
转inference模型时,使用的配置文件和训练时使用的配置文件相同。另外,还需要设置配置文件中的`Global.checkpoints`参数,其指向训练中保存的模型参数文件。
转换成功后,在模型保存目录下有三个文件:
@@ -64,14 +67,18 @@ inference/det_db/
下载超轻量中文识别模型:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_rec_train.tar -C ./ch_lite/
```
识别模型转inference模型与检测的方式相同,如下:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o ./inference/rec_crnn/
+# -c 后面设置训练算法的yml配置文件
+# -o 配置可选参数
+# Global.pretrained_model 参数设置待转换的训练模型地址,不用添加文件后缀 .pdmodel,.pdopt或.pdparams。
+# Global.load_static_weights 参数需要设置为 False。
+# Global.save_inference_dir参数设置转换的模型将保存的地址。
+
+python3 tools/export_model.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_rec_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/rec_crnn/
```
**注意:**如果您是在自己的数据集上训练的模型,并且调整了中文字符的字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。
@@ -89,15 +96,18 @@ python3 tools/export_model.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_trai
下载方向分类模型:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_cls_train.tar -C ./ch_lite/
```
方向分类模型转inference模型与检测的方式相同,如下:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
+# -c 后面设置训练算法的yml配置文件
+# -o 配置可选参数
+# Global.pretrained_model 参数设置待转换的训练模型地址,不用添加文件后缀 .pdmodel,.pdopt或.pdparams。
+# Global.load_static_weights 参数需要设置为 False。
+# Global.save_inference_dir参数设置转换的模型将保存的地址。
-python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
+python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_cls_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/cls/
```
转换成功后,在目录下有三个文件:
@@ -145,10 +155,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
首先将DB文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
+python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o Global.checkpoints=./det_r50_vd_db_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_db
```
DB文本检测模型推理,可以执行如下命令:
@@ -169,10 +176,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs_en/img_10.jpg" --det_
首先将EAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
+python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints=./det_r50_vd_east_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_east
```
**EAST文本检测模型推理,需要设置参数`--det_algorithm="EAST"`**,可以执行如下命令:
@@ -192,10 +196,8 @@ python3 tools/infer/predict_det.py --det_algorithm="EAST" --image_dir="./doc/img
#### (1). 四边形文本检测模型(ICDAR2015)
首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在ICDAR2015英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o Global.checkpoints=./det_r50_vd_sast_icdar15_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_sast_ic15
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
```
**SAST文本检测模型推理,需要设置参数`--det_algorithm="SAST"`**,可以执行如下命令:
```
@@ -209,10 +211,8 @@ python3 tools/infer/predict_det.py --det_algorithm="SAST" --image_dir="./doc/img
首先将SAST文本检测训练过程中保存的模型,转换成inference model。以基于Resnet50_vd骨干网络,在Total-Text英文数据集训练的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o Global.checkpoints=./det_r50_vd_sast_totaltext_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_sast_tt
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o "./inference/det_sast_tt"
```
**SAST文本检测模型推理,需要设置参数`--det_algorithm="SAST"`,同时,还需要增加参数`--det_sast_polygon=True`,**可以执行如下命令:
@@ -251,30 +251,30 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
### 2. 基于CTC损失的识别模型推理
-我们以STAR-Net为例,介绍基于CTC损失的识别模型推理。 CRNN和Rosetta使用方式类似,不用设置识别算法参数rec_algorithm。
+我们以 CRNN 为例,介绍基于CTC损失的识别模型推理。 Rosetta 使用方式类似,不用设置识别算法参数rec_algorithm。
-首先将STAR-Net文本识别训练过程中保存的模型,转换成inference model。以基于Resnet34_vd骨干网络,使用MJSynth和SynthText两个英文文本识别合成数据集训练
+首先将 Rosetta 文本识别训练过程中保存的模型,转换成inference model。以基于Resnet34_vd骨干网络,使用MJSynth和SynthText两个英文文本识别合成数据集训练
的模型为例([模型下载地址](link)),可以使用如下命令进行转换:
```
-# -c 后面设置训练算法的yml配置文件,需设置 `Global.load_static_weights=False`, 并将待转换的训练模型地址写入配置文件里的 `Global.pretrained_model` 字段下,不用添加文件后缀.pdmodel,.pdopt或.pdparams。
-# -o 后面设置转换的模型将保存的地址。
+python3 tools/export_model.py -c configs/det/rec_r34_vd_none_bilstm_ctc.yml -o Global.checkpoints=./rec_r34_vd_none_bilstm_ctc_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/rec_crnn
-python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
```
STAR-Net文本识别模型推理,可以执行如下命令:
```
-python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/starnet/" --rec_image_shape="3, 32, 100" --rec_char_type="en"
+python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rec_crnn/" --rec_image_shape="3, 32, 100" --rec_char_type="en"
```
### 3. 基于Attention损失的识别模型推理
+基于Attention损失的识别模型与ctc不同,需要额外设置识别算法参数 --rec_algorithm="RARE"
RARE 文本识别模型推理,可以执行如下命令:
```
-python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rare/" --rec_image_shape="3, 32, 100" --rec_char_type="en"
+python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rare/" --rec_image_shape="3, 32, 100" --rec_char_type="en" --rec_algorithm="RARE"
+
```

diff --git a/doc/doc_en/inference_en.md b/doc/doc_en/inference_en.md
index 40ac3d8c6..ac1b634de 100644
--- a/doc/doc_en/inference_en.md
+++ b/doc/doc_en/inference_en.md
@@ -43,15 +43,18 @@ Next, we first introduce how to convert a trained model into an inference model,
Download the lightweight Chinese detection model:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_det_train.tar -C ./ch_lite/
```
The above model is a DB algorithm trained with MobileNetV3 as the backbone. To convert the trained model into an inference model, just run the following command:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
+# -c Set the training algorithm yml configuration file
+# -o Set optional parameters
+# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
+# Global.load_static_weights needs to be set to False
+# Global.save_inference_dir Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/det/det_mv3_db_v1.1.yml -o ./inference/det_db/
+python3 tools/export_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_det_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_db/
```
When converting to an inference model, the configuration file used is the same as the configuration file used during training. In addition, you also need to set the `Global.checkpoints` parameter in the configuration file.
@@ -68,15 +71,18 @@ inference/det_db/
Download the lightweight Chinese recognition model:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_rec_train.tar -C ./ch_lite/
```
The recognition model is converted to the inference model in the same way as the detection, as follows:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
+# -c Set the training algorithm yml configuration file
+# -o Set optional parameters
+# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
+# Global.load_static_weights needs to be set to False
+# Global.save_inference_dir Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
+python3 tools/export_model.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_rec_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/rec_crnn/
```
If you have a model trained on your own dataset with a different dictionary file, please make sure that you modify the `character_dict_path` in the configuration file to your dictionary file path.
@@ -94,15 +100,18 @@ inference/det_db/
Download the angle classification model:
```
-wget -P ./ch_lite/ {link} && tar xf ./ch_lite/{file} -C ./ch_lite/
+wget -P ./ch_lite/ {link} && tar xf ./ch_lite/ch_ppocr_mobile_v2.0_cls_train.tar -C ./ch_lite/
```
The angle classification model is converted to the inference model in the same way as the detection, as follows:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
+# -c Set the training algorithm yml configuration file
+# -o Set optional parameters
+# Global.checkpoints parameter Set the training model address to be converted without adding the file suffix .pdmodel, .pdopt or .pdparams.
+# Global.load_static_weights needs to be set to False
+# Global.save_inference_dir Set the address where the converted model will be saved.
-python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o ./inference/cls/
+python3 tools/export_model.py -c configs/cls/cls_mv3.yml -o Global.checkpoints=./ch_lite/ch_ppocr_mobile_v2.0_cls_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/cls/
```
After the conversion is successful, there are two files in the directory:
@@ -152,10 +161,7 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/2.jpg" --det_model_di
First, convert the model saved in the DB text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o "./inference/det_db"
+python3 tools/export_model.py -c configs/det/det_r50_vd_db.yml -o Global.checkpoints=./det_r50_vd_db_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_db
```
DB text detection model inference, you can execute the following command:
@@ -176,10 +182,7 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the EAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints="./models/det_r50_vd_east/best_accuracy" Global.save_inference_dir="./inference/det_east"
+python3 tools/export_model.py -c configs/det/det_r50_vd_east.yml -o Global.checkpoints=./det_r50_vd_east_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_east
```
**For EAST text detection model inference, you need to set the parameter ``--det_algorithm="EAST"``**, run the following command:
@@ -200,10 +203,7 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the ICDAR2015 English dataset as an example ([model download link](link)), you can use the following command to convert:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o "./inference/det_sast_ic15"
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_icdar15.yml -o Global.checkpoints=./det_r50_vd_sast_icdar15_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_sast_ic15
```
**For SAST quadrangle text detection model inference, you need to set the parameter `--det_algorithm="SAST"`**, run the following command:
@@ -220,10 +220,7 @@ The visualized text detection results are saved to the `./inference_results` fol
First, convert the model saved in the SAST text detection training process into an inference model. Taking the model based on the Resnet50_vd backbone network and trained on the Total-Text English dataset as an example ([model download link](https://paddleocr.bj.bcebos.com/SAST/sast_r50_vd_total_text.tar)), you can use the following command to convert:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
-
-python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o Global.checkpoints="./models/sast_r50_vd_total_text/best_accuracy" Global.save_inference_dir="./inference/det_sast_tt"
+python3 tools/export_model.py -c configs/det/det_r50_vd_sast_totaltext.yml -o Global.checkpoints=./det_r50_vd_sast_totaltext_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/det_sast_tt
```
**For SAST curved text detection model inference, you need to set the parameter `--det_algorithm="SAST"` and `--det_sast_polygon=True`**, run the following command:
@@ -263,18 +260,15 @@ Predicts of ./doc/imgs_words/ch/word_4.jpg:['实力活力', 0.89552695]
### 2. CTC-BASED TEXT RECOGNITION MODEL INFERENCE
-Taking STAR-Net as an example, we introduce the recognition model inference based on CTC loss. CRNN and Rosetta are used in a similar way, by setting the recognition algorithm parameter `rec_algorithm`.
+Taking CRNN as an example, we introduce the recognition model inference based on CTC loss. Rosetta and Star-Net are used in a similar way, No need to set the recognition algorithm parameter rec_algorithm.
-First, convert the model saved in the STAR-Net text recognition training process into an inference model. Taking the model based on Resnet34_vd backbone network, using MJSynth and SynthText (two English text recognition synthetic datasets) for training, as an example ([model download address](link)). It can be converted as follow:
+First, convert the model saved in the CRNN text recognition training process into an inference model. Taking the model based on Resnet34_vd backbone network, using MJSynth and SynthText (two English text recognition synthetic datasets) for training, as an example ([model download address](link)). It can be converted as follow:
```
--c Set the yml configuration file of the algorithm, you need to set `Global.load_static_weights=False`, and write the path of the training model to be converted under the `Global.pretrained_model` parameter in the configuration file, without adding the file suffix .pdmodel, .pdopt or .pdparams.
-# -o Set the address where the converted model will be saved.
-
-python3 tools/export_model.py -c configs/rec/rec_r34_vd_tps_bilstm_ctc.yml -o "./inference/starnet"
+python3 tools/export_model.py -c configs/det/rec_r34_vd_none_bilstm_ctc.yml -o Global.checkpoints=./rec_r34_vd_none_bilstm_ctc_v2.0.train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=./inference/rec_crnn
```
-For STAR-Net text recognition model inference, execute the following commands:
+For CRNN text recognition model inference, execute the following commands:
```
python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/starnet/" --rec_image_shape="3, 32, 100" --rec_char_type="en"
@@ -284,7 +278,11 @@ python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png
### 3. ATTENTION-BASED TEXT RECOGNITION MODEL INFERENCE

+The recognition model based on Attention loss is different from ctc, and additional recognition algorithm parameters need to be set --rec_algorithm="RARE"
After executing the command, the recognition result of the above image is as follows:
+```bash
+python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rare/" --rec_image_shape="3, 32, 100" --rec_char_type="en" --rec_algorithm="RARE"
+```
Predicts of ./doc/imgs_words_en/word_336.png:['super', 0.9999555]
From 2ed027a91cfc6adbff6887029fd1e74ed0cff185 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Thu, 10 Dec 2020 17:20:10 +0800
Subject: [PATCH 24/51] change selected_gpus to gpus
---
doc/doc_ch/angle_class.md | 4 ++--
doc/doc_en/angle_class_en.md | 4 ++--
train.sh | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/doc/doc_ch/angle_class.md b/doc/doc_ch/angle_class.md
index d6a36b86b..887add31c 100644
--- a/doc/doc_ch/angle_class.md
+++ b/doc/doc_ch/angle_class.md
@@ -62,9 +62,9 @@ PaddleOCR提供了训练脚本、评估脚本和预测脚本。
*如果您安装的是cpu版本,请将配置文件中的 `use_gpu` 字段修改为false*
```
-# GPU训练 支持单卡,多卡训练,通过selected_gpus指定卡号
+# GPU训练 支持单卡,多卡训练,通过gpus指定卡号
# 启动训练,下面的命令已经写入train.sh文件中,只需修改文件里的配置文件路径即可
-python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
+python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
```
- 数据增强
diff --git a/doc/doc_en/angle_class_en.md b/doc/doc_en/angle_class_en.md
index defdff3cc..72a8760f8 100644
--- a/doc/doc_en/angle_class_en.md
+++ b/doc/doc_en/angle_class_en.md
@@ -65,9 +65,9 @@ Start training:
```
# Set PYTHONPATH path
export PYTHONPATH=$PYTHONPATH:.
-# GPU training Support single card and multi-card training, specify the card number through selected_gpus
+# GPU training Support single card and multi-card training, specify the card number through gpus
# Start training, the following command has been written into the train.sh file, just modify the configuration file path in the file
-python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
+python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
```
- Data Augmentation
diff --git a/train.sh b/train.sh
index a0483e4dc..17ded409b 100644
--- a/train.sh
+++ b/train.sh
@@ -1 +1 @@
- python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/rec/rec_mv3_none_bilstm_ctc.yml
\ No newline at end of file
+ python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/rec/rec_mv3_none_bilstm_ctc.yml
\ No newline at end of file
From ef9490ed7594623584071d3cad48484094d7ea80 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Thu, 10 Dec 2020 17:28:30 +0800
Subject: [PATCH 25/51] change gpus to selected_gpus
---
doc/doc_ch/angle_class.md | 4 ++--
doc/doc_en/angle_class_en.md | 4 ++--
train.sh | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/doc/doc_ch/angle_class.md b/doc/doc_ch/angle_class.md
index 887add31c..d6a36b86b 100644
--- a/doc/doc_ch/angle_class.md
+++ b/doc/doc_ch/angle_class.md
@@ -62,9 +62,9 @@ PaddleOCR提供了训练脚本、评估脚本和预测脚本。
*如果您安装的是cpu版本,请将配置文件中的 `use_gpu` 字段修改为false*
```
-# GPU训练 支持单卡,多卡训练,通过gpus指定卡号
+# GPU训练 支持单卡,多卡训练,通过selected_gpus指定卡号
# 启动训练,下面的命令已经写入train.sh文件中,只需修改文件里的配置文件路径即可
-python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
+python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
```
- 数据增强
diff --git a/doc/doc_en/angle_class_en.md b/doc/doc_en/angle_class_en.md
index 72a8760f8..defdff3cc 100644
--- a/doc/doc_en/angle_class_en.md
+++ b/doc/doc_en/angle_class_en.md
@@ -65,9 +65,9 @@ Start training:
```
# Set PYTHONPATH path
export PYTHONPATH=$PYTHONPATH:.
-# GPU training Support single card and multi-card training, specify the card number through gpus
+# GPU training Support single card and multi-card training, specify the card number through selected_gpus
# Start training, the following command has been written into the train.sh file, just modify the configuration file path in the file
-python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
+python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/cls/cls_mv3.yml
```
- Data Augmentation
diff --git a/train.sh b/train.sh
index 17ded409b..a0483e4dc 100644
--- a/train.sh
+++ b/train.sh
@@ -1 +1 @@
- python3 -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/rec/rec_mv3_none_bilstm_ctc.yml
\ No newline at end of file
+ python3 -m paddle.distributed.launch --selected_gpus '0,1,2,3,4,5,6,7' tools/train.py -c configs/rec/rec_mv3_none_bilstm_ctc.yml
\ No newline at end of file
From a2f95be7716be492c173f625efb70456350c08a5 Mon Sep 17 00:00:00 2001
From: xmy0916 <863299715@qq.com>
Date: Thu, 10 Dec 2020 18:43:27 +0800
Subject: [PATCH 26/51] fix doc recognition ch&en
---
doc/doc_ch/recognition.md | 18 +++++++++---------
doc/doc_en/recognition_en.md | 20 ++++++++++----------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 6c5efc067..769374aed 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -142,7 +142,7 @@ word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,
- 添加空格类别
-如果希望支持识别"空格"类别, 请将yml文件中的 `use_space_char` 字段设置为 `true`。
+如果希望支持识别"空格"类别, 请将yml文件中的 `use_space_char` 字段设置为 `True`。
@@ -193,8 +193,8 @@ PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/rec_icdar15_t
| 配置文件 | 算法名称 | backbone | trans | seq | pred |
| :--------: | :-------: | :-------: | :-------: | :-----: | :-----: |
-| [rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml) | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
-| [rec_chinese_common_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yml) | CRNN | ResNet34_vd | None | BiLSTM | ctc |
+| [rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml) | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
+| [rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml) | CRNN | ResNet34_vd | None | BiLSTM | ctc |
| rec_chinese_lite_train.yml | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
| rec_chinese_common_train.yml | CRNN | ResNet34_vd | None | BiLSTM | ctc |
| rec_icdar15_train.yml | CRNN | Mobilenet_v3 large 0.5 | None | BiLSTM | ctc |
@@ -208,9 +208,9 @@ PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/rec_icdar15_t
| rec_r34_vd_tps_bilstm_ctc.yml | STARNet | Resnet34_vd | tps | BiLSTM | ctc |
| rec_r50fpn_vd_none_srn.yml | SRN | Resnet50_fpn_vd | None | rnn | srn |
-训练中文数据,推荐使用[rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml),如您希望尝试其他算法在中文数据集上的效果,请参考下列说明修改配置文件:
+训练中文数据,推荐使用[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml),如您希望尝试其他算法在中文数据集上的效果,请参考下列说明修改配置文件:
-以 `rec_chinese_lite_train_v1.1.yml` 为例:
+以 `rec_chinese_lite_train_v2.0.yml` 为例:
```
Global:
...
@@ -220,7 +220,7 @@ Global:
character_type: ch
...
# 识别空格
- use_space_char: False
+ use_space_char: True
Optimizer:
@@ -300,7 +300,7 @@ Global:
character_dict_path: ./ppocr/utils/dict/french_dict.txt
...
# 识别空格
- use_space_char: False
+ use_space_char: True
...
@@ -362,12 +362,12 @@ infer_img: doc/imgs_words/en/word_1.png
word : joint
```
-预测使用的配置文件必须与训练一致,如您通过 `python3 tools/train.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml` 完成了中文模型的训练,
+预测使用的配置文件必须与训练一致,如您通过 `python3 tools/train.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml` 完成了中文模型的训练,
您可以使用如下命令进行中文模型预测。
```
# 预测中文结果
-python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o Global.checkpoints={path/to/weights}/best_accuracy Global.infer_img=doc/imgs_words/ch/word_1.jpg
+python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.checkpoints={path/to/weights}/best_accuracy Global.infer_img=doc/imgs_words/ch/word_1.jpg
```
预测图片:
diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md
index daa12820f..da5a7c473 100644
--- a/doc/doc_en/recognition_en.md
+++ b/doc/doc_en/recognition_en.md
@@ -135,7 +135,7 @@ If you need to customize dic file, please add character_dict_path field in confi
- Add space category
-If you want to support the recognition of the `space` category, please set the `use_space_char` field in the yml file to `true`.
+If you want to support the recognition of the `space` category, please set the `use_space_char` field in the yml file to `True`.
**Note: use_space_char only takes effect when character_type=ch**
@@ -183,8 +183,8 @@ If the evaluation set is large, the test will be time-consuming. It is recommend
| Configuration file | Algorithm | backbone | trans | seq | pred |
| :--------: | :-------: | :-------: | :-------: | :-----: | :-----: |
-| [rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml) | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
-| [rec_chinese_common_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_common_train_v1.1.yml) | CRNN | ResNet34_vd | None | BiLSTM | ctc |
+| [rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml) | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
+| [rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml) | CRNN | ResNet34_vd | None | BiLSTM | ctc |
| rec_chinese_lite_train.yml | CRNN | Mobilenet_v3 small 0.5 | None | BiLSTM | ctc |
| rec_chinese_common_train.yml | CRNN | ResNet34_vd | None | BiLSTM | ctc |
| rec_icdar15_train.yml | CRNN | Mobilenet_v3 large 0.5 | None | BiLSTM | ctc |
@@ -198,9 +198,9 @@ If the evaluation set is large, the test will be time-consuming. It is recommend
| rec_r34_vd_tps_bilstm_ctc.yml | STARNet | Resnet34_vd | tps | BiLSTM | ctc |
For training Chinese data, it is recommended to use
-[rec_chinese_lite_train_v1.1.yml](../../configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml). If you want to try the result of other algorithms on the Chinese data set, please refer to the following instructions to modify the configuration file:
+[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml). If you want to try the result of other algorithms on the Chinese data set, please refer to the following instructions to modify the configuration file:
co
-Take `rec_chinese_lite_train_v1.1.yml` as an example:
+Take `rec_chinese_lite_train_v2.0.yml` as an example:
```
Global:
...
@@ -210,7 +210,7 @@ Global:
character_type: ch
...
# Whether to recognize spaces
- use_space_char: False
+ use_space_char: True
Optimizer:
@@ -290,7 +290,7 @@ Global:
character_dict_path: ./ppocr/utils/dict/french_dict.txt
...
# Whether to recognize spaces
- use_space_char: False
+ use_space_char: True
...
@@ -337,7 +337,7 @@ The default prediction picture is stored in `infer_img`, and the weight is speci
```
# Predict English results
-python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o Global.checkpoints={path/to/weights}/best_accuracy TestReader.infer_img=doc/imgs_words/en/word_1.jpg
+python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.checkpoints={path/to/weights}/best_accuracy TestReader.infer_img=doc/imgs_words/en/word_1.jpg
```
Input image:
@@ -352,11 +352,11 @@ infer_img: doc/imgs_words/en/word_1.png
word : joint
```
-The configuration file used for prediction must be consistent with the training. For example, you completed the training of the Chinese model with `python3 tools/train.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml`, you can use the following command to predict the Chinese model:
+The configuration file used for prediction must be consistent with the training. For example, you completed the training of the Chinese model with `python3 tools/train.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml`, you can use the following command to predict the Chinese model:
```
# Predict Chinese results
-python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v1.1/rec_chinese_lite_train_v1.1.yml -o Global.checkpoints={path/to/weights}/best_accuracy TestReader.infer_img=doc/imgs_words/ch/word_1.jpg
+python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.checkpoints={path/to/weights}/best_accuracy TestReader.infer_img=doc/imgs_words/ch/word_1.jpg
```
Input image:
From 77376859351d5cebff0bee188e5a33df0b989d33 Mon Sep 17 00:00:00 2001
From: xmy0916 <863299715@qq.com>
Date: Thu, 10 Dec 2020 18:56:21 +0800
Subject: [PATCH 27/51] fix doc recognition ch&en
---
doc/doc_ch/recognition.md | 2 +-
doc/doc_en/recognition_en.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 769374aed..91b1af788 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -332,7 +332,7 @@ Eval:
*注意* 评估时必须确保配置文件中 infer_img 字段为空
```
# GPU 评估, Global.checkpoints 为待测权重
-python3 --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_train.yml -o Global.checkpoints={path/to/weights}/best_accuracy
+python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_train.yml -o Global.checkpoints={path/to/weights}/best_accuracy
```
diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md
index da5a7c473..f9849321d 100644
--- a/doc/doc_en/recognition_en.md
+++ b/doc/doc_en/recognition_en.md
@@ -322,7 +322,7 @@ The evaluation data set can be modified via `configs/rec/rec_icdar15_reader.yml`
```
# GPU evaluation, Global.checkpoints is the weight to be tested
-python3 --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_reader.yml -o Global.checkpoints={path/to/weights}/best_accuracy
+python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_icdar15_reader.yml -o Global.checkpoints={path/to/weights}/best_accuracy
```
From 1de89825f617c81e33d9828a6fdd20253f9f2fad Mon Sep 17 00:00:00 2001
From: gaotingquan-dev
Date: Fri, 11 Dec 2020 03:19:16 +0000
Subject: [PATCH 28/51] Fix the errors about description of dict
---
doc/doc_ch/recognition.md | 6 +++---
doc/doc_en/recognition_en.md | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 91b1af788..4097ec92c 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -122,11 +122,11 @@ word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,
`ppocr/utils/dict/french_dict.txt` 是一个包含118个字符的法文字典
-`ppocr/utils/dict/japan_dict.txt` 是一个包含4399个字符的法文字典
+`ppocr/utils/dict/japan_dict.txt` 是一个包含4399个字符的日文字典
-`ppocr/utils/dict/korean_dict.txt` 是一个包含3636个字符的法文字典
+`ppocr/utils/dict/korean_dict.txt` 是一个包含3636个字符的韩文字典
-`ppocr/utils/dict/german_dict.txt` 是一个包含131个字符的法文字典
+`ppocr/utils/dict/german_dict.txt` 是一个包含131个字符的德文字典
您可以按需使用。
diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md
index f9849321d..7f5e436e1 100644
--- a/doc/doc_en/recognition_en.md
+++ b/doc/doc_en/recognition_en.md
@@ -114,11 +114,11 @@ In `word_dict.txt`, there is a single word in each line, which maps characters a
`ppocr/utils/dict/french_dict.txt` is a French dictionary with 118 characters
-`ppocr/utils/dict/japan_dict.txt` is a French dictionary with 4399 characters
+`ppocr/utils/dict/japan_dict.txt` is a Japanese dictionary with 4399 characters
-`ppocr/utils/dict/korean_dict.txt` is a French dictionary with 3636 characters
+`ppocr/utils/dict/korean_dict.txt` is a Korean dictionary with 3636 characters
-`ppocr/utils/dict/german_dict.txt` is a French dictionary with 131 characters
+`ppocr/utils/dict/german_dict.txt` is a German dictionary with 131 characters
You can use it on demand.
From 49895d097a242f3cb61e01ae7914f5711c09e9cb Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Fri, 11 Dec 2020 13:19:37 +0800
Subject: [PATCH 29/51] fix typo error
---
ppocr/metrics/cls_metric.py | 5 ++---
ppocr/metrics/det_metric.py | 2 +-
ppocr/metrics/rec_metric.py | 2 +-
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/ppocr/metrics/cls_metric.py b/ppocr/metrics/cls_metric.py
index 03cbe9c80..098172002 100644
--- a/ppocr/metrics/cls_metric.py
+++ b/ppocr/metrics/cls_metric.py
@@ -32,9 +32,8 @@ class ClsMetric(object):
def get_metric(self):
"""
- return metircs {
- 'acc': 0,
- 'norm_edit_dis': 0,
+ return metrics {
+ 'acc': 0
}
"""
acc = self.correct_num / self.all_num
diff --git a/ppocr/metrics/det_metric.py b/ppocr/metrics/det_metric.py
index 889a8e152..0f9e94df4 100644
--- a/ppocr/metrics/det_metric.py
+++ b/ppocr/metrics/det_metric.py
@@ -57,7 +57,7 @@ class DetMetric(object):
def get_metric(self):
"""
- return metircs {
+ return metrics {
'precision': 0,
'recall': 0,
'hmean': 0
diff --git a/ppocr/metrics/rec_metric.py b/ppocr/metrics/rec_metric.py
index 98817ad82..bd0f92e0d 100644
--- a/ppocr/metrics/rec_metric.py
+++ b/ppocr/metrics/rec_metric.py
@@ -43,7 +43,7 @@ class RecMetric(object):
def get_metric(self):
"""
- return metircs {
+ return metrics {
'acc': 0,
'norm_edit_dis': 0,
}
From 058c0e53028d89d5d74891b5a99d9e89dde5b040 Mon Sep 17 00:00:00 2001
From: zhoujun
Date: Fri, 11 Dec 2020 13:21:58 +0800
Subject: [PATCH 30/51] fix typo error (#1387)
---
ppocr/metrics/cls_metric.py | 5 ++---
ppocr/metrics/det_metric.py | 2 +-
ppocr/metrics/rec_metric.py | 2 +-
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/ppocr/metrics/cls_metric.py b/ppocr/metrics/cls_metric.py
index 03cbe9c80..098172002 100644
--- a/ppocr/metrics/cls_metric.py
+++ b/ppocr/metrics/cls_metric.py
@@ -32,9 +32,8 @@ class ClsMetric(object):
def get_metric(self):
"""
- return metircs {
- 'acc': 0,
- 'norm_edit_dis': 0,
+ return metrics {
+ 'acc': 0
}
"""
acc = self.correct_num / self.all_num
diff --git a/ppocr/metrics/det_metric.py b/ppocr/metrics/det_metric.py
index 889a8e152..0f9e94df4 100644
--- a/ppocr/metrics/det_metric.py
+++ b/ppocr/metrics/det_metric.py
@@ -57,7 +57,7 @@ class DetMetric(object):
def get_metric(self):
"""
- return metircs {
+ return metrics {
'precision': 0,
'recall': 0,
'hmean': 0
diff --git a/ppocr/metrics/rec_metric.py b/ppocr/metrics/rec_metric.py
index 98817ad82..bd0f92e0d 100644
--- a/ppocr/metrics/rec_metric.py
+++ b/ppocr/metrics/rec_metric.py
@@ -43,7 +43,7 @@ class RecMetric(object):
def get_metric(self):
"""
- return metircs {
+ return metrics {
'acc': 0,
'norm_edit_dis': 0,
}
From 3ea94c94d25b72104fa9ee4a9d36e188eca3b3c8 Mon Sep 17 00:00:00 2001
From: WenmuZhou
Date: Fri, 11 Dec 2020 13:27:27 +0800
Subject: [PATCH 31/51] change save_model_dir
---
configs/det/det_r50_vd_db.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml
index 491983f57..b70ab7505 100644
--- a/configs/det/det_r50_vd_db.yml
+++ b/configs/det/det_r50_vd_db.yml
@@ -3,7 +3,7 @@ Global:
epoch_num: 1200
log_smooth_window: 20
print_batch_step: 10
- save_model_dir: ./output/det_rc/det_r50_vd/
+ save_model_dir: ./output/det_r50_vd/
save_epoch_step: 1200
# evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [5000,4000]
From 61b94e47cbcc7aeeefddde9f41ad695c3230ffd1 Mon Sep 17 00:00:00 2001
From: tink2123
Date: Fri, 11 Dec 2020 17:50:01 +0800
Subject: [PATCH 32/51] polish doc
---
README_ch.md | 7 +--
README_en.md | 12 ++--
configs/rec/rec_icdar15_train.yml | 97 ++++++++++++++++++++++++++++++
doc/doc_ch/recognition.md | 16 +++--
doc/doc_en/recognition_en.md | 9 +--
doc/joinus.PNG | Bin 16090 -> 418144 bytes
ppocr/utils/ic15_dict.txt | 2 +-
7 files changed, 117 insertions(+), 26 deletions(-)
create mode 100644 configs/rec/rec_icdar15_train.yml
diff --git a/README_ch.md b/README_ch.md
index b1f07e293..701d0194e 100644
--- a/README_ch.md
+++ b/README_ch.md
@@ -54,11 +54,10 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力
| 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 |
| ------------ | --------------- | ----------------|---- | ---------- | -------- |
-| 中英文超轻量OCR模型(8.1M) | ch_ppocr_mobile_v1.1_xx |移动端&服务器端|[推理模型](link) / [预训练模型](link)|[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |
-| 中英文通用OCR模型(155.1M) |ch_ppocr_server_v1.1_xx|服务器端 |[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |[推理模型](link) / [预训练模型](link) |
-| 中英文超轻量压缩OCR模型(3.5M) | ch_ppocr_mobile_slim_v1.1_xx| 移动端 |[推理模型](link) / [slim模型](link) |[推理模型](link) / [slim模型](link)| [推理模型](link) / [slim模型](link)|
+| 中英文超轻量OCR模型(8.1M) | 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)|[推理模型](link) / [预训练模型](link) |[推理模型](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) |
+| 中英文通用OCR模型(155.1M) |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) |[推理模型](link) / [预训练模型](link) |[推理模型](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 v1.1 系列模型下载](./doc/doc_ch/models_list.md)
+更多模型下载(包括多语言),可以参考[PP-OCR v2.0 系列模型下载](./doc/doc_ch/models_list.md)
## 文档教程
- [快速安装](./doc/doc_ch/installation.md)
diff --git a/README_en.md b/README_en.md
index d74c97aee..052479506 100644
--- a/README_en.md
+++ b/README_en.md
@@ -62,15 +62,11 @@ Mobile DEMO experience (based on EasyEdge and Paddle-Lite, supports iOS and Andr
| Model introduction | Model name | Recommended scene | Detection model | Direction classifier | Recognition model |
| ------------------------------------------------------------ | ---------------------------- | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
-| Chinese and English ultra-lightweight OCR model (8.1M) | ch_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) |
-| Chinese and English general OCR model (155.1M) | ch_ppocr_server_v1.1_xx | Server | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) | [inference model](link) / [pre-trained model](link) |
-| Chinese and English ultra-lightweight compressed OCR model (3.5M) | ch_ppocr_mobile_slim_v1.1_xx | Mobile | [inference model](link) / [slim model](link) | [inference model](link) / [slim model](link) | [inference model](link) / [slim model](link) |
-| French ultra-lightweight OCR model (4.6M) | french_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - | [inference model](link) / [pre-trained model](link) |
-| German ultra-lightweight OCR model (4.6M) | german_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link) |
-| Korean ultra-lightweight OCR model (5.9M) | korean_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link)|
-| Japan ultra-lightweight OCR model (6.2M) | japan_ppocr_mobile_v1.1_xx | Mobile & server | [inference model](link) / [pre-trained model](link) | - |[inference model](link) / [pre-trained model](link) |
+| Chinese and English ultra-lightweight OCR model (8.1M) | ch_ppocr_mobile_v2.0_xx | Mobile & server |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[inference model](link) / [pre-trained model](link) |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) |
+| Chinese and English general OCR model (155.1M) | ch_ppocr_server_v2.0_xx | Server |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[inference model](link) / [pre-trained model](link) |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) |
-For more model downloads (including multiple languages), please refer to [PP-OCR v1.1 series model downloads](./doc/doc_en/models_list_en.md).
+
+For more model downloads (including multiple languages), please refer to [PP-OCR v2.0 series model downloads](./doc/doc_en/models_list_en.md).
For a new language request, please refer to [Guideline for new language_requests](#language_requests).
diff --git a/configs/rec/rec_icdar15_train.yml b/configs/rec/rec_icdar15_train.yml
new file mode 100644
index 000000000..7efbd5cf0
--- /dev/null
+++ b/configs/rec/rec_icdar15_train.yml
@@ -0,0 +1,97 @@
+Global:
+ use_gpu: true
+ epoch_num: 72
+ log_smooth_window: 20
+ print_batch_step: 10
+ save_model_dir: ./output/rec/ic15/
+ save_epoch_step: 3
+ # evaluation is run every 2000 iterations
+ eval_batch_step: [0, 2000]
+ # if pretrained_model is saved in static mode, load_static_weights must set to True
+ 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/ic15_dict.txt
+ character_type: ch
+ max_text_length: 25
+ infer_mode: False
+ use_space_char: False
+
+Optimizer:
+ name: Adam
+ beta1: 0.9
+ beta2: 0.999
+ lr:
+ learning_rate: 0.0005
+ regularizer:
+ name: 'L2'
+ factor: 0
+
+Architecture:
+ model_type: rec
+ algorithm: CRNN
+ Transform:
+ Backbone:
+ name: ResNet
+ layers: 34
+ Neck:
+ name: SequenceEncoder
+ encoder_type: rnn
+ hidden_size: 256
+ Head:
+ name: CTCHead
+ fc_decay: 0
+
+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"]
+ transforms:
+ - DecodeImage: # load image
+ img_mode: BGR
+ channel_first: False
+ - CTCLabelEncode: # Class handling label
+ - RecResizeImg:
+ image_shape: [3, 32, 100]
+ - KeepKeys:
+ keep_keys: ['image', 'label', 'length'] # dataloader will return list in this order
+ 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/train_list.txt"]
+ transforms:
+ - DecodeImage: # load image
+ img_mode: BGR
+ channel_first: False
+ - CTCLabelEncode: # Class handling label
+ - RecResizeImg:
+ image_shape: [3, 32, 100]
+ - 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
diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md
index 91b1af788..9dda9dedd 100644
--- a/doc/doc_ch/recognition.md
+++ b/doc/doc_ch/recognition.md
@@ -37,8 +37,6 @@ ln -sf /train_data/dataset
若您本地没有数据集,可以在官网下载 [icdar2015](http://rrc.cvc.uab.es/?ch=4&com=downloads) 数据,用于快速验证。也可以参考[DTRB](https://github.com/clovaai/deep-text-recognition-benchmark#download-lmdb-dataset-for-traininig-and-evaluation-from-here),下载 benchmark 所需的lmdb格式数据集。
-如果希望复现SRN的论文指标,需要下载离线[增广数据](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA),提取码: y3ry。增广数据是由MJSynth和SynthText做旋转和扰动得到的。数据下载完成后请解压到 {your_path}/PaddleOCR/train_data/data_lmdb_release/training/ 路径下。
-
* 使用自己数据集
@@ -65,7 +63,7 @@ wget -P ./train_data/ic15_data https://paddleocr.bj.bcebos.com/dataset/rec_gt_t
wget -P ./train_data/ic15_data https://paddleocr.bj.bcebos.com/dataset/rec_gt_test.txt
```
-PaddleOCR 也提供了数据格式转换脚本,可以将官网 label 转换支持的数据格式。 数据转换工具在 `train_data/gen_label.py`, 这里以训练集为例:
+PaddleOCR 也提供了数据格式转换脚本,可以将官网 label 转换支持的数据格式。 数据转换工具在 `ppocr/utils/gen_label.py`, 这里以训练集为例:
```
# 将官网下载的标签文件转换为 rec_gt_label.txt
@@ -116,9 +114,9 @@ n
word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,“and” 将被映射成 [2 5 1]
-`ppocr/utils/ppocr_keys_v1.txt` 是一个包含6623个字符的中文字典,
+`ppocr/utils/ppocr_keys_v1.txt` 是一个包含6623个字符的中文字典
-`ppocr/utils/ic15_dict.txt` 是一个包含36个字符的英文字典,
+`ppocr/utils/ic15_dict.txt` 是一个包含36个字符的英文字典
`ppocr/utils/dict/french_dict.txt` 是一个包含118个字符的法文字典
@@ -128,6 +126,8 @@ word_dict.txt 每行有一个单字,将字符与数字索引映射在一起,
`ppocr/utils/dict/german_dict.txt` 是一个包含131个字符的法文字典
+`ppocr/utils/dict/en_dict.txt` 是一个包含63个字符的英文字典
+
您可以按需使用。
@@ -155,10 +155,10 @@ PaddleOCR提供了训练脚本、评估脚本和预测脚本,本节将以 CRNN
```
cd PaddleOCR/
# 下载MobileNetV3的预训练模型
-wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/rec_mv3_none_bilstm_ctc.tar
+wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mv3_none_bilstm_ctc_v2.0_infer.tar
# 解压模型参数
cd pretrain_models
-tar -xf rec_mv3_none_bilstm_ctc.tar && rm -rf rec_mv3_none_bilstm_ctc.tar
+tar -xf rec_mv3_none_bilstm_ctc_v2.0_infer.tar && rm -rf rec_mv3_none_bilstm_ctc_v2.0_infer.tar
```
开始训练:
@@ -204,9 +204,7 @@ PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/rec_icdar15_t
| rec_mv3_tps_bilstm_attn.yml | RARE | Mobilenet_v3 large 0.5 | tps | BiLSTM | attention |
| rec_r34_vd_none_bilstm_ctc.yml | CRNN | Resnet34_vd | None | BiLSTM | ctc |
| rec_r34_vd_none_none_ctc.yml | Rosetta | Resnet34_vd | None | None | ctc |
-| rec_r34_vd_tps_bilstm_attn.yml | RARE | Resnet34_vd | tps | BiLSTM | attention |
| rec_r34_vd_tps_bilstm_ctc.yml | STARNet | Resnet34_vd | tps | BiLSTM | ctc |
-| rec_r50fpn_vd_none_srn.yml | SRN | Resnet50_fpn_vd | None | rnn | srn |
训练中文数据,推荐使用[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml),如您希望尝试其他算法在中文数据集上的效果,请参考下列说明修改配置文件:
diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md
index f9849321d..14c3da739 100644
--- a/doc/doc_en/recognition_en.md
+++ b/doc/doc_en/recognition_en.md
@@ -114,11 +114,13 @@ In `word_dict.txt`, there is a single word in each line, which maps characters a
`ppocr/utils/dict/french_dict.txt` is a French dictionary with 118 characters
-`ppocr/utils/dict/japan_dict.txt` is a French dictionary with 4399 characters
+`ppocr/utils/dict/japan_dict.txt` is a Japan dictionary with 4399 characters
-`ppocr/utils/dict/korean_dict.txt` is a French dictionary with 3636 characters
+`ppocr/utils/dict/korean_dict.txt` is a Korean dictionary with 3636 characters
-`ppocr/utils/dict/german_dict.txt` is a French dictionary with 131 characters
+`ppocr/utils/dict/german_dict.txt` is a German dictionary with 131 characters
+
+`ppocr/utils/dict/en_dict.txt` is a English dictionary with 63 characters
You can use it on demand.
@@ -194,7 +196,6 @@ If the evaluation set is large, the test will be time-consuming. It is recommend
| rec_mv3_tps_bilstm_attn.yml | RARE | Mobilenet_v3 large 0.5 | tps | BiLSTM | attention |
| rec_r34_vd_none_bilstm_ctc.yml | CRNN | Resnet34_vd | None | BiLSTM | ctc |
| rec_r34_vd_none_none_ctc.yml | Rosetta | Resnet34_vd | None | None | ctc |
-| rec_r34_vd_tps_bilstm_attn.yml | RARE | Resnet34_vd | tps | BiLSTM | attention |
| rec_r34_vd_tps_bilstm_ctc.yml | STARNet | Resnet34_vd | tps | BiLSTM | ctc |
For training Chinese data, it is recommended to use
diff --git a/doc/joinus.PNG b/doc/joinus.PNG
index fa11f286d7d2d56d18d94e9034c3be77c974d42f..a6e947489831d90a841c3bb6f21596d5dac7e1ac 100644
GIT binary patch
literal 418144
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 ABs?$~!b}&~XcOV?_#d&(C9>
zTBOyLzHl<(*rz-NXHa={qs4DHD8I|q!m>IM)k}jo(Md+uxD_2y?ZRfF1aDhB#xVUc
zCkWez)K#86>^p8!__B5&bz~j*VO#5+b@nBiYU{+Y2g9LzlEgab68llL>=__Bb3=k@mC}M(UL=AZhMy%}PI2i==oIw<$9hGj$M6oUw
zwVxJ^hC`dd6y>vT>XfyQmWGkrud*lUy2Z9WLc7F*bto#!P@&=)W^vFD4Hz{pnJ>V9
zJlz=PhkF7_prOf{YGAHG>WR!errLn9R}T)l%k(%QbexHMa?tX-@@hkJZ@W`LmGS0Y
z>!sEt+67eC%=;3wL_!CX3TgD4EHl<@%XZo{bVpU~`gBVEyBcXew$&Z;09@(X2Lk^^
zhuglyQPjg=72G`Qna(jfO-`o6H)aXU*qRQK6BusYVC4fEPifHOS~rbMtJ4>m4kyQe
zZfv$StRN4Nj9STLv_tB$MAw>u`NIyHB5v)gbce^}$aEOnf0Vx2IN$I))eAU$
zj`?MJ7s&L*6$r|_F3om9ChtHjzJnxJsYT#uwE9JhShSJ?`7`l^Q?IwCTG
z;