From 0150e56bddc2cf9c9fe803f3f8eca86a010a2869 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Fri, 6 Aug 2021 05:41:17 +0000 Subject: [PATCH 01/77] add det and rec service --- deploy/pdserving/web_service_det.py | 77 ++++++++++++++++++++++++++ deploy/pdserving/web_service_rec.py | 86 +++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 deploy/pdserving/web_service_det.py create mode 100644 deploy/pdserving/web_service_rec.py diff --git a/deploy/pdserving/web_service_det.py b/deploy/pdserving/web_service_det.py new file mode 100644 index 0000000000..25ac2f37db --- /dev/null +++ b/deploy/pdserving/web_service_det.py @@ -0,0 +1,77 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from paddle_serving_server.web_service import WebService, Op + +import logging +import numpy as np +import cv2 +import base64 +# from paddle_serving_app.reader import OCRReader +from ocr_reader import OCRReader, DetResizeForTest +from paddle_serving_app.reader import Sequential, ResizeByFactor +from paddle_serving_app.reader import Div, Normalize, Transpose +from paddle_serving_app.reader import DBPostProcess, FilterBoxes, GetRotateCropImage, SortedBoxes + +_LOGGER = logging.getLogger() + + +class DetOp(Op): + def init_op(self): + self.det_preprocess = Sequential([ + DetResizeForTest(), Div(255), + Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), Transpose( + (2, 0, 1)) + ]) + self.filter_func = FilterBoxes(10, 10) + self.post_func = DBPostProcess({ + "thresh": 0.3, + "box_thresh": 0.5, + "max_candidates": 1000, + "unclip_ratio": 1.5, + "min_size": 3 + }) + + def preprocess(self, input_dicts, data_id, log_id): + (_, input_dict), = input_dicts.items() + data = base64.b64decode(input_dict["image"].encode('utf8')) + self.raw_im = data + data = np.fromstring(data, np.uint8) + # Note: class variables(self.var) can only be used in process op mode + im = cv2.imdecode(data, cv2.IMREAD_COLOR) + self.ori_h, self.ori_w, _ = im.shape + det_img = self.det_preprocess(im) + _, self.new_h, self.new_w = det_img.shape + return {"x": det_img[np.newaxis, :].copy()}, False, None, "" + + def postprocess(self, input_dicts, fetch_dict, log_id): + det_out = fetch_dict["save_infer_model/scale_0.tmp_1"] + ratio_list = [ + float(self.new_h) / self.ori_h, float(self.new_w) / self.ori_w + ] + dt_boxes_list = self.post_func(det_out, [ratio_list]) + dt_boxes = self.filter_func(dt_boxes_list[0], [self.ori_h, self.ori_w]) + out_dict = {"dt_boxes": str(dt_boxes)} + + return out_dict, None, "" + + +class OcrService(WebService): + def get_pipeline_response(self, read_op): + det_op = DetOp(name="det", input_ops=[read_op]) + return det_op + + +uci_service = OcrService(name="ocr") +uci_service.prepare_pipeline_config("config.yml") +uci_service.run_service() diff --git a/deploy/pdserving/web_service_rec.py b/deploy/pdserving/web_service_rec.py new file mode 100644 index 0000000000..6b3cf707f0 --- /dev/null +++ b/deploy/pdserving/web_service_rec.py @@ -0,0 +1,86 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from paddle_serving_server.web_service import WebService, Op + +import logging +import numpy as np +import cv2 +import base64 +# from paddle_serving_app.reader import OCRReader +from ocr_reader import OCRReader, DetResizeForTest +from paddle_serving_app.reader import Sequential, ResizeByFactor +from paddle_serving_app.reader import Div, Normalize, Transpose + +_LOGGER = logging.getLogger() + + +class RecOp(Op): + def init_op(self): + self.ocr_reader = OCRReader( + char_dict_path="../../ppocr/utils/ppocr_keys_v1.txt") + + def preprocess(self, input_dicts, data_id, log_id): + (_, input_dict), = input_dicts.items() + raw_im = base64.b64decode(input_dict["image"].encode('utf8')) + data = np.fromstring(raw_im, np.uint8) + im = cv2.imdecode(data, cv2.IMREAD_COLOR) + feed_list = [] + max_wh_ratio = 0 + ## Many mini-batchs, the type of feed_data is list. + max_batch_size = 6 # len(dt_boxes) + + # If max_batch_size is 0, skipping predict stage + if max_batch_size == 0: + return {}, True, None, "" + boxes_size = max_batch_size + rem = boxes_size % max_batch_size + + h, w = im.shape[0:2] + wh_ratio = w * 1.0 / h + max_wh_ratio = max(max_wh_ratio, wh_ratio) + _, w, h = self.ocr_reader.resize_norm_img(im, max_wh_ratio).shape + norm_img = self.ocr_reader.resize_norm_img(im, max_batch_size) + norm_img = norm_img[np.newaxis, :] + feed = {"x": norm_img.copy()} + feed_list.append(feed) + return feed_list, False, None, "" + + def postprocess(self, input_dicts, fetch_data, log_id): + res_list = [] + if isinstance(fetch_data, dict): + if len(fetch_data) > 0: + rec_batch_res = self.ocr_reader.postprocess( + fetch_data, with_score=True) + for res in rec_batch_res: + res_list.append(res[0]) + elif isinstance(fetch_data, list): + for one_batch in fetch_data: + one_batch_res = self.ocr_reader.postprocess( + one_batch, with_score=True) + for res in one_batch_res: + res_list.append(res[0]) + + res = {"res": str(res_list)} + return res, None, "" + + +class OcrService(WebService): + def get_pipeline_response(self, read_op): + rec_op = RecOp(name="rec", input_ops=[read_op]) + return rec_op + + +uci_service = OcrService(name="ocr") +uci_service.prepare_pipeline_config("config.yml") +uci_service.run_service() From 8fda0c4fd2d145ffce738383571963fa529e84a1 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Fri, 13 Aug 2021 13:41:25 +0000 Subject: [PATCH 02/77] replace rec dataset --- tests/ocr_det_params.txt | 11 ++++++++++- tests/ocr_rec_params.txt | 2 +- tests/prepare.sh | 10 ++++++++++ tests/test.sh | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 6aff66c6aa..4e59fcd756 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -49,4 +49,13 @@ inference:tools/infer/predict_det.py --save_log_path:null --benchmark:True null:null - +===========================deploy_params=========================== +trans_model:-m paddle_serving_client.convert +--dirname:./inference/ch_ppocr_mobile_v2.0_det_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--serving_server:./deploy/pdserving/ppocr_det_mobile_2.0_serving/ +--serving_client:./deploy/pdserving/ppocr_det_mobile_2.0_client/ +serving_dir:./deploy/pdserving +web_service:web_service_det.py &>log.txt & +pipline:pipeline_http_client.py --image_dir=../../doc/imgs diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index 71d12f90b3..cc55884471 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -9,7 +9,7 @@ Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_infer=128|whole_train_infer=128 Global.pretrained_model:null train_model_name:latest -train_infer_img_dir:./train_data/ic15_data/train +train_infer_img_dir:./train_data/ic15_data/test null:null ## trainer:norm_train|pact_train diff --git a/tests/prepare.sh b/tests/prepare.sh index d27a051cb0..8f5291da69 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -74,3 +74,13 @@ else fi fi +# prepare serving env +python_name=$(func_parser_value "${lines[2]}") +${python_name} -m pip install install paddle-serving-server-gpu==0.6.1.post101 +${python_name} -m pip install paddle_serving_client==0.6.1 +${python_name} -m pip install paddle-serving-app==0.6.1 +wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar +wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar +cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar + + diff --git a/tests/test.sh b/tests/test.sh index 9888e0faab..12dfa9d3d7 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -144,6 +144,22 @@ benchmark_key=$(func_parser_key "${lines[49]}") benchmark_value=$(func_parser_value "${lines[49]}") infer_key1=$(func_parser_key "${lines[50]}") infer_value1=$(func_parser_value "${lines[50]}") +# parser serving +trans_model_py=$(func_parser_value "${lines[52]}") +infer_model_dir_key=$(func_parser_key "${lines[53]}") +infer_model_dir_value=$(func_parser_value "${lines[53]}") +model_filename_key=$(func_parser_key "${lines[54]}") +model_filename_value=$(func_parser_value "${lines[54]}") +params_filename_key=$(func_parser_key "${lines[55]}") +params_filename_value=$(func_parser_value "${lines[55]}") +serving_server_key=$(func_parser_key "${lines[56]}") +serving_server_value=$(func_parser_value "${lines[56]}") +serving_client_key=$(func_parser_key "${lines[57]}") +serving_client_value=$(func_parser_value "${lines[57]}") +serving_dir_value=$(func_parser_value "${lines[58]}") +web_service_py=$(func_parser_value "${lines[59]}") +pipline_py=$(func_parser_value "${lines[60]}") + LOG_PATH="./tests/output" mkdir -p ${LOG_PATH} @@ -250,6 +266,23 @@ if [ ${MODE} = "infer" ]; then is_quant=${infer_quant_flag[Count]} func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${LOG_PATH}" "${infer_img_dir}" ${is_quant} Count=$(($Count + 1)) + #run serving + set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_serving_server=$(func_set_params "${serving_server_key}" "${serving_server_value}") + set_serving_client=$(func_set_params "${serving_client_key}" "${serving_client_value}") + trans_model_cmd="${python} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + cd ${serving_dir_value} + echo $PWD + web_service_cmd="${python} ${web_service_py}" + echo $web_service_cmd + eval $web_service_cmd + pipline_cmd="${python} ${pipline_py}" + echo $pipline_cmd + eval $pipline_cmd + done else @@ -363,3 +396,4 @@ else done # done with: for autocast in ${autocast_list[*]}; do done # done with: for gpu in ${gpu_list[*]}; do fi # end if [ ${MODE} = "infer" ]; then + From 418385b88c6f83a3f2b91aded7f5f4e952e8e0c8 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Tue, 17 Aug 2021 07:20:30 +0000 Subject: [PATCH 03/77] smaller rec_inference dataset --- tests/ocr_rec_params.txt | 2 +- tests/prepare.sh | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index cc55884471..123719f951 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -9,7 +9,7 @@ Global.save_model_dir:./output/ Train.loader.batch_size_per_card:lite_train_infer=128|whole_train_infer=128 Global.pretrained_model:null train_model_name:latest -train_infer_img_dir:./train_data/ic15_data/test +train_infer_img_dir:./inference/rec_inference null:null ## trainer:norm_train|pact_train diff --git a/tests/prepare.sh b/tests/prepare.sh index 8f5291da69..828705c380 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -38,10 +38,11 @@ if [ ${MODE} = "lite_train_infer" ];then rm -rf ./train_data/ic15_data wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015_lite.tar wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar # todo change to bcebos - + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar cd ./train_data/ && tar xf icdar2015_lite.tar && tar xf ic15_data.tar ln -s ./icdar2015_lite ./icdar2015 cd ../ + cd ./inference && tar xf rec_inference.tar && cd ../ elif [ ${MODE} = "whole_train_infer" ];then wget -nc -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV3_large_x0_5_pretrained.pdparams rm -rf ./train_data/icdar2015 @@ -68,9 +69,9 @@ else else rm -rf ./train_data/ic15_data eval_model_name="ch_ppocr_mobile_v2.0_rec_infer" - wget -nc -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ic15_data.tar + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar - cd ./inference && tar xf ${eval_model_name}.tar && tar xf ic15_data.tar && cd ../ + cd ./inference && tar xf ${eval_model_name}.tar && tar xf rec_inference.tar && cd ../ fi fi From ec300c652dfa0e387d70613cfeca8d8fc3f95b40 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Thu, 19 Aug 2021 08:58:35 +0000 Subject: [PATCH 04/77] replace gpu id --- tests/ocr_rec_params.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index 123719f951..2d27a9ee3b 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -1,7 +1,7 @@ ===========================train_params=========================== model_name:ocr_rec python:python3.7 -gpu_list:0|2,3 +gpu_list:0|0,1 Global.use_gpu:True|True Global.auto_cast:null Global.epoch_num:lite_train_infer=2|whole_train_infer=300 @@ -41,7 +41,7 @@ inference:tools/infer/predict_rec.py --use_gpu:True|False --enable_mkldnn:True|False --cpu_threads:1|6 ---rec_batch_num:1 +--rec_batch_num:1|6 --use_tensorrt:True|False --precision:fp32|fp16|int8 --rec_model_dir: From ffa94415c35497a73cda435f67182920edb04c1f Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 24 Aug 2021 03:45:59 +0000 Subject: [PATCH 05/77] add_rec_sar, test=dygraph --- configs/rec/rec_r31_sar.yml | 99 ++++++ ppocr/losses/rec_sar_loss.py | 25 ++ ppocr/modeling/backbones/rec_resnet_31.py | 176 ++++++++++ ppocr/modeling/heads/rec_sar_head.py | 378 ++++++++++++++++++++++ ppocr/utils/dict90.txt | 90 ++++++ 5 files changed, 768 insertions(+) create mode 100644 configs/rec/rec_r31_sar.yml create mode 100644 ppocr/losses/rec_sar_loss.py create mode 100644 ppocr/modeling/backbones/rec_resnet_31.py create mode 100644 ppocr/modeling/heads/rec_sar_head.py create mode 100644 ppocr/utils/dict90.txt diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml new file mode 100644 index 0000000000..3a39806410 --- /dev/null +++ b/configs/rec/rec_r31_sar.yml @@ -0,0 +1,99 @@ +Global: + use_gpu: true + epoch_num: 5 + log_smooth_window: 20 + print_batch_step: 20 + save_model_dir: /paddle/backup/sar_rec/sar_train_v3 + save_epoch_step: 1 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 2000] + cal_metric_during_train: True + pretrained_model: #/paddle/backup/sar_rec/sar_train_v2/best_accuracy + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: demo_text_recog.jpg + # for data or label process + character_dict_path: ppocr/utils/dict90.txt + character_type: ch + max_text_length: 30 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_sar.txt + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.999 + lr: + name: Piecewise + decay_epochs: [3, 4] + values: [0.001, 0.0001, 0.00001] + regularizer: + name: 'L2' + factor: 0 + +Architecture: + model_type: rec + algorithm: SAR + Transform: + Backbone: + name: ResNet31 + Head: + name: SARHead + +Loss: + name: SARLoss + +PostProcess: + name: SARLabelDecode + +Metric: + name: RecMetric + + +Train: + dataset: + name: LMDBDataSet #SimpleDataSet + # delimiter: ' ' + # label_file_list: ['/paddle/data/concat_data/icdar_2013_train20.txt', '/paddle/data/concat_data/icdar_2015_train20.txt', '/paddle/data/concat_data/coco_text_train20.txt', '/paddle/data/concat_data/IIIt5k_train20.txt', '/paddle/data/concat_data/SynthAdd_train.txt', '/paddle/data/concat_data/SynthText_train.txt', '/paddle/data/concat_data/Syn90k_train.txt'] + data_dir: /paddle/data/ocr_data/training/ #/paddle/data/concat_data/ + # ratio_list: 1.0 + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - SARLabelEncode: # Class handling label + - SARRecResizeImg: + image_shape: [3, 48, 48, 160] # h:48 w:[48,160] + width_downsample_ratio: 0.25 + - KeepKeys: + keep_keys: ['image', 'label', 'valid_ratio'] # dataloader will return list in this order + loader: + shuffle: True + batch_size_per_card: 64 # 32 + drop_last: True + num_workers: 8 + use_shared_memory: False + +Eval: + dataset: + name: LMDBDataSet + data_dir: /paddle/data/ocr_data/evaluation/ + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - SARLabelEncode: # Class handling label + - SARRecResizeImg: + image_shape: [3, 48, 48, 160] + width_downsample_ratio: 0.25 + - KeepKeys: + keep_keys: ['image', 'label', 'valid_ratio'] # dataloader will return list in this order + loader: + shuffle: False + drop_last: False + batch_size_per_card: 64 + num_workers: 4 + use_shared_memory: False + \ No newline at end of file diff --git a/ppocr/losses/rec_sar_loss.py b/ppocr/losses/rec_sar_loss.py new file mode 100644 index 0000000000..1afb21fe8a --- /dev/null +++ b/ppocr/losses/rec_sar_loss.py @@ -0,0 +1,25 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import paddle +from paddle import nn + + +class SARLoss(nn.Layer): + def __init__(self, **kwargs): + super(SARLoss, self).__init__() + self.loss_func = paddle.nn.loss.CrossEntropyLoss(reduction="mean", ignore_index=92) + + def forward(self, predicts, batch): + predict = predicts[:, :-1, :] # ignore last index of outputs to be in same seq_len with targets + label = batch[1].astype("int64")[:, 1:] # ignore first index of target in loss calculation + batch_size, num_steps, num_classes = predict.shape[0], predict.shape[ + 1], predict.shape[2] + assert len(label.shape) == len(list(predict.shape)) - 1, \ + "The target's shape and inputs's shape is [N, d] and [N, num_steps]" + + inputs = paddle.reshape(predict, [-1, num_classes]) + targets = paddle.reshape(label, [-1]) + loss = self.loss_func(inputs, targets) + return {'loss': loss} diff --git a/ppocr/modeling/backbones/rec_resnet_31.py b/ppocr/modeling/backbones/rec_resnet_31.py new file mode 100644 index 0000000000..f60729cdcc --- /dev/null +++ b/ppocr/modeling/backbones/rec_resnet_31.py @@ -0,0 +1,176 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np + +__all__ = ["ResNet31"] + + +def conv3x3(in_channel, out_channel, stride=1): + return nn.Conv2D( + in_channel, + out_channel, + kernel_size=3, + stride=stride, + padding=1, + bias_attr=False + ) + + +class BasicBlock(nn.Layer): + expansion = 1 + def __init__(self, in_channels, channels, stride=1, downsample=False): + super().__init__() + self.conv1 = conv3x3(in_channels, channels, stride) + self.bn1 = nn.BatchNorm2D(channels) + self.relu = nn.ReLU() + self.conv2 = conv3x3(channels, channels) + self.bn2 = nn.BatchNorm2D(channels) + self.downsample = downsample + if downsample: + self.downsample = nn.Sequential( + nn.Conv2D(in_channels, channels * self.expansion, 1, stride, bias_attr=False), + nn.BatchNorm2D(channels * self.expansion), + ) + else: + self.downsample = nn.Sequential() + self.stride = stride + + def forward(self, x): + residual = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample: + residual = self.downsample(x) + + out += residual + out = self.relu(out) + + return out + + +class ResNet31(nn.Layer): + ''' + Args: + in_channels (int): Number of channels of input image tensor. + layers (list[int]): List of BasicBlock number for each stage. + channels (list[int]): List of out_channels of Conv2d layer. + out_indices (None | Sequence[int]): Indices of output stages. + last_stage_pool (bool): If True, add `MaxPool2d` layer to last stage. + ''' + def __init__(self, + in_channels=3, + layers=[1, 2, 5, 3], + channels=[64, 128, 256, 256, 512, 512, 512], + out_indices=None, + last_stage_pool=False): + super(ResNet31, self).__init__() + assert isinstance(in_channels, int) + assert isinstance(last_stage_pool, bool) + + self.out_indices = out_indices + self.last_stage_pool = last_stage_pool + + # conv 1 (Conv Conv) + self.conv1_1 = nn.Conv2D(in_channels, channels[0], kernel_size=3, stride=1, padding=1) + self.bn1_1 = nn.BatchNorm2D(channels[0]) + self.relu1_1 = nn.ReLU() + + self.conv1_2 = nn.Conv2D(channels[0], channels[1], kernel_size=3, stride=1, padding=1) + self.bn1_2 = nn.BatchNorm2D(channels[1]) + self.relu1_2 = nn.ReLU() + + # conv 2 (Max-pooling, Residual block, Conv) + self.pool2 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0, ceil_mode=True) + self.block2 = self._make_layer(channels[1], channels[2], layers[0]) + self.conv2 = nn.Conv2D(channels[2], channels[2], kernel_size=3, stride=1, padding=1) + self.bn2 = nn.BatchNorm2D(channels[2]) + self.relu2 = nn.ReLU() + + # conv 3 (Max-pooling, Residual block, Conv) + self.pool3 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0, ceil_mode=True) + self.block3 = self._make_layer(channels[2], channels[3], layers[1]) + self.conv3 = nn.Conv2D(channels[3], channels[3], kernel_size=3, stride=1, padding=1) + self.bn3 = nn.BatchNorm2D(channels[3]) + self.relu3 = nn.ReLU() + + # conv 4 (Max-pooling, Residual block, Conv) + self.pool4 = nn.MaxPool2D(kernel_size=(2, 1), stride=(2, 1), padding=0, ceil_mode=True) + self.block4 = self._make_layer(channels[3], channels[4], layers[2]) + self.conv4 = nn.Conv2D(channels[4], channels[4], kernel_size=3, stride=1, padding=1) + self.bn4 = nn.BatchNorm2D(channels[4]) + self.relu4 = nn.ReLU() + + # conv 5 ((Max-pooling), Residual block, Conv) + self.pool5 = None + if self.last_stage_pool: + self.pool5 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0, ceil_mode=True) + self.block5 = self._make_layer(channels[4], channels[5], layers[3]) + self.conv5 = nn.Conv2D(channels[5], channels[5], kernel_size=3, stride=1, padding=1) + self.bn5 = nn.BatchNorm2D(channels[5]) + self.relu5 = nn.ReLU() + + self.out_channels = channels[-1] + + def _make_layer(self, input_channels, output_channels, blocks): + layers = [] + for _ in range(blocks): + downsample = None + if input_channels != output_channels: + downsample = nn.Sequential( + nn.Conv2D( + input_channels, + output_channels, + kernel_size=1, + stride=1, + bias_attr=False), + nn.BatchNorm2D(output_channels), + ) + + layers.append(BasicBlock(input_channels, output_channels, downsample=downsample)) + input_channels = output_channels + return nn.Sequential(*layers) + + + def forward(self, x): + x = self.conv1_1(x) + x = self.bn1_1(x) + x = self.relu1_1(x) + + x = self.conv1_2(x) + x = self.bn1_2(x) + x = self.relu1_2(x) + + outs = [] + for i in range(4): + layer_index = i + 2 + pool_layer = getattr(self, f'pool{layer_index}') + block_layer = getattr(self, f'block{layer_index}') + conv_layer = getattr(self, f'conv{layer_index}') + bn_layer = getattr(self, f'bn{layer_index}') + relu_layer = getattr(self, f'relu{layer_index}') + + if pool_layer is not None: + x = pool_layer(x) + x = block_layer(x) + x = conv_layer(x) + x = bn_layer(x) + x= relu_layer(x) + + outs.append(x) + + if self.out_indices is not None: + return tuple([outs[i] for i in self.out_indices]) + + return x diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py new file mode 100644 index 0000000000..fb37b8cef2 --- /dev/null +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -0,0 +1,378 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import math +import paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F + + +class SAREncoder(nn.Layer): + """ + Args: + enc_bi_rnn (bool): If True, use bidirectional RNN in encoder. + enc_drop_rnn (float): Dropout probability of RNN layer in encoder. + enc_gru (bool): If True, use GRU, else LSTM in encoder. + d_model (int): Dim of channels from backbone. + d_enc (int): Dim of encoder RNN layer. + mask (bool): If True, mask padding in RNN sequence. + """ + def __init__(self, + enc_bi_rnn=False, + enc_drop_rnn=0.1, + enc_gru=False, + d_model=512, + d_enc=512, + mask=True, + **kwargs): + super().__init__() + assert isinstance(enc_bi_rnn, bool) + assert isinstance(enc_drop_rnn, (int, float)) + assert 0 <= enc_drop_rnn < 1.0 + assert isinstance(enc_gru, bool) + assert isinstance(d_model, int) + assert isinstance(d_enc, int) + assert isinstance(mask, bool) + + self.enc_bi_rnn = enc_bi_rnn + self.enc_drop_rnn = enc_drop_rnn + self.mask = mask + + # LSTM Encoder + if enc_bi_rnn: + direction = 'bidirectional' + else: + direction = 'forward' + kwargs = dict( + input_size=d_model, + hidden_size=d_enc, + num_layers=2, + time_major=False, + dropout=enc_drop_rnn, + direction=direction + ) + if enc_gru: + self.rnn_encoder = nn.GRU(**kwargs) + else: + self.rnn_encoder = nn.LSTM(**kwargs) + + # global feature transformation + encoder_rnn_out_size = d_enc * (int(enc_bi_rnn) + 1) + self.linear = nn.Linear(encoder_rnn_out_size, encoder_rnn_out_size) + + def forward(self, feat, img_metas=None): + if img_metas is not None: + assert len(img_metas[0]) == feat.shape[0] + + valid_ratios = None + if img_metas is not None and self.mask: + valid_ratios = img_metas[-1] + + h_feat = feat.shape[2] # bsz c h w + feat_v = F.max_pool2d( + feat, kernel_size=(h_feat, 1), stride=1, padding=0 + ) + feat_v = feat_v.squeeze(2) # bsz * C * W + feat_v = paddle.transpose(feat_v, perm=[0, 2, 1]) # bsz * W * C + holistic_feat = self.rnn_encoder(feat_v)[0] # bsz * T * C + + if valid_ratios is not None: + valid_hf = [] + T = holistic_feat.shape[1] + for i, valid_ratio in enumerate(valid_ratios): + valid_step = min(T, math.ceil(T * valid_ratio)) - 1 + valid_hf.append(holistic_feat[i, valid_step, :]) + valid_hf = paddle.stack(valid_hf, axis=0) + else: + valid_hf = holistic_feat[:, -1, :] # bsz * C + holistic_feat = self.linear(valid_hf) # bsz * C + + return holistic_feat + + +class BaseDecoder(nn.Layer): + def __init__(self, **kwargs): + super().__init__() + + def forward_train(self, feat, out_enc, targets, img_metas): + raise NotImplementedError + + def forward_test(self, feat, out_enc, img_metas): + raise NotImplementedError + + def forward(self, + feat, + out_enc, + label=None, + img_metas=None, + train_mode=True): + self.train_mode = train_mode + + if train_mode: + return self.forward_train(feat, out_enc, label, img_metas) + return self.forward_test(feat, out_enc, img_metas) + + +class ParallelSARDecoder(BaseDecoder): + """ + Args: + num_classes (int): Output class number. + channels (list[int]): Network layer channels. + enc_bi_rnn (bool): If True, use bidirectional RNN in encoder. + dec_bi_rnn (bool): If True, use bidirectional RNN in decoder. + dec_drop_rnn (float): Dropout of RNN layer in decoder. + dec_gru (bool): If True, use GRU, else LSTM in decoder. + d_model (int): Dim of channels from backbone. + d_enc (int): Dim of encoder RNN layer. + d_k (int): Dim of channels of attention module. + pred_dropout (float): Dropout probability of prediction layer. + max_seq_len (int): Maximum sequence length for decoding. + mask (bool): If True, mask padding in feature map. + start_idx (int): Index of start token. + padding_idx (int): Index of padding token. + pred_concat (bool): If True, concat glimpse feature from + attention with holistic feature and hidden state. + """ + + def __init__(self, + num_classes=93, # 90 + unknown + start + padding + enc_bi_rnn=False, + dec_bi_rnn=False, + dec_drop_rnn=0.0, + dec_gru=False, + d_model=512, + d_enc=512, + d_k=64, + pred_dropout=0.1, + max_text_length=30, + mask=True, + start_idx=91, + padding_idx=92, # 92 + pred_concat=True, + **kwargs): + super().__init__() + + self.num_classes = num_classes + self.enc_bi_rnn = enc_bi_rnn + self.d_k = d_k + self.start_idx = start_idx + self.max_seq_len = max_text_length + self.mask = mask + self.pred_concat = pred_concat + + encoder_rnn_out_size = d_enc * (int(enc_bi_rnn) + 1) + decoder_rnn_out_size = encoder_rnn_out_size * (int(dec_bi_rnn) + 1) + + # 2D attention layer + self.conv1x1_1 = nn.Linear(decoder_rnn_out_size, d_k) + self.conv3x3_1 = nn.Conv2D(d_model, d_k, kernel_size=3, stride=1, padding=1) + self.conv1x1_2 = nn.Linear(d_k, 1) + + # Decoder RNN layer + if dec_bi_rnn: + direction = 'bidirectional' + else: + direction = 'forward' + + kwargs = dict( + input_size=encoder_rnn_out_size, + hidden_size=encoder_rnn_out_size, + num_layers=2, + time_major=False, + dropout=dec_drop_rnn, + direction=direction + ) + if dec_gru: + self.rnn_decoder = nn.GRU(**kwargs) + else: + self.rnn_decoder = nn.LSTM(**kwargs) + + # Decoder input embedding + self.embedding = nn.Embedding( + self.num_classes, encoder_rnn_out_size, padding_idx=padding_idx) + + # Prediction layer + self.pred_dropout = nn.Dropout(pred_dropout) + pred_num_classes = num_classes - 1 + if pred_concat: + fc_in_channel = decoder_rnn_out_size + d_model + d_enc + else: + fc_in_channel = d_model + self.prediction = nn.Linear(fc_in_channel, pred_num_classes) + + def _2d_attention(self, + decoder_input, + feat, + holistic_feat, + valid_ratios=None): + + y = self.rnn_decoder(decoder_input)[0] + # y: bsz * (seq_len + 1) * hidden_size + + attn_query = self.conv1x1_1(y) # bsz * (seq_len + 1) * attn_size + bsz, seq_len, attn_size = attn_query.shape + attn_query = paddle.unsqueeze(attn_query, axis=[3, 4]) + # (bsz, seq_len + 1, attn_size, 1, 1) + + attn_key = self.conv3x3_1(feat) + # bsz * attn_size * h * w + attn_key = attn_key.unsqueeze(1) + # bsz * 1 * attn_size * h * w + + attn_weight = paddle.tanh(paddle.add(attn_key, attn_query)) + + # bsz * (seq_len + 1) * attn_size * h * w + attn_weight = paddle.transpose(attn_weight, perm=[0, 1, 3, 4, 2]) + # bsz * (seq_len + 1) * h * w * attn_size + attn_weight = self.conv1x1_2(attn_weight) + # bsz * (seq_len + 1) * h * w * 1 + bsz, T, h, w, c = attn_weight.shape + assert c == 1 + + if valid_ratios is not None: + # cal mask of attention weight + for i, valid_ratio in enumerate(valid_ratios): + valid_width = min(w, math.ceil(w * valid_ratio)) + attn_weight[i, :, :, valid_width:, :] = float('-inf') + + attn_weight = paddle.reshape(attn_weight, [bsz, T, -1]) + attn_weight = F.softmax(attn_weight, axis=-1) + + attn_weight = paddle.reshape(attn_weight, [bsz, T, h, w, c]) + attn_weight = paddle.transpose(attn_weight, perm=[0, 1, 4, 2, 3]) + # attn_weight: bsz * T * c * h * w + # feat: bsz * c * h * w + attn_feat = paddle.sum(paddle.multiply(feat.unsqueeze(1), attn_weight), (3, 4), keepdim=False) + # bsz * (seq_len + 1) * C + + # Linear transformation + if self.pred_concat: + hf_c = holistic_feat.shape[-1] + holistic_feat = paddle.expand(holistic_feat, shape=[bsz, seq_len, hf_c]) + y = self.prediction(paddle.concat((y, attn_feat, holistic_feat), 2)) + else: + y = self.prediction(attn_feat) + # bsz * (seq_len + 1) * num_classes + if self.train_mode: + y = self.pred_dropout(y) + + return y + + def forward_train(self, feat, out_enc, label, img_metas): + ''' + img_metas: [label, valid_ratio] + ''' + if img_metas is not None: + assert len(img_metas[0]) == feat.shape[0] + + valid_ratios = None + if img_metas is not None and self.mask: + valid_ratios = img_metas[-1] + + label = label.cuda() + lab_embedding = self.embedding(label) + # bsz * seq_len * emb_dim + out_enc = out_enc.unsqueeze(1) + # bsz * 1 * emb_dim + in_dec = paddle.concat((out_enc, lab_embedding), axis=1) + # bsz * (seq_len + 1) * C + out_dec = self._2d_attention( + in_dec, feat, out_enc, valid_ratios=valid_ratios + ) + # bsz * (seq_len + 1) * num_classes + + return out_dec[:, 1:, :] # bsz * seq_len * num_classes + + def forward_test(self, feat, out_enc, img_metas): + if img_metas is not None: + assert len(img_metas[0]) == feat.shape[0] + + valid_ratios = None + if img_metas is not None and self.mask: + valid_ratios = img_metas[-1] + + seq_len = self.max_seq_len + bsz = feat.shape[0] + start_token = paddle.full((bsz, ), + fill_value=self.start_idx, + dtype='int64') + # bsz + start_token = self.embedding(start_token) + # bsz * emb_dim + emb_dim = start_token.shape[1] + start_token = start_token.unsqueeze(1) + start_token = paddle.expand(start_token, shape=[bsz, seq_len, emb_dim]) + # bsz * seq_len * emb_dim + out_enc = out_enc.unsqueeze(1) + # bsz * 1 * emb_dim + decoder_input = paddle.concat((out_enc, start_token), axis=1) + # bsz * (seq_len + 1) * emb_dim + + outputs = [] + for i in range(1, seq_len + 1): + decoder_output = self._2d_attention( + decoder_input, feat, out_enc, valid_ratios=valid_ratios + ) + char_output = decoder_output[:, i, :] # bsz * num_classes + char_output = F.softmax(char_output, -1) + outputs.append(char_output) + max_idx = paddle.argmax(char_output, axis=1, keepdim=False) + char_embedding = self.embedding(max_idx) # bsz * emb_dim + if i < seq_len: + decoder_input[:, i + 1, :] = char_embedding + + outputs = paddle.stack(outputs, 1) # bsz * seq_len * num_classes + + return outputs + + +class SARHead(nn.Layer): + def __init__(self, + enc_bi_rnn=False, + enc_drop_rnn=0.1, + enc_gru=False, + dec_bi_rnn=False, + dec_drop_rnn=0.0, + dec_gru=False, + d_k=512, + pred_dropout=0.1, + max_text_length=30, + pred_concat=True, + **kwargs): + super(SARHead, self).__init__() + + # encoder module + self.encoder = SAREncoder( + enc_bi_rnn=enc_bi_rnn, + enc_drop_rnn=enc_drop_rnn, + enc_gru=enc_gru) + + # decoder module + self.decoder = ParallelSARDecoder( + enc_bi_rnn=enc_bi_rnn, + dec_bi_rnn=dec_bi_rnn, + dec_drop_rnn=dec_drop_rnn, + dec_gru=dec_gru, + d_k=d_k, + pred_dropout=pred_dropout, + max_text_length=max_text_length, + pred_concat=pred_concat) + + def forward(self, feat, targets=None): + ''' + img_metas: [label, valid_ratio] + ''' + holistic_feat = self.encoder(feat, targets) # bsz c + + if self.training: + label = targets[0] # label + label = paddle.to_tensor(label, dtype='int64') + final_out = self.decoder(feat, holistic_feat, label, img_metas=targets) + if not self.training: + final_out = self.decoder(feat, holistic_feat, label=None, img_metas=targets, train_mode=False) + # (bsz, seq_len, num_classes) + + return final_out + \ No newline at end of file diff --git a/ppocr/utils/dict90.txt b/ppocr/utils/dict90.txt new file mode 100644 index 0000000000..a945ae9c52 --- /dev/null +++ b/ppocr/utils/dict90.txt @@ -0,0 +1,90 @@ +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 +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +: +; +< += +> +? +@ +[ +\ +] +_ +` +~ \ No newline at end of file From 8a95b3352df44307a1e9f0aff5458881356170ec Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 24 Aug 2021 03:49:26 +0000 Subject: [PATCH 06/77] add_rec_sar, test=dygraph --- doc/doc_ch/algorithm_overview.md | 3 +- doc/doc_ch/recognition.md | 1 + doc/doc_en/algorithm_overview_en.md | 2 + doc/doc_en/recognition_en.md | 1 + ppocr/data/imaug/__init__.py | 2 +- ppocr/data/imaug/label_ops.py | 46 +++++++++++++++++ ppocr/data/imaug/rec_img_aug.py | 50 ++++++++++++++++++ ppocr/losses/__init__.py | 3 +- ppocr/modeling/backbones/__init__.py | 3 +- ppocr/modeling/heads/__init__.py | 3 +- ppocr/postprocess/__init__.py | 4 +- ppocr/postprocess/rec_postprocess.py | 77 ++++++++++++++++++++++++++++ tools/eval.py | 3 +- tools/infer_rec.py | 9 ++++ tools/program.py | 13 +++-- 15 files changed, 207 insertions(+), 13 deletions(-) diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md index 19d7a69c7f..b6a365b35d 100755 --- a/doc/doc_ch/algorithm_overview.md +++ b/doc/doc_ch/algorithm_overview.md @@ -44,6 +44,7 @@ PaddleOCR基于动态图开源的文本识别算法列表: - [x] STAR-Net([paper](http://www.bmva.org/bmvc/2016/papers/paper043/index.html))[11] - [x] RARE([paper](https://arxiv.org/abs/1603.03915v1))[12] - [x] SRN([paper](https://arxiv.org/abs/2003.12294))[5] +- [x] SAR([paper](https://arxiv.org/abs/1811.00751v2)) 参考[DTRB][3](https://arxiv.org/abs/1904.01906)文字识别训练和评估流程,使用MJSynth和SynthText两个文字识别数据集训练,在IIIT, SVT, IC03, IC13, IC15, SVTP, CUTE数据集上进行评估,算法效果如下: @@ -58,6 +59,6 @@ PaddleOCR基于动态图开源的文本识别算法列表: |RARE|MobileNetV3|82.5%|rec_mv3_tps_bilstm_att |[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mv3_tps_bilstm_att_v2.0_train.tar)| |RARE|Resnet34_vd|83.6%|rec_r34_vd_tps_bilstm_att |[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r34_vd_tps_bilstm_att_v2.0_train.tar)| |SRN|Resnet50_vd_fpn| 88.52% | rec_r50fpn_vd_none_srn | [下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r50_vd_srn_train.tar) | - +|SAR|Resnet31| 87.1% | rec_r31_sar | [下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_r31_sar_train.tar) | PaddleOCR文本识别算法的训练和使用请参考文档教程中[模型训练/评估中的文本识别部分](./recognition.md)。 diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md index 0ff0513a2b..0ac6da8715 100644 --- a/doc/doc_ch/recognition.md +++ b/doc/doc_ch/recognition.md @@ -215,6 +215,7 @@ PaddleOCR支持训练和评估交替进行, 可以在 `configs/rec/rec_icdar15_t | rec_mv3_tps_bilstm_att.yml | CRNN | Mobilenet_v3 | TPS | BiLSTM | att | | rec_r34_vd_tps_bilstm_att.yml | CRNN | Resnet34_vd | TPS | BiLSTM | att | | rec_r50fpn_vd_none_srn.yml | SRN | Resnet50_fpn_vd | None | rnn | srn | +| rec_r31_sar.yml | SAR | ResNet31 | None | LSTM encoder | LSTM decoder | 训练中文数据,推荐使用[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/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md index d70f99bb5c..f201589abb 100755 --- a/doc/doc_en/algorithm_overview_en.md +++ b/doc/doc_en/algorithm_overview_en.md @@ -46,6 +46,7 @@ PaddleOCR open-source text recognition algorithms list: - [x] STAR-Net([paper](http://www.bmva.org/bmvc/2016/papers/paper043/index.html))[11] - [x] RARE([paper](https://arxiv.org/abs/1603.03915v1))[12] - [x] SRN([paper](https://arxiv.org/abs/2003.12294))[5] +- [x] SAR([paper](https://arxiv.org/abs/1811.00751v2)) 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: @@ -60,5 +61,6 @@ Refer to [DTRB](https://arxiv.org/abs/1904.01906), the training and evaluation r |RARE|MobileNetV3|82.5%|rec_mv3_tps_bilstm_att |[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_mv3_tps_bilstm_att_v2.0_train.tar)| |RARE|Resnet34_vd|83.6%|rec_r34_vd_tps_bilstm_att |[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r34_vd_tps_bilstm_att_v2.0_train.tar)| |SRN|Resnet50_vd_fpn| 88.52% | rec_r50fpn_vd_none_srn |[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/rec_r50_vd_srn_train.tar)| +|SAR|Resnet31| 87.1% | rec_r31_sar | [Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/rec/rec_r31_sar_train.tar) | Please refer to the document for training guide and use of PaddleOCR text recognition algorithms [Text recognition model training/evaluation/prediction](./recognition_en.md) diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md index 634ec783aa..91f81a6aac 100644 --- a/doc/doc_en/recognition_en.md +++ b/doc/doc_en/recognition_en.md @@ -207,6 +207,7 @@ If the evaluation set is large, the test will be time-consuming. It is recommend | rec_mv3_tps_bilstm_att.yml | CRNN | Mobilenet_v3 | TPS | BiLSTM | att | | rec_r34_vd_tps_bilstm_att.yml | CRNN | Resnet34_vd | TPS | BiLSTM | att | | rec_r50fpn_vd_none_srn.yml | SRN | Resnet50_fpn_vd | None | rnn | srn | +| rec_r31_sar.yml | SAR | ResNet31 | None | LSTM encoder | LSTM decoder | For training Chinese data, it is recommended to use diff --git a/ppocr/data/imaug/__init__.py b/ppocr/data/imaug/__init__.py index 52194eb964..6f0492e16a 100644 --- a/ppocr/data/imaug/__init__.py +++ b/ppocr/data/imaug/__init__.py @@ -21,7 +21,7 @@ from .make_border_map import MakeBorderMap from .make_shrink_map import MakeShrinkMap from .random_crop_data import EastRandomCropData, PSERandomCrop -from .rec_img_aug import RecAug, RecResizeImg, ClsResizeImg, SRNRecResizeImg +from .rec_img_aug import RecAug, RecResizeImg, ClsResizeImg, SRNRecResizeImg, SARRecResizeImg from .randaugment import RandAugment from .copy_paste import CopyPaste from .operators import * diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index d222c4109c..56da029b32 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -521,3 +521,49 @@ class TableLabelEncode(object): assert False, "Unsupport type %s in char_or_elem" \ % char_or_elem return idx + + +class SARLabelEncode(BaseRecLabelEncode): + """ Convert between text-label and text-index """ + + def __init__(self, + max_text_length, + character_dict_path=None, + character_type='ch', + use_space_char=False, + **kwargs): + super(SARLabelEncode, + self).__init__(max_text_length, character_dict_path, + character_type, use_space_char) + + def add_special_char(self, dict_character): + beg_end_str = "" + unknown_str = "" + padding_str = "" + dict_character = dict_character + [unknown_str] + self.unknown_idx = len(dict_character) - 1 + dict_character = dict_character + [beg_end_str] + self.start_idx = len(dict_character) - 1 + self.end_idx = len(dict_character) - 1 + dict_character = dict_character + [padding_str] + self.padding_idx = len(dict_character) - 1 + + return dict_character + + def __call__(self, data): + text = data['label'] + text = self.encode(text) + if text is None: + return None + if len(text) >= self.max_text_len - 1: + return None + data['length'] = np.array(len(text)) + target = [self.start_idx] + text + [self.end_idx] + padded_text = [self.padding_idx for _ in range(self.max_text_len)] + + padded_text[:len(target)] = target + data['label'] = np.array(padded_text) + return data + + def get_ignored_tokens(self): + return [self.padding_idx] diff --git a/ppocr/data/imaug/rec_img_aug.py b/ppocr/data/imaug/rec_img_aug.py index 28e6bd0bce..d968f43744 100644 --- a/ppocr/data/imaug/rec_img_aug.py +++ b/ppocr/data/imaug/rec_img_aug.py @@ -83,6 +83,56 @@ class SRNRecResizeImg(object): return data +class SARRecResizeImg(object): + def __init__(self, image_shape, width_downsample_ratio=0.25, **kwargs): + self.image_shape = image_shape + self.width_downsample_ratio = width_downsample_ratio + + def __call__(self, data): + img = data['image'] + norm_img, resize_shape, pad_shape, valid_ratio = resize_norm_img_sar(img, self.image_shape, self.width_downsample_ratio) + data['image'] = norm_img + data['resized_shape'] = resize_shape + data['pad_shape'] = pad_shape + data['valid_ratio'] = valid_ratio + return data + + +def resize_norm_img_sar(img, image_shape, width_downsample_ratio=0.25): + imgC, imgH, imgW_min, imgW_max = image_shape + h = img.shape[0] + w = img.shape[1] + valid_ratio = 1.0 + # make sure new_width is an integral multiple of width_divisor. + width_divisor = int(1 / width_downsample_ratio) + # resize + ratio = w / float(h) + resize_w = math.ceil(imgH * ratio) + if resize_w % width_divisor != 0: + resize_w = round(resize_w / width_divisor) * width_divisor + if imgW_min is not None: + resize_w = max(imgW_min, resize_w) + if imgW_max is not None: + valid_ratio = min(1.0, 1.0 * resize_w / imgW_max) + resize_w = min(imgW_max, resize_w) + resized_image = cv2.resize(img, (resize_w, imgH)) + resized_image = resized_image.astype('float32') + # norm + if image_shape[0] == 1: + resized_image = resized_image / 255 + resized_image = resized_image[np.newaxis, :] + else: + resized_image = resized_image.transpose((2, 0, 1)) / 255 + resized_image -= 0.5 + resized_image /= 0.5 + resize_shape = resized_image.shape + padding_im = -1.0 * np.ones((imgC, imgH, imgW_max), dtype=np.float32) + padding_im[:, :, 0:resize_w] = resized_image + pad_shape = padding_im.shape + + return padding_im, resize_shape, pad_shape, valid_ratio + + def resize_norm_img(img, image_shape): imgC, imgH, imgW = image_shape h = img.shape[0] diff --git a/ppocr/losses/__init__.py b/ppocr/losses/__init__.py index 025ae7ca5c..d731185b3e 100755 --- a/ppocr/losses/__init__.py +++ b/ppocr/losses/__init__.py @@ -25,6 +25,7 @@ from .det_sast_loss import SASTLoss from .rec_ctc_loss import CTCLoss from .rec_att_loss import AttentionLoss from .rec_srn_loss import SRNLoss +from .rec_sar_loss import SARLoss # cls loss from .cls_loss import ClsLoss @@ -44,7 +45,7 @@ from .table_att_loss import TableAttentionLoss def build_loss(config): support_dict = [ 'DBLoss', 'EASTLoss', 'SASTLoss', 'CTCLoss', 'ClsLoss', 'AttentionLoss', - 'SRNLoss', 'PGLoss', 'CombinedLoss', 'TableAttentionLoss' + 'SRNLoss', 'PGLoss', 'CombinedLoss', 'TableAttentionLoss', 'SARLoss' ] config = copy.deepcopy(config) module_name = config.pop('name') diff --git a/ppocr/modeling/backbones/__init__.py b/ppocr/modeling/backbones/__init__.py index f4fe8c76be..ce1d6bcf28 100755 --- a/ppocr/modeling/backbones/__init__.py +++ b/ppocr/modeling/backbones/__init__.py @@ -26,8 +26,9 @@ def build_backbone(config, model_type): from .rec_resnet_vd import ResNet from .rec_resnet_fpn import ResNetFPN from .rec_mv1_enhance import MobileNetV1Enhance + from .rec_resnet_31 import ResNet31 support_dict = [ - "MobileNetV1Enhance", "MobileNetV3", "ResNet", "ResNetFPN" + "MobileNetV1Enhance", "MobileNetV3", "ResNet", "ResNetFPN", "ResNet31" ] elif model_type == "e2e": from .e2e_resnet_vd_pg import ResNet diff --git a/ppocr/modeling/heads/__init__.py b/ppocr/modeling/heads/__init__.py index 5096479415..8414f2adfd 100755 --- a/ppocr/modeling/heads/__init__.py +++ b/ppocr/modeling/heads/__init__.py @@ -26,12 +26,13 @@ def build_head(config): from .rec_ctc_head import CTCHead from .rec_att_head import AttentionHead from .rec_srn_head import SRNHead + from .rec_sar_head import SARHead # cls head from .cls_head import ClsHead support_dict = [ 'DBHead', 'EASTHead', 'SASTHead', 'CTCHead', 'ClsHead', 'AttentionHead', - 'SRNHead', 'PGHead', 'TableAttentionHead'] + 'SRNHead', 'PGHead', 'TableAttentionHead', 'SARHead'] #table head from .table_att_head import TableAttentionHead diff --git a/ppocr/postprocess/__init__.py b/ppocr/postprocess/__init__.py index 654ddf39d2..86f9ede45c 100644 --- a/ppocr/postprocess/__init__.py +++ b/ppocr/postprocess/__init__.py @@ -25,7 +25,7 @@ from .db_postprocess import DBPostProcess, DistillationDBPostProcess from .east_postprocess import EASTPostProcess from .sast_postprocess import SASTPostProcess from .rec_postprocess import CTCLabelDecode, AttnLabelDecode, SRNLabelDecode, DistillationCTCLabelDecode, \ - TableLabelDecode + TableLabelDecode, SARLabelDecode from .cls_postprocess import ClsPostProcess from .pg_postprocess import PGPostProcess @@ -35,7 +35,7 @@ def build_post_process(config, global_config=None): 'DBPostProcess', 'EASTPostProcess', 'SASTPostProcess', 'CTCLabelDecode', 'AttnLabelDecode', 'ClsPostProcess', 'SRNLabelDecode', 'PGPostProcess', 'DistillationCTCLabelDecode', 'TableLabelDecode', - 'DistillationDBPostProcess' + 'DistillationDBPostProcess', 'SARLabelDecode' ] config = copy.deepcopy(config) diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index 8ebe5b2741..9e9ddd8f95 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -15,6 +15,7 @@ import numpy as np import string import paddle from paddle.nn import functional as F +import re class BaseRecLabelDecode(object): @@ -454,3 +455,79 @@ class TableLabelDecode(object): assert False, "Unsupport type %s in char_or_elem" \ % char_or_elem return idx + + +class SARLabelDecode(BaseRecLabelDecode): + """ Convert between text-label and text-index """ + + def __init__(self, + character_dict_path=None, + character_type='ch', + use_space_char=False, + **kwargs): + super(SARLabelDecode, self).__init__(character_dict_path, + character_type, use_space_char) + + def add_special_char(self, dict_character): + beg_end_str = "" + unknown_str = "" + padding_str = "" + dict_character = dict_character + [unknown_str] + self.unknown_idx = len(dict_character) - 1 + dict_character = dict_character + [beg_end_str] + self.start_idx = len(dict_character) - 1 + self.end_idx = len(dict_character) - 1 + dict_character = dict_character + [padding_str] + self.padding_idx = len(dict_character) - 1 + return dict_character + + def decode(self, text_index, text_prob=None, is_remove_duplicate=False): + """ convert text-index into text-label. """ + result_list = [] + ignored_tokens = self.get_ignored_tokens() + + batch_size = len(text_index) + for batch_idx in range(batch_size): + char_list = [] + conf_list = [] + for idx in range(len(text_index[batch_idx])): + if text_index[batch_idx][idx] in ignored_tokens: + continue + if int(text_index[batch_idx][idx]) == int(self.end_idx): + if text_prob is None and idx ==0: + continue + else: + break + if is_remove_duplicate: + # only for predict + if idx > 0 and text_index[batch_idx][idx - 1] == text_index[ + batch_idx][idx]: + continue + char_list.append(self.character[int(text_index[batch_idx][ + idx])]) + if text_prob is not None: + conf_list.append(text_prob[batch_idx][idx]) + else: + conf_list.append(1) + text = ''.join(char_list) + comp = re.compile('[^A-Z^a-z^0-9^\u4e00-\u9fa5]') + text = text.lower() + text = comp.sub('', text) + result_list.append((text, np.mean(conf_list))) + return result_list + + def __call__(self, preds, label=None, *args, **kwargs): + if isinstance(preds, paddle.Tensor): + preds = preds.numpy() + preds_idx = preds.argmax(axis=2) + preds_prob = preds.max(axis=2) + + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) + + if label is None: + return text + label = self.decode(label, is_remove_duplicate=False) + return text, label + + def get_ignored_tokens(self): + return [self.padding_idx] diff --git a/tools/eval.py b/tools/eval.py index 0120baab0f..fb8c7925ad 100755 --- a/tools/eval.py +++ b/tools/eval.py @@ -55,6 +55,7 @@ def main(): model = build_model(config['Architecture']) use_srn = config['Architecture']['algorithm'] == "SRN" + use_sar = config['Architecture']['algorithm'] == "SAR" if "model_type" in config['Architecture'].keys(): model_type = config['Architecture']['model_type'] else: @@ -71,7 +72,7 @@ def main(): # start eval metric = program.eval(model, valid_dataloader, post_process_class, - eval_class, model_type, use_srn) + eval_class, model_type, use_srn, use_sar) logger.info('metric eval ***************') for k, v in metric.items(): logger.info('{}:{}'.format(k, v)) diff --git a/tools/infer_rec.py b/tools/infer_rec.py index 09f5a0c767..f16cd7d327 100755 --- a/tools/infer_rec.py +++ b/tools/infer_rec.py @@ -74,6 +74,10 @@ def main(): 'image', 'encoder_word_pos', 'gsrm_word_pos', 'gsrm_slf_attn_bias1', 'gsrm_slf_attn_bias2' ] + elif config['Architecture']['algorithm'] == "SAR": + op[op_name]['keep_keys'] = [ + 'image', 'valid_ratio' + ] else: op[op_name]['keep_keys'] = ['image'] transforms.append(op) @@ -106,11 +110,16 @@ def main(): paddle.to_tensor(gsrm_slf_attn_bias1_list), paddle.to_tensor(gsrm_slf_attn_bias2_list) ] + if config['Architecture']['algorithm'] == "SAR": + valid_ratio = np.expand_dims(batch[-1], axis=0) + img_metas = [paddle.to_tensor(valid_ratio)] images = np.expand_dims(batch[0], axis=0) images = paddle.to_tensor(images) if config['Architecture']['algorithm'] == "SRN": preds = model(images, others) + elif config['Architecture']['algorithm'] == "SAR": + preds = model(images, img_metas) else: preds = model(images) post_result = post_process_class(preds) diff --git a/tools/program.py b/tools/program.py index 595fe4cb96..cb6f8a8b75 100755 --- a/tools/program.py +++ b/tools/program.py @@ -186,6 +186,7 @@ def train(config, model.train() use_srn = config['Architecture']['algorithm'] == "SRN" + use_sar = config['Architecture']['algorithm'] == 'SAR' try: model_type = config['Architecture']['model_type'] except: @@ -213,7 +214,7 @@ def train(config, images = batch[0] if use_srn: model_average = True - if use_srn or model_type == 'table': + if use_srn or model_type == 'table' or use_sar: preds = model(images, data=batch[1:]) else: preds = model(images) @@ -277,7 +278,8 @@ def train(config, post_process_class, eval_class, model_type, - use_srn=use_srn) + use_srn=use_srn, + use_sar=use_sar) cur_metric_str = 'cur metric, {}'.format(', '.join( ['{}: {}'.format(k, v) for k, v in cur_metric.items()])) logger.info(cur_metric_str) @@ -349,7 +351,8 @@ def eval(model, post_process_class, eval_class, model_type, - use_srn=False): + use_srn=False, + use_sar=False): model.eval() with paddle.no_grad(): total_frame = 0.0 @@ -362,7 +365,7 @@ def eval(model, break images = batch[0] start = time.time() - if use_srn or model_type == 'table': + if use_srn or model_type == 'table' or use_sar: preds = model(images, data=batch[1:]) else: preds = model(images) @@ -398,7 +401,7 @@ def preprocess(is_train=False): alg = config['Architecture']['algorithm'] assert alg in [ 'EAST', 'DB', 'SAST', 'Rosetta', 'CRNN', 'STARNet', 'RARE', 'SRN', - 'CLS', 'PGNet', 'Distillation', 'TableAttn' + 'CLS', 'PGNet', 'Distillation', 'TableAttn', 'SAR' ] device = 'gpu:{}'.format(dist.ParallelEnv().dev_id) if use_gpu else 'cpu' From 69f9bdd8f6730762b2b4348b5a2791d736968af5 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 24 Aug 2021 04:23:03 +0000 Subject: [PATCH 07/77] add_rec_sar,test=dygraph --- configs/rec/rec_r31_sar.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index 3a39806410..b761d28bd2 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -3,16 +3,16 @@ Global: epoch_num: 5 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: /paddle/backup/sar_rec/sar_train_v3 + save_model_dir: ./sar_rec save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] cal_metric_during_train: True - pretrained_model: #/paddle/backup/sar_rec/sar_train_v2/best_accuracy + pretrained_model: checkpoints: save_inference_dir: use_visualdl: False - infer_img: demo_text_recog.jpg + infer_img: # for data or label process character_dict_path: ppocr/utils/dict90.txt character_type: ch @@ -54,11 +54,11 @@ Metric: Train: dataset: - name: LMDBDataSet #SimpleDataSet - # delimiter: ' ' - # label_file_list: ['/paddle/data/concat_data/icdar_2013_train20.txt', '/paddle/data/concat_data/icdar_2015_train20.txt', '/paddle/data/concat_data/coco_text_train20.txt', '/paddle/data/concat_data/IIIt5k_train20.txt', '/paddle/data/concat_data/SynthAdd_train.txt', '/paddle/data/concat_data/SynthText_train.txt', '/paddle/data/concat_data/Syn90k_train.txt'] - data_dir: /paddle/data/ocr_data/training/ #/paddle/data/concat_data/ - # ratio_list: 1.0 + name: SimpleDataSet + delimiter: ' ' + label_file_list: ['/paddle/data/concat_data/icdar_2013_train20.txt', '/paddle/data/concat_data/icdar_2015_train20.txt', '/paddle/data/concat_data/coco_text_train20.txt', '/paddle/data/concat_data/IIIt5k_train20.txt', '/paddle/data/concat_data/SynthAdd_train.txt', '/paddle/data/concat_data/SynthText_train.txt', '/paddle/data/concat_data/Syn90k_train.txt'] + data_dir: /paddle/data/concat_data/ + ratio_list: 1.0 transforms: - DecodeImage: # load image img_mode: BGR @@ -96,4 +96,4 @@ Eval: batch_size_per_card: 64 num_workers: 4 use_shared_memory: False - \ No newline at end of file + From 9ba13f104e82f83318cc2faba60e4379f12fb048 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 02:35:32 +0000 Subject: [PATCH 08/77] add train model download --- tests/prepare.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index 5da74d949f..45d4c880b6 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -63,10 +63,10 @@ elif [ ${MODE} = "whole_infer" ];then cd ../ elif [ ${MODE} = "infer" ] || [ ${MODE} = "cpp_infer" ];then if [ ${model_name} = "ocr_det" ]; then - eval_model_name="ch_ppocr_mobile_v2.0_det_infer" + eval_model_name="ch_ppocr_mobile_v2.0_det_train" rm -rf ./train_data/icdar2015 wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar - wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar cd ./inference && tar xf ${eval_model_name}.tar && tar xf ch_det_data_50.tar && cd ../ elif [ ${model_name} = "ocr_server_det" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar From 33f44548791f6ada6b39a67744343b067b5f781b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 02:36:11 +0000 Subject: [PATCH 09/77] add export statue check for infer MODE --- tests/test.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test.sh b/tests/test.sh index 484d557353..9fe16968ee 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -332,9 +332,7 @@ if [ ${MODE} = "infer" ]; then export_cmd="${python} ${norm_export} ${set_export_weight} ${set_save_infer_key}" eval $export_cmd status_export=$? - if [ ${status_export} = 0 ];then - status_check $status_export "${export_cmd}" "${status_log}" - fi + status_check $status_export "${export_cmd}" "${status_log}" else save_infer_dir=${infer_model} fi From 07f4199445203664441f95f06cf7824690d7d470 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 02:36:43 +0000 Subject: [PATCH 10/77] support train model for infer MODE --- tests/ocr_det_params.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 73b12cec9c..bb1556fb81 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -34,8 +34,8 @@ distill_export:null export1:null export2:null ## -infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ -infer_export:null +infer_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy +infer_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False From 01d5937808d8108bbf6ab7e3af377d8ba981e16a Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 02:37:26 +0000 Subject: [PATCH 11/77] set cpu_thread as 6 --- tests/ocr_det_params.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index bb1556fb81..733de0ff45 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -40,7 +40,7 @@ infer_quant:False inference:tools/infer/predict_det.py --use_gpu:True|False --enable_mkldnn:True|False ---cpu_threads:1|6 +--cpu_threads:6 --rec_batch_num:1 --use_tensorrt:False|True --precision:fp32|fp16|int8 From eb96c623b8d2a6f3b6e973c76f5b0349546f36bc Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 06:46:40 +0000 Subject: [PATCH 12/77] set benchmark in predict_system --- tools/infer/predict_system.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/infer/predict_system.py b/tools/infer/predict_system.py index eae0e27cd2..6e7f69025a 100755 --- a/tools/infer/predict_system.py +++ b/tools/infer/predict_system.py @@ -173,7 +173,9 @@ def main(args): logger.info("The predict total time is {}".format(time.time() - _st)) logger.info("\nThe predict total time is {}".format(total_time)) - + if args.benchmark: + text_sys.text_detector.autolog.report() + text_sys.text_recognizer.autolog.report() if __name__ == "__main__": args = utility.parse_args() From cf16859919b574aea5c8f55022135bea875f3da6 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 06:48:27 +0000 Subject: [PATCH 13/77] set benchmark in predict_system --- tools/infer/predict_system.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/infer/predict_system.py b/tools/infer/predict_system.py index 6e7f69025a..b5edd01589 100755 --- a/tools/infer/predict_system.py +++ b/tools/infer/predict_system.py @@ -177,6 +177,7 @@ def main(args): text_sys.text_detector.autolog.report() text_sys.text_recognizer.autolog.report() + if __name__ == "__main__": args = utility.parse_args() if args.use_mp: From 3133ff28d9e8e37d628c899464d8eedc76885215 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 07:03:13 +0000 Subject: [PATCH 14/77] add ocr_system --- tests/prepare.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index 5da74d949f..6e329b6581 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -72,6 +72,11 @@ elif [ ${MODE} = "infer" ] || [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ocr_system" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ else rm -rf ./train_data/ic15_data eval_model_name="ch_ppocr_mobile_v2.0_rec_infer" @@ -149,4 +154,4 @@ if [ ${MODE} = "cpp_infer" ];then make -j echo "################### build PaddleOCR demo finished ###################" -fi \ No newline at end of file +fi From aa210b9d6241845013ca0458671ea2ae711c4661 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 07:03:36 +0000 Subject: [PATCH 15/77] add tests/ppocr_mobile_params.txt --- tests/ppocr_mobile_params.txt | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/ppocr_mobile_params.txt diff --git a/tests/ppocr_mobile_params.txt b/tests/ppocr_mobile_params.txt new file mode 100644 index 0000000000..7f0e65596d --- /dev/null +++ b/tests/ppocr_mobile_params.txt @@ -0,0 +1,67 @@ +===========================train_params=========================== +model_name:ocr_system +python:python3.7 +gpu_list:null +Global.use_gpu:null +Global.auto_cast:null +Global.epoch_num:null +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:null +Global.pretrained_model:null +train_model_name:null +train_infer_img_dir:null +null:null +## +trainer: +norm_train:null +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.pretrained_model: +norm_export:null +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_system.py +--use_gpu:True +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +===========================cpp_infer_params=========================== +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr det +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True + From 11d9169c2b580d8bbbe54c09e4d69cac4835c050 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 07:04:52 +0000 Subject: [PATCH 16/77] rename ppocr_mobile_params.txt --- tests/1 | 67 +++++++++++++++++++ ...params.txt => ocr_ppocr_mobile_params.txt} | 0 2 files changed, 67 insertions(+) create mode 100644 tests/1 rename tests/{ppocr_mobile_params.txt => ocr_ppocr_mobile_params.txt} (100%) diff --git a/tests/1 b/tests/1 new file mode 100644 index 0000000000..bb237f793a --- /dev/null +++ b/tests/1 @@ -0,0 +1,67 @@ +===========================train_params=========================== +model_name:ocr_det +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:null +Global.epoch_num:lite_train_infer=1|whole_train_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_infer=2|whole_train_infer=4 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ +null:null +## +trainer:norm_train|pact_train|fpgm_train +norm_train:tools/train.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained +pact_train:deploy/slim/quantization/quant.py -c configs/det/det_mv3_db.yml -o +fpgm_train:deploy/slim/prune/sensitivity_anal.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/det_mv3_db_v2.0_train/best_accuracy +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c configs/det/det_mv3_db.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.pretrained_model: +norm_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o +quant_export:deploy/slim/quantization/export_model.py -c configs/det/det_mv3_db.yml -o +fpgm_export:deploy/slim/prune/export_prune_model.py -c configs/det/det_mv3_db.yml -o +distill_export:null +export1:null +export2:null +## +infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_system.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +===========================cpp_infer_params=========================== +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr det +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True + diff --git a/tests/ppocr_mobile_params.txt b/tests/ocr_ppocr_mobile_params.txt similarity index 100% rename from tests/ppocr_mobile_params.txt rename to tests/ocr_ppocr_mobile_params.txt From 35449b5c7440f7706e5a4558e5b3efeb76944432 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Fri, 27 Aug 2021 07:05:06 +0000 Subject: [PATCH 17/77] rename ppocr_mobile_params.txt --- tests/1 | 67 --------------------------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 tests/1 diff --git a/tests/1 b/tests/1 deleted file mode 100644 index bb237f793a..0000000000 --- a/tests/1 +++ /dev/null @@ -1,67 +0,0 @@ -===========================train_params=========================== -model_name:ocr_det -python:python3.7 -gpu_list:0|0,1 -Global.use_gpu:True|True -Global.auto_cast:null -Global.epoch_num:lite_train_infer=1|whole_train_infer=300 -Global.save_model_dir:./output/ -Train.loader.batch_size_per_card:lite_train_infer=2|whole_train_infer=4 -Global.pretrained_model:null -train_model_name:latest -train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ -null:null -## -trainer:norm_train|pact_train|fpgm_train -norm_train:tools/train.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained -pact_train:deploy/slim/quantization/quant.py -c configs/det/det_mv3_db.yml -o -fpgm_train:deploy/slim/prune/sensitivity_anal.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/det_mv3_db_v2.0_train/best_accuracy -distill_train:null -null:null -null:null -## -===========================eval_params=========================== -eval:tools/eval.py -c configs/det/det_mv3_db.yml -o -null:null -## -===========================infer_params=========================== -Global.save_inference_dir:./output/ -Global.pretrained_model: -norm_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o -quant_export:deploy/slim/quantization/export_model.py -c configs/det/det_mv3_db.yml -o -fpgm_export:deploy/slim/prune/export_prune_model.py -c configs/det/det_mv3_db.yml -o -distill_export:null -export1:null -export2:null -## -infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ -infer_export:null -infer_quant:False -inference:tools/infer/predict_system.py ---use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 ---rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16|int8 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ ---save_log_path:null ---benchmark:True ---rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ -===========================cpp_infer_params=========================== -use_opencv:True -infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ -infer_quant:False -inference:./deploy/cpp_infer/build/ppocr det ---use_gpu:True|False ---enable_mkldnn:True|False ---cpu_threads:1|6 ---rec_batch_num:1 ---use_tensorrt:False|True ---precision:fp32|fp16 ---det_model_dir: ---image_dir:./inference/ch_det_data_50/all-sum-510/ ---save_log_path:null ---benchmark:True - From bd025cd29bc9aaa1d8745589d12083d016d33794 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Tue, 31 Aug 2021 08:43:09 +0000 Subject: [PATCH 18/77] add more config for serving --- tests/ocr_det_params.txt | 8 ++- tests/test.sh | 106 ++++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 19 deletions(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 4e59fcd756..2dd9f958ab 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -57,5 +57,11 @@ trans_model:-m paddle_serving_client.convert --serving_server:./deploy/pdserving/ppocr_det_mobile_2.0_serving/ --serving_client:./deploy/pdserving/ppocr_det_mobile_2.0_client/ serving_dir:./deploy/pdserving -web_service:web_service_det.py &>log.txt & +web_service:web_service_det.py --config=config.yml --opt op.det.concurrency=1 +op.det.local_service_conf.devices:null|0 +op.det.local_service_conf.use_mkldnn:True|False +op.det.local_service_conf.thread_num:1|6 +op.det.local_service_conf.use_trt:False|True +op.det.local_service_conf.precision:fp32|fp16|int8 pipline:pipeline_http_client.py --image_dir=../../doc/imgs + diff --git a/tests/test.sh b/tests/test.sh index 12dfa9d3d7..ac2687d347 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -158,7 +158,17 @@ serving_client_key=$(func_parser_key "${lines[57]}") serving_client_value=$(func_parser_value "${lines[57]}") serving_dir_value=$(func_parser_value "${lines[58]}") web_service_py=$(func_parser_value "${lines[59]}") -pipline_py=$(func_parser_value "${lines[60]}") +web_use_gpu_key=$(func_parser_key "${lines[60]}") +web_use_gpu_list=$(func_parser_value "${lines[60]}") +web_use_mkldnn_key=$(func_parser_key "${lines[61]}") +web_use_mkldnn_list=$(func_parser_value "${lines[61]}") +web_cpu_threads_key=$(func_parser_key "${lines[62]}") +web_cpu_threads_list=$(func_parser_value "${lines[62]}") +web_use_trt_key=$(func_parser_key "${lines[63]}") +web_use_trt_list=$(func_parser_value "${lines[63]}") +web_precision_key=$(func_parser_key "${lines[64]}") +web_precision_list=$(func_parser_value "${lines[64]}") +pipline_py=$(func_parser_value "${lines[65]}") LOG_PATH="./tests/output" @@ -234,6 +244,69 @@ function func_inference(){ done } +function func_serving(){ + IFS='|' + _python=$1 + _script=$2 + _model_dir=$3 + # pdserving + set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") + set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") + set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") + set_serving_server=$(func_set_params "${serving_server_key}" "${serving_server_value}") + set_serving_client=$(func_set_params "${serving_client_key}" "${serving_client_value}") + trans_model_cmd="${python} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" + eval $trans_model_cmd + cd ${serving_dir_value} + echo $PWD + for use_gpu in ${web_use_gpu_list[*]}; do + echo ${ues_gpu} + if [ ${use_gpu} = "null" ]; then + for use_mkldnn in ${web_use_mkldnn_list[*]}; do + if [ ${use_mkldnn} = "False" ]; then + continue + fi + for threads in ${web_cpu_threads_list[*]}; do + _save_log_path="${_log_path}/server_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" + set_cpu_threads=$(func_set_params "${web_cpu_threads_key}" "${threads}") + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} &>log.txt &" + echo $web_service_cmd + eval $web_service_cmd + pipline_cmd="${python} ${pipline_py}" + echo $pipline_cmd + eval $pipline_cmd + done + done + elif [ ${use_gpu} = "0" ]; then + for use_trt in ${web_use_trt_list[*]}; do + for precision in ${web_precision_list[*]}; do + if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then + continue + fi + if [[ ${precision} =~ "fp16" || ${precision} =~ "int8" ]] && [ ${use_trt} = "False" ]; then + continue + fi + if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [ ${_flag_quant} = "True" ]; then + continue + fi + _save_log_path="${_log_path}/infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" + set_tensorrt=$(func_set_params "${web_use_trt_key}" "${use_trt}") + set_precision=$(func_set_params "${web_precision_key}" "${precision}") + web_service_cmd="${_python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${web_use_trt_key}=${set_tensorrt} ${set_precision} > ${_save_log_path} &>log.txt & " + echo $web_service_cmd + eval $web_service_cmd + pipline_cmd="${python} ${pipline_py}" + echo $pipline_cmd + eval $pipline_cmd + done + done + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done +} + + if [ ${MODE} = "infer" ]; then GPUID=$3 if [ ${#GPUID} -le 0 ];then @@ -266,25 +339,21 @@ if [ ${MODE} = "infer" ]; then is_quant=${infer_quant_flag[Count]} func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${LOG_PATH}" "${infer_img_dir}" ${is_quant} Count=$(($Count + 1)) - #run serving - set_dirname=$(func_set_params "${infer_model_dir_key}" "${infer_model_dir_value}") - set_model_filename=$(func_set_params "${model_filename_key}" "${model_filename_value}") - set_params_filename=$(func_set_params "${params_filename_key}" "${params_filename_value}") - set_serving_server=$(func_set_params "${serving_server_key}" "${serving_server_value}") - set_serving_client=$(func_set_params "${serving_client_key}" "${serving_client_value}") - trans_model_cmd="${python} ${trans_model_py} ${set_dirname} ${set_model_filename} ${set_params_filename} ${set_serving_server} ${set_serving_client}" - eval $trans_model_cmd - cd ${serving_dir_value} - echo $PWD - web_service_cmd="${python} ${web_service_py}" - echo $web_service_cmd - eval $web_service_cmd - pipline_cmd="${python} ${pipline_py}" - echo $pipline_cmd - eval $pipline_cmd - done +elif [ ${MODE} = "serving_infer" ]; then + GPUID=$3 + if [ ${#GPUID} -le 0 ];then + env=" " + else + env="export CUDA_VISIBLE_DEVICES=${GPUID}" + fi + # set CUDA_VISIBLE_DEVICES + eval $env + export Count=0 + IFS="|" + #run serving + func_serving "${web_service_cmd}" else IFS="|" export Count=0 @@ -397,3 +466,4 @@ else done # done with: for gpu in ${gpu_list[*]}; do fi # end if [ ${MODE} = "infer" ]; then + From d43688a4da377269b6469bc818ce325301eb51a7 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 31 Aug 2021 11:33:41 +0000 Subject: [PATCH 19/77] update rec_r31_sar.yml and sar docs --- configs/rec/rec_r31_sar.yml | 4 ++-- doc/doc_ch/recognition.md | 2 ++ doc/doc_en/recognition_en.md | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index b761d28bd2..c19bcdee09 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -56,7 +56,7 @@ Train: dataset: name: SimpleDataSet delimiter: ' ' - label_file_list: ['/paddle/data/concat_data/icdar_2013_train20.txt', '/paddle/data/concat_data/icdar_2015_train20.txt', '/paddle/data/concat_data/coco_text_train20.txt', '/paddle/data/concat_data/IIIt5k_train20.txt', '/paddle/data/concat_data/SynthAdd_train.txt', '/paddle/data/concat_data/SynthText_train.txt', '/paddle/data/concat_data/Syn90k_train.txt'] + label_file_list: ['/paddle/data/concat_data/train_list.txt'] data_dir: /paddle/data/concat_data/ ratio_list: 1.0 transforms: @@ -71,7 +71,7 @@ Train: keep_keys: ['image', 'label', 'valid_ratio'] # dataloader will return list in this order loader: shuffle: True - batch_size_per_card: 64 # 32 + batch_size_per_card: 64 drop_last: True num_workers: 8 use_shared_memory: False diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md index 0ac6da8715..bcad6b8654 100644 --- a/doc/doc_ch/recognition.md +++ b/doc/doc_ch/recognition.md @@ -90,6 +90,8 @@ train_data/rec/train/word_002.jpg 用科技让复杂的世界更简单 如果希望复现SRN的论文指标,需要下载离线[增广数据](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA),提取码: y3ry。增广数据是由MJSynth和SynthText做旋转和扰动得到的。数据下载完成后请解压到 {your_path}/PaddleOCR/train_data/data_lmdb_release/training/ 路径下。 +如果希望复现SAR的论文指标,需要下载[SynthAdd](https://pan.baidu.com/share/init?surl=uV0LtoNmcxbO-0YA7Ch4dg), 提取码:627x。此外,真实数据集icdar2013, icdar2015, cocotext, IIIT5也作为训练数据的一部分。具体数据细节可以参考论文SAR。 + ``` # 训练集标签 wget -P ./train_data/ic15_data https://paddleocr.bj.bcebos.com/dataset/rec_gt_train.txt diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md index 91f81a6aac..65030b4a16 100644 --- a/doc/doc_en/recognition_en.md +++ b/doc/doc_en/recognition_en.md @@ -90,6 +90,8 @@ If you do not have a dataset locally, you can download it on the official websit If you want to reproduce the paper indicators of SRN, you need to download offline [augmented data](https://pan.baidu.com/s/1-HSZ-ZVdqBF2HaBZ5pRAKA), extraction code: y3ry. The augmented data is obtained by rotation and perturbation of mjsynth and synthtext. Please unzip the data to {your_path}/PaddleOCR/train_data/data_lmdb_Release/training/path. +If you want to reproduce the paper SAR, you need to download extra dataset [SynthAdd](https://pan.baidu.com/share/init?surl=uV0LtoNmcxbO-0YA7Ch4dg), extraction code: 627x. Besides, icdar2013, icdar2015, cocotext, IIIT5k datasets are also used to train. For specific details, please refer to the paper SAR. + PaddleOCR provides label files for training the icdar2015 dataset, which can be downloaded in the following ways: ``` From e7d981b674248bfb5e4cf9c0be794997351c8232 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 11:43:00 +0000 Subject: [PATCH 20/77] add resize class and lock seed --- configs/det/det_mv3_db.yml | 10 ++++++---- ppocr/data/imaug/operators.py | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/configs/det/det_mv3_db.yml b/configs/det/det_mv3_db.yml index b69ed58cd6..b702ad04cc 100644 --- a/configs/det/det_mv3_db.yml +++ b/configs/det/det_mv3_db.yml @@ -76,10 +76,12 @@ Train: - { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } - { 'type': Resize, 'args': { 'size': [0.5, 3] } } - - EastRandomCropData: + - Resize: size: [640, 640] - max_tries: 50 - keep_ratio: true +# - EastRandomCropData: +# size: [640, 640] +# max_tries: 50 +# keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 @@ -128,4 +130,4 @@ Eval: drop_last: False batch_size_per_card: 1 # must be 1 num_workers: 8 - use_shared_memory: False \ No newline at end of file + use_shared_memory: False diff --git a/ppocr/data/imaug/operators.py b/ppocr/data/imaug/operators.py index 2535b4420c..6b62dd1da8 100644 --- a/ppocr/data/imaug/operators.py +++ b/ppocr/data/imaug/operators.py @@ -81,7 +81,7 @@ class NormalizeImage(object): assert isinstance(img, np.ndarray), "invalid input 'img' in NormalizeImage" data['image'] = ( - img.astype('float32') * self.scale - self.mean) / self.std + img.astype('float32') * self.scale - self.mean) / self.std return data @@ -112,6 +112,34 @@ class KeepKeys(object): return data_list +class Resize(object): + def __init__(self, size=(640, 640), **kwargs): + self.size = size + + def resize_image(self, img): + resize_h, resize_w = self.size + ori_h, ori_w = img.shape[:2] # (h, w, c) + ratio_h = float(resize_h) / ori_h + ratio_w = float(resize_w) / ori_w + img = cv2.resize(img, (int(resize_w), int(resize_h))) + return img, [ratio_h, ratio_w] + + def __call__(self, data): + img = data['image'] + text_polys = data['polys'] + + img_resize, [ratio_h, ratio_w] = self.resize_image(img) + new_boxes = [] + for box in text_polys: + new_box = [] + for cord in box: + new_box.append([cord[0] * ratio_w, cord[1] * ratio_h]) + new_boxes.append(new_box) + data['image'] = img_resize + data['polys'] = np.array(new_boxes, dtype=np.float32) + return data + + class DetResizeForTest(object): def __init__(self, **kwargs): super(DetResizeForTest, self).__init__() @@ -183,7 +211,7 @@ class DetResizeForTest(object): else: ratio = 1. elif self.limit_type == 'resize_long': - ratio = float(limit_side_len) / max(h,w) + ratio = float(limit_side_len) / max(h, w) else: raise Exception('not support limit type, image ') resize_h = int(h * ratio) From f6cb62b7b8591c33fb4b7acfb82e9a924e461a9d Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 11:43:32 +0000 Subject: [PATCH 21/77] lock seed for res50_db --- configs/det/det_r50_vd_db.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml index 42b3898ef4..4a6820dab5 100644 --- a/configs/det/det_r50_vd_db.yml +++ b/configs/det/det_r50_vd_db.yml @@ -75,10 +75,12 @@ Train: - { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } - { 'type': Resize, 'args': { 'size': [0.5, 3] } } - - EastRandomCropData: + - Resize: size: [640, 640] - max_tries: 50 - keep_ratio: true +# - EastRandomCropData: +# size: [640, 640] +# max_tries: 50 +# keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 @@ -95,10 +97,10 @@ Train: - KeepKeys: keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list loader: - shuffle: True + shuffle: False drop_last: False - batch_size_per_card: 16 - num_workers: 8 + batch_size_per_card: 4 + num_workers: 2 Eval: dataset: @@ -125,4 +127,4 @@ Eval: shuffle: False drop_last: False batch_size_per_card: 1 # must be 1 - num_workers: 8 \ No newline at end of file + num_workers: 8 From ea019601a712ba99e24c2b4dcad1944c38a90f2b Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 31 Aug 2021 12:19:11 +0000 Subject: [PATCH 22/77] fix conflic in program --- tools/program.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/program.py b/tools/program.py index 2d3114f66d..d6d47d047b 100755 --- a/tools/program.py +++ b/tools/program.py @@ -402,11 +402,7 @@ def preprocess(is_train=False): alg = config['Architecture']['algorithm'] assert alg in [ 'EAST', 'DB', 'SAST', 'Rosetta', 'CRNN', 'STARNet', 'RARE', 'SRN', -<<<<<<< HEAD - 'CLS', 'PGNet', 'Distillation', 'TableAttn', 'SAR' -======= - 'CLS', 'PGNet', 'Distillation', 'NRTR', 'TableAttn' ->>>>>>> 63ed5fcab30801626ecf55a89f5dc9faf79a16d2 + 'CLS', 'PGNet', 'Distillation', 'NRTR', 'TableAttn', 'SAR' ] device = 'gpu:{}'.format(dist.ParallelEnv().dev_id) if use_gpu else 'cpu' From 5c26d2e8bc49b06ffbdfe2c2a987b092b97f8c39 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:46:07 +0000 Subject: [PATCH 23/77] add yml for lock seed --- tests/configs/det_mv3_db.yml | 125 +++++++++++++++++++++++++++++++++++ tests/configs/det_r50_db.yml | 124 ++++++++++++++++++++++++++++++++++ tests/ocr_det_params.txt | 2 +- 3 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 tests/configs/det_mv3_db.yml create mode 100644 tests/configs/det_r50_db.yml diff --git a/tests/configs/det_mv3_db.yml b/tests/configs/det_mv3_db.yml new file mode 100644 index 0000000000..0845687192 --- /dev/null +++ b/tests/configs/det_mv3_db.yml @@ -0,0 +1,125 @@ +Global: + use_gpu: false + epoch_num: 5 + log_smooth_window: 20 + print_batch_step: 1 + save_model_dir: ./output/db_mv3/ + save_epoch_step: 1200 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 400] + cal_metric_during_train: False + pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_en/img_10.jpg + save_res_path: ./output/det_db/predicts_db.txt + +Architecture: + model_type: det + algorithm: DB + Transform: + Backbone: + name: MobileNetV3 + scale: 0.5 + model_name: large + Neck: + name: DBFPN + out_channels: 256 + Head: + name: DBHead + k: 50 + +Loss: + name: DBLoss + balance_loss: true + main_loss_type: DiceLoss + alpha: 5 #5 + beta: 10 #10 + ohem_ratio: 3 + +Optimizer: + name: Adam #Momentum + #momentum: 0.9 + beta1: 0.9 + beta2: 0.999 + lr: + learning_rate: 0.001 + regularizer: + name: 'L2' + factor: 0 + +PostProcess: + name: DBPostProcess + thresh: 0.3 + box_thresh: 0.6 + max_candidates: 1000 + unclip_ratio: 1.5 + +Metric: + name: DetMetric + main_indicator: hmean + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/train_icdar2015_label.txt + ratio_list: [1.0] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label + - Resize: + # size: [640, 640] + - MakeBorderMap: + shrink_ratio: 0.4 + thresh_min: 0.3 + thresh_max: 0.7 + - MakeShrinkMap: + shrink_ratio: 0.4 + min_text_size: 8 + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 + num_workers: 0 + use_shared_memory: False + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/test_icdar2015_label.txt + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label + - DetResizeForTest: + image_shape: [736, 1280] + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'shape', 'polys', 'ignore_tags'] + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 # must be 1 + num_workers: 0 + use_shared_memory: False diff --git a/tests/configs/det_r50_db.yml b/tests/configs/det_r50_db.yml new file mode 100644 index 0000000000..f512de8081 --- /dev/null +++ b/tests/configs/det_r50_db.yml @@ -0,0 +1,124 @@ +Global: + use_gpu: false + epoch_num: 5 + log_smooth_window: 20 + print_batch_step: 1 + save_model_dir: ./output/db_mv3/ + save_epoch_step: 1200 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 400] + cal_metric_during_train: False + pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_en/img_10.jpg + save_res_path: ./output/det_db/predicts_db.txt + +Architecture: + model_type: det + algorithm: DB + Transform: + Backbone: + name: ResNet #MobileNetV3 + layers: 50 + Neck: + name: DBFPN + out_channels: 256 + Head: + name: DBHead + k: 50 + +Loss: + name: DBLoss + balance_loss: true + main_loss_type: DiceLoss + alpha: 5 #5 + beta: 10 #10 + ohem_ratio: 3 + +Optimizer: + name: Adam #Momentum + #momentum: 0.9 + beta1: 0.9 + beta2: 0.999 + lr: + learning_rate: 0.001 + regularizer: + name: 'L2' + factor: 0 + +PostProcess: + name: DBPostProcess + thresh: 0.3 + box_thresh: 0.6 + max_candidates: 1000 + unclip_ratio: 1.5 + +Metric: + name: DetMetric + main_indicator: hmean + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/train_icdar2015_label.txt + ratio_list: [1.0] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label + - Resize: + # size: [640, 640] + - MakeBorderMap: + shrink_ratio: 0.4 + thresh_min: 0.3 + thresh_max: 0.7 + - MakeShrinkMap: + shrink_ratio: 0.4 + min_text_size: 8 + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 + num_workers: 0 + use_shared_memory: False + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/test_icdar2015_label.txt + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label + - DetResizeForTest: + image_shape: [736, 1280] + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'shape', 'polys', 'ignore_tags'] + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 # must be 1 + num_workers: 0 + use_shared_memory: False diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 6aff66c6aa..c345ab1f76 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -13,7 +13,7 @@ train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ null:null ## trainer:norm_train|pact_train -norm_train:tools/train.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained +norm_train:tools/train.py -c tests/configs/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained pact_train:deploy/slim/quantization/quant.py -c configs/det/det_mv3_db.yml -o fpgm_train:null distill_train:null From 5f3558c99222ebc802a18df4e74d092fadb0589c Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:48:33 +0000 Subject: [PATCH 24/77] restore yml file --- configs/det/det_mv3_db.yml | 12 +-- configs/det/det_mv3_db_unittest.yml | 129 ++++++++++++++++++++++++++++ configs/det/det_r50_vd_db.yml | 14 +-- 3 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 configs/det/det_mv3_db_unittest.yml diff --git a/configs/det/det_mv3_db.yml b/configs/det/det_mv3_db.yml index b702ad04cc..fa71487149 100644 --- a/configs/det/det_mv3_db.yml +++ b/configs/det/det_mv3_db.yml @@ -76,12 +76,14 @@ Train: - { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } - { 'type': Resize, 'args': { 'size': [0.5, 3] } } - - Resize: + - EastRandomCropData: size: [640, 640] -# - EastRandomCropData: -# size: [640, 640] -# max_tries: 50 -# keep_ratio: true + max_tries: 50 + keep_ratio: true + - EastRandomCropData: + size: [640, 640] + max_tries: 50 + keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 diff --git a/configs/det/det_mv3_db_unittest.yml b/configs/det/det_mv3_db_unittest.yml new file mode 100644 index 0000000000..63c3b73add --- /dev/null +++ b/configs/det/det_mv3_db_unittest.yml @@ -0,0 +1,129 @@ +Global: + use_gpu: true + epoch_num: 5 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/db_mv3/ + save_epoch_step: 1200 + # evaluation is run every 2000 iterations + eval_batch_step: [0, 2000] + cal_metric_during_train: False + pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained + checkpoints: + save_inference_dir: + use_visualdl: False + infer_img: doc/imgs_en/img_10.jpg + save_res_path: ./output/det_db/predicts_db.txt + +Architecture: + model_type: det + algorithm: DB + Transform: + Backbone: + name: MobileNetV3 + scale: 0.5 + model_name: large + Neck: + name: DBFPN + out_channels: 256 + Head: + name: DBHead + k: 50 + +Loss: + name: DBLoss + balance_loss: true + main_loss_type: DiceLoss + alpha: 5 + beta: 10 + ohem_ratio: 3 + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.999 + lr: + learning_rate: 0.001 + regularizer: + name: 'L2' + factor: 0 + +PostProcess: + name: DBPostProcess + thresh: 0.3 + box_thresh: 0.6 + max_candidates: 1000 + unclip_ratio: 1.5 + +Metric: + name: DetMetric + main_indicator: hmean + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/train_icdar2015_label.txt + ratio_list: [1.0] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label +# - IaaAugment: +# augmenter_args: +# - { 'type': Fliplr, 'args': { 'p': 0.5 } } +# - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } +# - { 'type': Resize, 'args': { 'size': [0.5, 3] } } + - Resize: + size: [640, 640] + - MakeBorderMap: + shrink_ratio: 0.4 + thresh_min: 0.3 + thresh_max: 0.7 + - MakeShrinkMap: + shrink_ratio: 0.4 + min_text_size: 8 + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 + num_workers: 0 + use_shared_memory: False + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/icdar2015/text_localization/ + label_file_list: + - ./train_data/icdar2015/text_localization/test_icdar2015_label.txt + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - DetLabelEncode: # Class handling label + - DetResizeForTest: + image_shape: [736, 1280] + - NormalizeImage: + scale: 1./255. + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] + order: 'hwc' + - ToCHWImage: + - KeepKeys: + keep_keys: ['image', 'shape', 'polys', 'ignore_tags'] + loader: + shuffle: False + drop_last: False + batch_size_per_card: 1 # must be 1 + num_workers: 8 + use_shared_memory: False diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml index 4a6820dab5..e863e02e99 100644 --- a/configs/det/det_r50_vd_db.yml +++ b/configs/det/det_r50_vd_db.yml @@ -75,12 +75,14 @@ Train: - { 'type': Fliplr, 'args': { 'p': 0.5 } } - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } - { 'type': Resize, 'args': { 'size': [0.5, 3] } } - - Resize: + - EastRandomCropData: size: [640, 640] -# - EastRandomCropData: -# size: [640, 640] -# max_tries: 50 -# keep_ratio: true + max_tries: 50 + keep_ratio: true + - EastRandomCropData: + size: [640, 640] + max_tries: 50 + keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 @@ -97,7 +99,7 @@ Train: - KeepKeys: keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list loader: - shuffle: False + shuffle: True drop_last: False batch_size_per_card: 4 num_workers: 2 From f75efcc3ce57912e95c2c9c3f57341e4b7f90a08 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:50:19 +0000 Subject: [PATCH 25/77] rm configs/det/det_mv3_db_unittest.yml --- configs/det/det_mv3_db_unittest.yml | 129 ---------------------------- 1 file changed, 129 deletions(-) delete mode 100644 configs/det/det_mv3_db_unittest.yml diff --git a/configs/det/det_mv3_db_unittest.yml b/configs/det/det_mv3_db_unittest.yml deleted file mode 100644 index 63c3b73add..0000000000 --- a/configs/det/det_mv3_db_unittest.yml +++ /dev/null @@ -1,129 +0,0 @@ -Global: - use_gpu: true - epoch_num: 5 - log_smooth_window: 20 - print_batch_step: 10 - save_model_dir: ./output/db_mv3/ - save_epoch_step: 1200 - # evaluation is run every 2000 iterations - eval_batch_step: [0, 2000] - cal_metric_during_train: False - pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained - checkpoints: - save_inference_dir: - use_visualdl: False - infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt - -Architecture: - model_type: det - algorithm: DB - Transform: - Backbone: - name: MobileNetV3 - scale: 0.5 - model_name: large - Neck: - name: DBFPN - out_channels: 256 - Head: - name: DBHead - k: 50 - -Loss: - name: DBLoss - balance_loss: true - main_loss_type: DiceLoss - alpha: 5 - beta: 10 - ohem_ratio: 3 - -Optimizer: - name: Adam - beta1: 0.9 - beta2: 0.999 - lr: - learning_rate: 0.001 - regularizer: - name: 'L2' - factor: 0 - -PostProcess: - name: DBPostProcess - thresh: 0.3 - box_thresh: 0.6 - max_candidates: 1000 - unclip_ratio: 1.5 - -Metric: - name: DetMetric - main_indicator: hmean - -Train: - dataset: - name: SimpleDataSet - data_dir: ./train_data/icdar2015/text_localization/ - label_file_list: - - ./train_data/icdar2015/text_localization/train_icdar2015_label.txt - ratio_list: [1.0] - transforms: - - DecodeImage: # load image - img_mode: BGR - channel_first: False - - DetLabelEncode: # Class handling label -# - IaaAugment: -# augmenter_args: -# - { 'type': Fliplr, 'args': { 'p': 0.5 } } -# - { 'type': Affine, 'args': { 'rotate': [-10, 10] } } -# - { 'type': Resize, 'args': { 'size': [0.5, 3] } } - - Resize: - size: [640, 640] - - MakeBorderMap: - shrink_ratio: 0.4 - thresh_min: 0.3 - thresh_max: 0.7 - - MakeShrinkMap: - shrink_ratio: 0.4 - min_text_size: 8 - - NormalizeImage: - scale: 1./255. - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] - order: 'hwc' - - ToCHWImage: - - KeepKeys: - keep_keys: ['image', 'threshold_map', 'threshold_mask', 'shrink_map', 'shrink_mask'] # the order of the dataloader list - loader: - shuffle: False - drop_last: False - batch_size_per_card: 1 - num_workers: 0 - use_shared_memory: False - -Eval: - dataset: - name: SimpleDataSet - data_dir: ./train_data/icdar2015/text_localization/ - label_file_list: - - ./train_data/icdar2015/text_localization/test_icdar2015_label.txt - transforms: - - DecodeImage: # load image - img_mode: BGR - channel_first: False - - DetLabelEncode: # Class handling label - - DetResizeForTest: - image_shape: [736, 1280] - - NormalizeImage: - scale: 1./255. - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] - order: 'hwc' - - ToCHWImage: - - KeepKeys: - keep_keys: ['image', 'shape', 'polys', 'ignore_tags'] - loader: - shuffle: False - drop_last: False - batch_size_per_card: 1 # must be 1 - num_workers: 8 - use_shared_memory: False From 1b486757516b73903161ab7c3361cef724adb1d1 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:51:15 +0000 Subject: [PATCH 26/77] fix r50_db yml --- configs/det/det_r50_vd_db.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml index e863e02e99..9b43cfa798 100644 --- a/configs/det/det_r50_vd_db.yml +++ b/configs/det/det_r50_vd_db.yml @@ -79,10 +79,6 @@ Train: size: [640, 640] max_tries: 50 keep_ratio: true - - EastRandomCropData: - size: [640, 640] - max_tries: 50 - keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 From be8829167da4a69f287747641013b1c9237c5e93 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:53:29 +0000 Subject: [PATCH 27/77] fix r50_db yml --- configs/det/det_r50_vd_db.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml index 9b43cfa798..ab67786ece 100644 --- a/configs/det/det_r50_vd_db.yml +++ b/configs/det/det_r50_vd_db.yml @@ -97,8 +97,8 @@ Train: loader: shuffle: True drop_last: False - batch_size_per_card: 4 - num_workers: 2 + batch_size_per_card: 16 + num_workers: 4 Eval: dataset: From c3341000f1f0b14896b3cbcd64ddab46c1a7ba63 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:54:13 +0000 Subject: [PATCH 28/77] fix configs/det/det_mv3_db.yml --- configs/det/det_mv3_db.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configs/det/det_mv3_db.yml b/configs/det/det_mv3_db.yml index fa71487149..1fab509d12 100644 --- a/configs/det/det_mv3_db.yml +++ b/configs/det/det_mv3_db.yml @@ -80,10 +80,6 @@ Train: size: [640, 640] max_tries: 50 keep_ratio: true - - EastRandomCropData: - size: [640, 640] - max_tries: 50 - keep_ratio: true - MakeBorderMap: shrink_ratio: 0.4 thresh_min: 0.3 From e5d9ef00f290620e586be947cb024d5e380e838f Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 12:56:49 +0000 Subject: [PATCH 29/77] update yml used by ocr_det_params.txt --- tests/ocr_det_params.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 1e11b4a8be..8b9273f745 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -14,22 +14,22 @@ null:null ## trainer:norm_train|pact_train norm_train:tools/train.py -c tests/configs/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/MobileNetV3_large_x0_5_pretrained -pact_train:deploy/slim/quantization/quant.py -c configs/det/det_mv3_db.yml -o -fpgm_train:deploy/slim/prune/sensitivity_anal.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/det_mv3_db_v2.0_train/best_accuracy +pact_train:deploy/slim/quantization/quant.py -c tests/configs/det_mv3_db.yml -o +fpgm_train:deploy/slim/prune/sensitivity_anal.py -c tests/configs/det_mv3_db.yml -o Global.pretrained_model=./pretrain_models/det_mv3_db_v2.0_train/best_accuracy distill_train:null null:null null:null ## ===========================eval_params=========================== -eval:tools/eval.py -c configs/det/det_mv3_db.yml -o +eval:tools/eval.py -c tests/configs/det_mv3_db.yml -o null:null ## ===========================infer_params=========================== Global.save_inference_dir:./output/ Global.pretrained_model: -norm_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o -quant_export:deploy/slim/quantization/export_model.py -c configs/det/det_mv3_db.yml -o -fpgm_export:deploy/slim/prune/export_prune_model.py -c configs/det/det_mv3_db.yml -o +norm_export:tools/export_model.py -c tests/configs/det_mv3_db.yml -o +quant_export:deploy/slim/quantization/export_model.py -c tests/configs/det_mv3_db.yml -o +fpgm_export:deploy/slim/prune/export_prune_model.py -c tests/configs/det_mv3_db.yml -o distill_export:null export1:null export2:null From 5aa1ffccd02799f0307fe4a6042305dd8ce05fe8 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 31 Aug 2021 13:08:16 +0000 Subject: [PATCH 30/77] rename tests/configs/det_r50_db.yml --- tests/configs/{det_r50_db.yml => det_r50_vd_db.yml} | 0 tests/ocr_det_server_params.txt | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename tests/configs/{det_r50_db.yml => det_r50_vd_db.yml} (100%) diff --git a/tests/configs/det_r50_db.yml b/tests/configs/det_r50_vd_db.yml similarity index 100% rename from tests/configs/det_r50_db.yml rename to tests/configs/det_r50_vd_db.yml diff --git a/tests/ocr_det_server_params.txt b/tests/ocr_det_server_params.txt index 0835cfffa6..4a17fa6834 100644 --- a/tests/ocr_det_server_params.txt +++ b/tests/ocr_det_server_params.txt @@ -13,7 +13,7 @@ train_infer_img_dir:./train_data/icdar2015/text_localization/ch4_test_images/ null:null ## trainer:norm_train|pact_train -norm_train:tools/train.py -c configs/det/det_r50_vd_db.yml -o Global.pretrained_model="" +norm_train:tools/train.py -c tests/configs/det_r50_vd_db.yml -o Global.pretrained_model="" pact_train:null fpgm_train:null distill_train:null @@ -21,13 +21,13 @@ null:null null:null ## ===========================eval_params=========================== -eval:tools/eval.py -c configs/det/det_mv3_db.yml -o +eval:tools/eval.py -c tests/configs/det_r50_vd_db.yml -o null:null ## ===========================infer_params=========================== Global.save_inference_dir:./output/ Global.pretrained_model: -norm_export:tools/export_model.py -c configs/det/det_r50_vd_db.yml -o +norm_export:tools/export_model.py -c tests/configs/det_r50_vd_db.yml -o quant_export:null fpgm_export:null distill_export:null From 97987978cf721524422783449853970dc7821135 Mon Sep 17 00:00:00 2001 From: before31 Date: Tue, 31 Aug 2021 22:56:08 +0800 Subject: [PATCH 31/77] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E7=AB=AF=E5=88=B0?= =?UTF-8?q?=E7=AB=AF=E7=AE=97=E6=B3=95=E8=B0=83=E7=94=A8inference=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=97=B6=E4=B8=8E=E8=AE=AD=E7=BB=83=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E4=B8=8D=E4=B8=80=E8=87=B4=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E7=94=B1rgb3=E4=B8=AA=E9=80=9A=E9=81=93?= =?UTF-8?q?=E7=9A=84=E9=A1=BA=E5=BA=8F=E4=B8=8D=E4=B8=80=E8=87=B4=E5=BC=95?= =?UTF-8?q?=E8=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/infer/predict_e2e.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/infer/predict_e2e.py b/tools/infer/predict_e2e.py index 5029d60593..8ff279d743 100755 --- a/tools/infer/predict_e2e.py +++ b/tools/infer/predict_e2e.py @@ -141,6 +141,7 @@ if __name__ == "__main__": img, flag = check_and_read_gif(image_file) if not flag: img = cv2.imread(image_file) + img = img[:, :, ::-1] if img is None: logger.info("error in loading image:{}".format(image_file)) continue From a2bd540c90cf45243b0520d1bd974db587725918 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Wed, 1 Sep 2021 07:38:16 +0000 Subject: [PATCH 32/77] update test.sh for serving --- tests/prepare.sh | 5 +++-- tests/test.sh | 38 ++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index 828705c380..94367f4829 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -77,9 +77,10 @@ fi # prepare serving env python_name=$(func_parser_value "${lines[2]}") -${python_name} -m pip install install paddle-serving-server-gpu==0.6.1.post101 +wget https://paddle-serving.bj.bcebos.com/chain/paddle_serving_server_gpu-0.0.0.post101-py3-none-any.whl +${python_name} -m pip install install paddle_serving_server_gpu-0.0.0.post101-py3-none-any.whl ${python_name} -m pip install paddle_serving_client==0.6.1 -${python_name} -m pip install paddle-serving-app==0.6.1 +${python_name} -m pip install paddle-serving-app==0.6.3 wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar diff --git a/tests/test.sh b/tests/test.sh index ac2687d347..6c34d0797a 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -168,7 +168,7 @@ web_use_trt_key=$(func_parser_key "${lines[63]}") web_use_trt_list=$(func_parser_value "${lines[63]}") web_precision_key=$(func_parser_key "${lines[64]}") web_precision_list=$(func_parser_value "${lines[64]}") -pipline_py=$(func_parser_value "${lines[65]}") +pipeline_py=$(func_parser_value "${lines[65]}") LOG_PATH="./tests/output" @@ -259,6 +259,8 @@ function func_serving(){ eval $trans_model_cmd cd ${serving_dir_value} echo $PWD + unset https_proxy + unset http_proxy for use_gpu in ${web_use_gpu_list[*]}; do echo ${ues_gpu} if [ ${use_gpu} = "null" ]; then @@ -269,12 +271,18 @@ function func_serving(){ for threads in ${web_cpu_threads_list[*]}; do _save_log_path="${_log_path}/server_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_batchsize_1.log" set_cpu_threads=$(func_set_params "${web_cpu_threads_key}" "${threads}") - web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} &>log.txt &" - echo $web_service_cmd + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${web_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} &>${_save_log_path} &" eval $web_service_cmd - pipline_cmd="${python} ${pipline_py}" - echo $pipline_cmd - eval $pipline_cmd + sleep 2s + pipeline_cmd="${python} ${pipeline_py}" + eval $pipeline_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${pipeline_cmd}" "${status_log}" + PID=$! + kill $PID + sleep 2s + ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 done done elif [ ${use_gpu} = "0" ]; then @@ -286,18 +294,24 @@ function func_serving(){ if [[ ${precision} =~ "fp16" || ${precision} =~ "int8" ]] && [ ${use_trt} = "False" ]; then continue fi - if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [ ${_flag_quant} = "True" ]; then + if [[ ${use_trt} = "Falg_quantse" || ${precision} =~ "int8" ]]; then continue fi _save_log_path="${_log_path}/infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_1.log" set_tensorrt=$(func_set_params "${web_use_trt_key}" "${use_trt}") set_precision=$(func_set_params "${web_precision_key}" "${precision}") - web_service_cmd="${_python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${web_use_trt_key}=${set_tensorrt} ${set_precision} > ${_save_log_path} &>log.txt & " - echo $web_service_cmd + web_service_cmd="${python} ${web_service_py} ${web_use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} &>${_save_log_path} & " eval $web_service_cmd - pipline_cmd="${python} ${pipline_py}" - echo $pipline_cmd - eval $pipline_cmd + sleep 2s + pipeline_cmd="${python} ${pipeline_py}" + eval $pipeline_cmd + last_status=${PIPESTATUS[0]} + eval "cat ${_save_log_path}" + status_check $last_status "${pipeline_cmd}" "${status_log}" + PID=$! + kill $PID + sleep 2s + ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 done done else From 37cd4ed333acff9620f7fb0c4c003935fff2b154 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Sep 2021 07:18:13 +0000 Subject: [PATCH 33/77] delete dict90, update sar postprocess, update sar.yml --- configs/rec/rec_r31_sar.yml | 9 +-- ppocr/postprocess/rec_postprocess.py | 8 ++- ppocr/utils/dict90.txt | 90 ---------------------------- 3 files changed, 10 insertions(+), 97 deletions(-) delete mode 100644 ppocr/utils/dict90.txt diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index c19bcdee09..73d56f375e 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -15,7 +15,7 @@ Global: infer_img: # for data or label process character_dict_path: ppocr/utils/dict90.txt - character_type: ch + character_type: EN_symbol max_text_length: 30 infer_mode: False use_space_char: False @@ -47,6 +47,7 @@ Loss: PostProcess: name: SARLabelDecode + rm_symbol: True Metric: name: RecMetric @@ -56,8 +57,8 @@ Train: dataset: name: SimpleDataSet delimiter: ' ' - label_file_list: ['/paddle/data/concat_data/train_list.txt'] - data_dir: /paddle/data/concat_data/ + label_file_list: ['./train_data/train_list.txt'] + data_dir: ./train_data/ ratio_list: 1.0 transforms: - DecodeImage: # load image @@ -79,7 +80,7 @@ Train: Eval: dataset: name: LMDBDataSet - data_dir: /paddle/data/ocr_data/evaluation/ + data_dir: ./eval_data/evaluation/ transforms: - DecodeImage: # load image img_mode: BGR diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index 83d7b21540..2043928142 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -526,6 +526,7 @@ class SARLabelDecode(BaseRecLabelDecode): character_dict_path=None, character_type='ch', use_space_char=False, + rm_symbol=True, **kwargs): super(SARLabelDecode, self).__init__(character_dict_path, character_type, use_space_char) @@ -572,9 +573,10 @@ class SARLabelDecode(BaseRecLabelDecode): else: conf_list.append(1) text = ''.join(char_list) - comp = re.compile('[^A-Z^a-z^0-9^\u4e00-\u9fa5]') - text = text.lower() - text = comp.sub('', text) + if self.rm_symbol: + comp = re.compile('[^A-Z^a-z^0-9^\u4e00-\u9fa5]') + text = text.lower() + text = comp.sub('', text) result_list.append((text, np.mean(conf_list))) return result_list diff --git a/ppocr/utils/dict90.txt b/ppocr/utils/dict90.txt deleted file mode 100644 index a945ae9c52..0000000000 --- a/ppocr/utils/dict90.txt +++ /dev/null @@ -1,90 +0,0 @@ -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 -! -" -# -$ -% -& -' -( -) -* -+ -, -- -. -/ -: -; -< -= -> -? -@ -[ -\ -] -_ -` -~ \ No newline at end of file From e0e7cdb1f2ddde3bcb12a6c20d0e1f08d13b4f46 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Thu, 2 Sep 2021 07:22:21 +0000 Subject: [PATCH 34/77] fix typo --- tests/test.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/test.sh b/tests/test.sh index 1a19c37907..0aad08e21c 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -270,7 +270,6 @@ function func_inference(){ fi done } - function func_serving(){ IFS='|' _python=$1 @@ -339,6 +338,14 @@ function func_serving(){ kill $PID sleep 2s ps ux | grep -E 'web_service|pipeline' | awk '{print $2}' | xargs kill -s 9 + done + done + else + echo "Does not support hardware other than CPU and GPU Currently!" + fi + done +} + function func_cpp_inference(){ IFS='|' _script=$1 @@ -582,5 +589,3 @@ else done # done with: for autocast in ${autocast_list[*]}; do done # done with: for gpu in ${gpu_list[*]}; do fi # end if [ ${MODE} = "infer" ]; then - - From dc3bce76916b515870655a1e9150a91f01ac7649 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Sep 2021 07:28:30 +0000 Subject: [PATCH 35/77] update sar postprocess --- configs/rec/rec_r31_sar.yml | 2 +- ppocr/postprocess/rec_postprocess.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index 73d56f375e..7adb7136c5 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -19,6 +19,7 @@ Global: max_text_length: 30 infer_mode: False use_space_char: False + rm_symbol: True save_res_path: ./output/rec/predicts_sar.txt Optimizer: @@ -47,7 +48,6 @@ Loss: PostProcess: name: SARLabelDecode - rm_symbol: True Metric: name: RecMetric diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index 2043928142..f2c3f289b8 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -526,10 +526,10 @@ class SARLabelDecode(BaseRecLabelDecode): character_dict_path=None, character_type='ch', use_space_char=False, - rm_symbol=True, **kwargs): super(SARLabelDecode, self).__init__(character_dict_path, character_type, use_space_char) + self.rm_symbol = kwargs.get('rm_symbol', True) def add_special_char(self, dict_character): beg_end_str = "" From 073fad37ba1e0237b2d56bcfe54e32e7850b34c3 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Thu, 2 Sep 2021 07:38:08 +0000 Subject: [PATCH 36/77] update sar postprocess --- ppocr/postprocess/rec_postprocess.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index f2c3f289b8..2bc6064882 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -529,6 +529,7 @@ class SARLabelDecode(BaseRecLabelDecode): **kwargs): super(SARLabelDecode, self).__init__(character_dict_path, character_type, use_space_char) + self.rm_symbol = kwargs.get('rm_symbol', True) def add_special_char(self, dict_character): From 69fdbf812a5fdd4a7c65867930dc622dc3d432a1 Mon Sep 17 00:00:00 2001 From: Double_V Date: Thu, 2 Sep 2021 19:23:01 +0800 Subject: [PATCH 37/77] infer model TO train model --- tests/ocr_det_params.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 733de0ff45..3d75dc9ef6 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -34,7 +34,7 @@ distill_export:null export1:null export2:null ## -infer_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy +train_model:./inference/ch_ppocr_mobile_v2.0_det_train/best_accuracy infer_export:tools/export_model.py -c configs/det/det_mv3_db.yml -o infer_quant:False inference:tools/infer/predict_det.py From c245db5a5347e8d860f0a5e501cf0cfde45cd163 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Mon, 6 Sep 2021 09:39:42 +0000 Subject: [PATCH 38/77] refine opencv build --- tests/prepare.sh | 64 +++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index 5da74d949f..ae3ec5d101 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -85,40 +85,44 @@ if [ ${MODE} = "cpp_infer" ];then cd deploy/cpp_infer use_opencv=$(func_parser_value "${lines[52]}") if [ ${use_opencv} = "True" ]; then - echo "################### build opencv ###################" - rm -rf 3.4.7.tar.gz opencv-3.4.7/ - wget https://github.com/opencv/opencv/archive/3.4.7.tar.gz - tar -xf 3.4.7.tar.gz + if [ -d "opencv-3.4.7/opencv3/" ] && [ $(md5sum opencv-3.4.7.tar.gz | awk -F ' ' '{print $1}') = "faa2b5950f8bee3f03118e600c74746a" ];then + echo "################### build opencv skipped ###################" + else + echo "################### build opencv ###################" + rm -rf opencv-3.4.7.tar.gz opencv-3.4.7/ + wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/opencv-3.4.7.tar.gz + tar -xf opencv-3.4.7.tar.gz - cd opencv-3.4.7/ - install_path=$(pwd)/opencv-3.4.7/opencv3 + cd opencv-3.4.7/ + install_path=$(pwd)/opencv3 - rm -rf build - mkdir build - cd build + rm -rf build + mkdir build + cd build - cmake .. \ - -DCMAKE_INSTALL_PREFIX=${install_path} \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ - -DWITH_IPP=OFF \ - -DBUILD_IPP_IW=OFF \ - -DWITH_LAPACK=OFF \ - -DWITH_EIGEN=OFF \ - -DCMAKE_INSTALL_LIBDIR=lib64 \ - -DWITH_ZLIB=ON \ - -DBUILD_ZLIB=ON \ - -DWITH_JPEG=ON \ - -DBUILD_JPEG=ON \ - -DWITH_PNG=ON \ - -DBUILD_PNG=ON \ - -DWITH_TIFF=ON \ - -DBUILD_TIFF=ON + cmake .. \ + -DCMAKE_INSTALL_PREFIX=${install_path} \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DWITH_IPP=OFF \ + -DBUILD_IPP_IW=OFF \ + -DWITH_LAPACK=OFF \ + -DWITH_EIGEN=OFF \ + -DCMAKE_INSTALL_LIBDIR=lib64 \ + -DWITH_ZLIB=ON \ + -DBUILD_ZLIB=ON \ + -DWITH_JPEG=ON \ + -DBUILD_JPEG=ON \ + -DWITH_PNG=ON \ + -DBUILD_PNG=ON \ + -DWITH_TIFF=ON \ + -DBUILD_TIFF=ON - make -j - make install - cd ../ - echo "################### build opencv finished ###################" + make -j + make install + cd ../ + echo "################### build opencv finished ###################" + fi fi From 50fde82b91ea3fb38e764629be9de76b8043c399 Mon Sep 17 00:00:00 2001 From: DanielYang Date: Tue, 7 Sep 2021 08:59:13 +0800 Subject: [PATCH 39/77] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb3418d925..039b2f474d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ PaddleOCR aims to create multilingual, awesome, leading, and practical OCR tools **Recent updates** -- PaddleOCR R&D team would like to share the released tools with developers, at 20:15 pm on September 8th, [Live Address](https://live.bilibili.com/21689802). +- PaddleOCR R&D team would like to share the key points of PP-OCRv2, at 20:15 pm on September 8th, [Live Address](https://live.bilibili.com/21689802). - 2021.9.7 release PaddleOCR v2.3, [PP-OCRv2](#PP-OCRv2) is proposed. The inference speed of PP-OCRv2 is 220% higher than that of PP-OCR server in CPU device. The F-score of PP-OCRv2 is 7% higher than that of PP-OCR mobile. - 2021.8.3 released PaddleOCR v2.2, add a new structured documents analysis toolkit, i.e., [PP-Structure](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.2/ppstructure/README.md), support layout analysis and table recognition (One-key to export chart images to Excel files). - 2021.4.8 release end-to-end text recognition algorithm [PGNet](https://www.aaai.org/AAAI21Papers/AAAI-2885.WangP.pdf) which is published in AAAI 2021. Find tutorial [here](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.1/doc/doc_en/pgnet_en.md);release multi language recognition [models](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.1/doc/doc_en/multi_languages_en.md), support more than 80 languages recognition; especically, the performance of [English recognition model](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.1/doc/doc_en/models_list_en.md#English) is Optimized. From a83f9aef70993fe0388ac2116b246b704035d41b Mon Sep 17 00:00:00 2001 From: DanielYang Date: Tue, 7 Sep 2021 09:00:10 +0800 Subject: [PATCH 40/77] Update README_ch.md --- README_ch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_ch.md b/README_ch.md index 3a9c7567d4..88b6ed04a6 100755 --- a/README_ch.md +++ b/README_ch.md @@ -81,7 +81,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 | 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 | | ------------ | --------------- | ----------------|---- | ---------- | -------- | -| 中英文超轻量PP-OCRv2模型(11.6M) | ch_ppocrv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_ppocrv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| | 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | | 中英文通用PP-OCR server模型(143.4M) |ch_ppocr_server_v2.0_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | From 5fb116a0e68131a035e878a069b60a84207ed3a7 Mon Sep 17 00:00:00 2001 From: grasswolfs Date: Tue, 7 Sep 2021 10:01:06 +0800 Subject: [PATCH 41/77] test=documents_fix,test=release/2.3 --- README.md | 2 +- doc/doc_ch/environment.md | 33 +++++++++++++++++---------------- doc/doc_ch/quickstart.md | 7 ++++--- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 039b2f474d..ae5dd1334b 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ For a new language request, please refer to [Guideline for new language_requests [1] 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 (as shown in the green box above). The final results are an ultra-lightweight Chinese and English OCR model with an overall size of 3.5M and a 2.8M English digital OCR model. For more details, please refer to the PP-OCR technical article (https://arxiv.org/abs/2009.09941). -[2] On the basis of PP-OCR, PP-OCRv2 is further optimized in five aspects. The detection model adopts CML(Collaborative Mutual Learning) knowledge distillation strategy and CopyPaste data expansion strategy; The recognition model adopts LCNet lightweight backbone network, U-DML knowledge distillation strategy and enhanced CTC loss function improvement (as shown in the red box above), which further improves the inference speed and prediction effect. For more details, please refer to the technical report of PP-OCRv2 (arXiv link is coming soon). +[2] On the basis of PP-OCR, PP-OCRv2 is further optimized in five aspects. The detection model adopts CML(Collaborative Mutual Learning) knowledge distillation strategy and CopyPaste data expansion strategy. The recognition model adopts LCNet lightweight backbone network, U-DML knowledge distillation strategy and enhanced CTC loss function improvement (as shown in the red box above), which further improves the inference speed and prediction effect. For more details, please refer to the technical report of PP-OCRv2 (arXiv link is coming soon). diff --git a/doc/doc_ch/environment.md b/doc/doc_ch/environment.md index 8efc31983a..a550081003 100644 --- a/doc/doc_ch/environment.md +++ b/doc/doc_ch/environment.md @@ -1,4 +1,7 @@ # 运行环境准备 +Windows和Mac用户推荐使用Anaconda搭建Python环境,Linux用户建议使用docker搭建PyThon环境。 + +如果对于Python环境熟悉的用户可以直接跳到第2步安装PaddlePaddle。 * [1. Python环境搭建](#1) + [1.1 Windows](#1.1) @@ -63,9 +66,9 @@ ``` create environment - - - + + + 以上anaconda环境和python环境安装完毕 @@ -80,9 +83,9 @@ - 安装完Anaconda后,可以安装python环境,以及numpy等所需的工具包环境 - Anaconda下载: - 地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D - + anaconda download - + - 选择最下方的`Anaconda3-2021.05-MacOSX-x86_64.pkg`下载 - 下载完成后,双击.pkg文件进入图形界面 - 按默认设置即可,安装需要花费一段时间 @@ -177,7 +180,7 @@ Linux用户可选择Anaconda或Docker两种方式运行。如果你熟悉Docker - 说明:使用paddlepaddle需要先安装python环境,这里我们选择python集成环境Anaconda工具包 - Anaconda是1个常用的python包管理程序 - 安装完Anaconda后,可以安装python环境,以及numpy等所需的工具包环境 - + - **下载Anaconda**: - 下载地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D @@ -185,22 +188,22 @@ Linux用户可选择Anaconda或Docker两种方式运行。如果你熟悉Docker - 选择适合您操作系统的版本 - 可在终端输入`uname -m`查询系统所用的指令集 - + - 下载法1:本地下载,再将安装包传到linux服务器上 - + - 下载法2:直接使用linux命令行下载 - + ```shell # 首先安装wget sudo apt-get install wget # Ubuntu sudo yum install wget # CentOS ``` - + ```shell # 然后使用wget从清华源上下载 # 如要下载Anaconda3-2021.05-Linux-x86_64.sh,则下载命令如下: wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.05-Linux-x86_64.sh - + # 若您要下载其他版本,需要将最后1个/后的文件名改成您希望下载的版本 ``` @@ -210,7 +213,7 @@ Linux用户可选择Anaconda或Docker两种方式运行。如果你熟悉Docker - 若您下载的是其它版本,则将该命令的文件名替换为您下载的文件名 - 按照安装提示安装即可 - 查看许可时可输入q来退出 - + - **将conda加入环境变量** - 加入环境变量是为了让系统能识别conda命令,若您在安装时已将conda加入环境变量path,则可跳过本步 @@ -277,13 +280,13 @@ Linux用户可选择Anaconda或Docker两种方式运行。如果你熟悉Docker # 激活paddle_env环境 conda activate paddle_env ``` - + 以上anaconda环境和python环境安装完毕 #### 1.3.2 Docker环境配置 -**注意:第一次使用这个镜像,会自动下载该镜像,请耐心等待。** +**注意:第一次使用这个镜像,会自动下载该镜像,请耐心等待。您也可以访问[DockerHub](https://hub.docker.com/r/paddlepaddle/paddle/tags/)获取与您机器适配的镜像。** ```bash # 切换到工作目录下 @@ -297,8 +300,6 @@ sudo docker run --name ppocr -v $PWD:/paddle --network=host -it paddlepaddle/pad 如果使用CUDA10,请运行以下命令创建容器,设置docker容器共享内存shm-size为64G,建议设置32G以上 sudo nvidia-docker run --name ppocr -v $PWD:/paddle --shm-size=64G --network=host -it paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82 /bin/bash -您也可以访问[DockerHub](https://hub.docker.com/r/paddlepaddle/paddle/tags/)获取与您机器适配的镜像。 - # ctrl+P+Q可退出docker 容器,重新进入docker 容器使用如下命令 sudo docker container exec -it ppocr /bin/bash ``` diff --git a/doc/doc_ch/quickstart.md b/doc/doc_ch/quickstart.md index 74d7004b35..d66ed0bef8 100644 --- a/doc/doc_ch/quickstart.md +++ b/doc/doc_ch/quickstart.md @@ -2,7 +2,7 @@ - [PaddleOCR快速开始](#paddleocr) - + + [1. 安装PaddleOCR whl包](#1) * [2. 便捷使用](#2) + [2.1 命令行使用](#21) @@ -166,7 +166,7 @@ paddleocr --image_dir=./table/1.png --type=structure ``` /output/table/1/ - └─ res.txt + └─ res.txt └─ [454, 360, 824, 658].xlsx 表格识别结果 └─ [16, 2, 828, 305].jpg 被裁剪出的图片区域 └─ [17, 361, 404, 711].xlsx 表格识别结果 @@ -183,7 +183,7 @@ paddleocr --image_dir=./table/1.png --type=structure 大部分参数和paddleocr whl包保持一致,见 [whl包文档](./whl.md) - + ### 2.2 Python脚本使用 @@ -232,6 +232,7 @@ im_show.save('result.jpg') + #### 2.2.2 版面分析 ```python From 62cd82ea1347da3d2ce869d6f3b3520bb0f54d80 Mon Sep 17 00:00:00 2001 From: Leif <4603009@qq.com> Date: Tue, 7 Sep 2021 11:06:02 +0800 Subject: [PATCH 42/77] Divide PP-OCR model inference and other model inference Divide PP-OCR model inference and other model inference --- README.md | 4 +-- README_ch.md | 4 +-- doc/doc_ch/models_and_config.md | 2 +- doc/doc_ch/quickstart.md | 2 +- doc/doc_ch/recognition.md | 40 +++++++++++++++++++++++++++--- doc/doc_en/inference_ppocr_en.md | 26 +++++++++---------- doc/doc_en/models_and_config_en.md | 8 ++++++ doc/doc_en/quickstart_en.md | 2 +- doc/doc_en/recognition_en.md | 39 +++++++++++++++++++++++++++++ 9 files changed, 104 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 039b2f474d..3fab7134d7 100644 --- a/README.md +++ b/README.md @@ -103,13 +103,12 @@ For a new language request, please refer to [Guideline for new language_requests - [PP-OCR Model and Configuration](./doc/doc_en/models_and_config_en.md) - [PP-OCR Model Download](./doc/doc_en/models_list_en.md) - [Yml Configuration](./doc/doc_en/config_en.md) - - [Python Inference](./doc/doc_en/inference_en.md) + - [Python Inference for PP-OCR Model Library](./doc/doc_en/inference_ppocr_en.md) - [PP-OCR Training](./doc/doc_en/training_en.md) - [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) - Inference and Deployment - - [Python Inference](./doc/doc_en/inference_en.md) - [C++ Inference](./deploy/cpp_infer/readme_en.md) - [Serving](./deploy/pdserving/README.md) - [Mobile](./deploy/lite/readme_en.md) @@ -120,6 +119,7 @@ For a new language request, please refer to [Guideline for new language_requests - Academic Circles - [Two-stage Algorithm](./doc/doc_en/algorithm_overview_en.md) - [PGNet Algorithm](./doc/doc_en/algorithm_overview_en.md) + - [Python Inference](./doc/doc_en/inference_en.md) - Data Annotation and Synthesis - [Semi-automatic Annotation Tool: PPOCRLabel](./PPOCRLabel/README.md) - [Data Synthesis Tool: Style-Text](./StyleText/README.md) diff --git a/README_ch.md b/README_ch.md index 88b6ed04a6..c5bd0c0d9f 100755 --- a/README_ch.md +++ b/README_ch.md @@ -95,13 +95,12 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 - [PP-OCR模型与配置文件](./doc/doc_ch/models_and_config.md) - [PP-OCR模型下载](./doc/doc_ch/models_list.md) - [配置文件内容与生成](./doc/doc_ch/config.md) - - [模型库快速使用](./doc/doc_ch/inference.md) + - [PP-OCR模型库快速推理](./doc/doc_ch/inference_ppocr.md) - [PP-OCR模型训练](./doc/doc_ch/training.md) - [文本检测](./doc/doc_ch/detection.md) - [文本识别](./doc/doc_ch/recognition.md) - [方向分类器](./doc/doc_ch/angle_class.md) - PP-OCR模型推理部署 - - [基于Python脚本预测引擎推理](./doc/doc_ch/inference.md) - [基于C++预测引擎推理](./deploy/cpp_infer/readme.md) - [服务化部署](./deploy/pdserving/README_CN.md) - [端侧部署](./deploy/lite/readme.md) @@ -117,6 +116,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 - OCR学术圈 - [两阶段模型介绍与下载](./doc/doc_ch/algorithm_overview.md) - [端到端PGNet算法](./doc/doc_ch/pgnet.md) + - [基于Python脚本预测引擎推理](./doc/doc_ch/inference.md) - 数据集 - [通用中英文OCR数据集](./doc/doc_ch/datasets.md) - [手写中文OCR数据集](./doc/doc_ch/handwritten_datasets.md) diff --git a/doc/doc_ch/models_and_config.md b/doc/doc_ch/models_and_config.md index cc42594723..89afc89a99 100644 --- a/doc/doc_ch/models_and_config.md +++ b/doc/doc_ch/models_and_config.md @@ -2,7 +2,7 @@ # PP-OCR模型与配置文件 PP-OCR模型与配置文件一章主要补充一些OCR模型的基本概念、配置文件的内容与作用以便对模型后续的参数调整和训练中拥有更好的体验。 -本节包含三个部分,首先在[PP-OCR模型下载](./models_list.md)中解释PP-OCR模型的类型概念,并提供所有模型的下载链接。然后在[配置文件内容与生成](./config.md)中详细说明调整PP-OCR模型所需的参数。最后的[模型库快速使用](./inference.md)是对第一节PP-OCR模型库使用方法的介绍,可以通过Python推理引擎快速利用丰富的模型库模型获得测试结果。 +本章包含三个部分,首先在[PP-OCR模型下载](./models_list.md)中解释PP-OCR模型的类型概念,并提供所有模型的下载链接。然后在[配置文件内容与生成](./config.md)中详细说明调整PP-OCR模型所需的参数。最后的[模型库快速使用](./inference_ppocr.md)是对第一节PP-OCR模型库使用方法的介绍,可以通过Python推理引擎快速利用丰富的模型库模型获得测试结果。 ------ diff --git a/doc/doc_ch/quickstart.md b/doc/doc_ch/quickstart.md index 74d7004b35..86e99aa06e 100644 --- a/doc/doc_ch/quickstart.md +++ b/doc/doc_ch/quickstart.md @@ -90,7 +90,7 @@ cd /path/to/ppocr_img ``` -更多whl包使用可参考[whl包文档](./whl.md) +如需使用2.0模型,请指定参数`--version 2.0`,paddleocr默认使用2.1模型。更多whl包使用可参考[whl包文档](./whl.md) diff --git a/doc/doc_ch/recognition.md b/doc/doc_ch/recognition.md index cd1a64bd7b..d57d6bb152 100644 --- a/doc/doc_ch/recognition.md +++ b/doc/doc_ch/recognition.md @@ -7,15 +7,13 @@ - [1.2 数据下载](#数据下载) - [1.3 字典](#字典) - [1.4 支持空格](#支持空格) - - [2 启动训练](#启动训练) - [2.1 数据增强](#数据增强) - [2.2 通用模型训练](#通用模型训练) - [2.3 多语言模型训练](#多语言模型训练) - - [3 评估](#评估) - - [4 预测](#预测) +- [5 转Inference模型测试](#Inference) @@ -424,3 +422,39 @@ python3 tools/infer_rec.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v infer_img: doc/imgs_words/ch/word_1.jpg result: ('韩国小馆', 0.997218) ``` + + + +## 5. 转Inference模型测试 + +识别模型转inference模型与检测的方式相同,如下: + +``` +# -c 后面设置训练算法的yml配置文件 +# -o 配置可选参数 +# Global.pretrained_model 参数设置待转换的训练模型地址,不用添加文件后缀 .pdmodel,.pdopt或.pdparams。 +# 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.pretrained_model=./ch_lite/ch_ppocr_mobile_v2.0_rec_train/best_accuracy Global.save_inference_dir=./inference/rec_crnn/ +``` + +**注意:**如果您是在自己的数据集上训练的模型,并且调整了中文字符的字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。 + +转换成功后,在目录下有三个文件: + +``` +/inference/rec_crnn/ + ├── inference.pdiparams # 识别inference模型的参数文件 + ├── inference.pdiparams.info # 识别inference模型的参数信息,可忽略 + └── inference.pdmodel # 识别inference模型的program文件 +``` + +- 自定义模型推理 + + 如果训练时修改了文本的字典,在使用inference模型预测时,需要通过`--rec_char_dict_path`指定使用的字典路径,并且设置 `rec_char_type=ch` + + ``` + python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./your inference model" --rec_image_shape="3, 32, 100" --rec_char_type="ch" --rec_char_dict_path="your text dict path" + ``` + + diff --git a/doc/doc_en/inference_ppocr_en.md b/doc/doc_en/inference_ppocr_en.md index 5442d0c578..fa3b1c8871 100755 --- a/doc/doc_en/inference_ppocr_en.md +++ b/doc/doc_en/inference_ppocr_en.md @@ -1,22 +1,22 @@ -# Reasoning based on Python prediction engine +# Python Inference for PP-OCR Model Library This article introduces the use of the Python inference engine for the PP-OCR model library. The content is in order of text detection, text recognition, direction classifier and the prediction method of the three in series on the CPU and GPU. -- [TEXT DETECTION MODEL INFERENCE](#DETECTION_MODEL_INFERENCE) +- [Text Detection Model Inference](#DETECTION_MODEL_INFERENCE) -- [TEXT RECOGNITION MODEL INFERENCE](#RECOGNITION_MODEL_INFERENCE) - - [1. LIGHTWEIGHT CHINESE MODEL](#LIGHTWEIGHT_RECOGNITION) - - [2. MULTILINGUAL MODEL INFERENCE](MULTILINGUAL_MODEL_INFERENCE) +- [Text Recognition Model Inference](#RECOGNITION_MODEL_INFERENCE) + - [1. Lightweight Chinese Recognition Model Inference](#LIGHTWEIGHT_RECOGNITION) + - [2. Multilingaul Model Inference](#MULTILINGUAL_MODEL_INFERENCE) -- [ANGLE CLASSIFICATION MODEL INFERENCE](#ANGLE_CLASS_MODEL_INFERENCE) +- [Angle Classification Model Inference](#ANGLE_CLASS_MODEL_INFERENCE) -- [TEXT DETECTION ANGLE CLASSIFICATION AND RECOGNITION INFERENCE CONCATENATION](#CONCATENATION) +- [Text Detection Angle Classification and Recognition Inference Concatenation](#CONCATENATION) -## TEXT DETECTION MODEL INFERENCE +## Text Detection Model Inference The default configuration is based on the inference setting of the DB text detection model. For lightweight Chinese detection model inference, you can execute the following commands: @@ -52,11 +52,11 @@ python3 tools/infer/predict_det.py --image_dir="./doc/imgs/1.jpg" --det_model_di -## TEXT RECOGNITION MODEL INFERENCE +## Text Recognition Model Inference -### 1. LIGHTWEIGHT CHINESE TEXT RECOGNITION MODEL REFERENCE +### 1. Lightweight Chinese Recognition Model Inference For lightweight Chinese recognition model inference, you can execute the following commands: @@ -77,7 +77,7 @@ Predicts of ./doc/imgs_words_en/word_10.png:('PAIN', 0.9897658) -### 2. MULTILINGAUL MODEL INFERENCE +### 2. 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/fonts` path, such as Korean recognition: @@ -94,7 +94,7 @@ Predicts of ./doc/imgs_words/korean/1.jpg:('바탕으로', 0.9948904) -## ANGLE CLASSIFICATION MODEL INFERENCE +## Angle Classification Model Inference For angle classification model inference, you can execute the following commands: @@ -114,7 +114,7 @@ After executing the command, the prediction results (classification angle and sc ``` -## TEXT DETECTION ANGLE CLASSIFICATION AND RECOGNITION INFERENCE CONCATENATION +## Text Detection Angle Classification and Recognition Inference Concatenation When performing prediction, you need to specify the path of a single image or a folder of images through the parameter `image_dir`, the parameter `det_model_dir` specifies the path to detect the inference model, the parameter `cls_model_dir` specifies the path to angle classification inference model and the parameter `rec_model_dir` specifies the path to identify the inference model. The parameter `use_angle_cls` is used to control whether to enable the angle classification model. The parameter `use_mp` specifies whether to use multi-process to infer `total_process_num` specifies process number when using multi-process. The parameter . The visualized recognition results are saved to the `./inference_results` folder by default. diff --git a/doc/doc_en/models_and_config_en.md b/doc/doc_en/models_and_config_en.md index f80c00715f..414d844d63 100644 --- a/doc/doc_en/models_and_config_en.md +++ b/doc/doc_en/models_and_config_en.md @@ -1,4 +1,12 @@ # PP-OCR Model and Configuration +The chapter on PP-OCR model and configuration file mainly adds some basic concepts of OCR model and the content and role of configuration file to have a better experience in the subsequent parameter adjustment and training of the model. + +This chapter contains three parts. Firstly, [PP-OCR Model Download](. /models_list_en.md) explains the concept of PP-OCR model types and provides links to download all models. Then in [Yml Configuration](. /config_en.md) details the parameters needed to fine-tune the PP-OCR models. The final [Python Inference for PP-OCR Model Library](. /inference_ppocr_en.md) is an introduction to the use of the PP-OCR model library in the first section, which can quickly utilize the rich model library models to obtain test results through the Python inference engine. + +------ + +Let's first understand some basic concepts. + - [INTRODUCTION ABOUT OCR](#introduction-about-ocr) * [BASIC CONCEPTS OF OCR DETECTION MODEL](#basic-concepts-of-ocr-detection-model) * [Basic concepts of OCR recognition model](#basic-concepts-of-ocr-recognition-model) diff --git a/doc/doc_en/quickstart_en.md b/doc/doc_en/quickstart_en.md index 19d6f327a6..c4fb506819 100644 --- a/doc/doc_en/quickstart_en.md +++ b/doc/doc_en/quickstart_en.md @@ -95,7 +95,7 @@ If you do not use the provided test image, you can replace the following `--imag ['PAIN', 0.990372] ``` -More whl package usage can be found in [whl package](./whl_en.md) +If you need to use the 2.0 model, please specify the parameter `--version 2.0`, paddleocr uses the 2.1 model by default. More whl package usage can be found in [whl package](./whl_en.md) #### 2.1.2 Multi-language Model diff --git a/doc/doc_en/recognition_en.md b/doc/doc_en/recognition_en.md index 21233c80a2..7ee0cb5fc0 100644 --- a/doc/doc_en/recognition_en.md +++ b/doc/doc_en/recognition_en.md @@ -15,6 +15,7 @@ - [4 PREDICTION](#PREDICTION) - [4.1 Training engine prediction](#Training_engine_prediction) +- [5 CONVERT TO INFERENCE MODEL](#Inference) ## 1 DATA PREPARATION @@ -361,6 +362,7 @@ Eval: ``` + ## 3 EVALUATION The evaluation dataset can be set by modifying the `Eval.dataset.label_file_list` field in the `configs/rec/rec_icdar15_train.yml` file. @@ -432,3 +434,40 @@ Get the prediction result of the input image: infer_img: doc/imgs_words/ch/word_1.jpg result: ('韩国小馆', 0.997218) ``` + + + +## 5 CONVERT TO INFERENCE MODEL + +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.pretrained_model 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. + +python3 tools/export_model.py -c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml -o Global.pretrained_model=./ch_lite/ch_ppocr_mobile_v2.0_rec_train/best_accuracy 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. + +After the conversion is successful, there are three files in the model save directory: + +``` +inference/det_db/ + ├── 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 +``` + +- Text recognition model Inference using custom characters dictionary + + If the text dictionary is modified during training, when using the inference model to predict, you need to specify the dictionary path used by `--rec_char_dict_path`, and set `rec_char_type=ch` + + ``` + python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./your inference model" --rec_image_shape="3, 32, 100" --rec_char_type="ch" --rec_char_dict_path="your text dict path" + ``` + + + From d9a7357967ea39953419a483b89f8d204ced6e86 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 11:27:56 +0800 Subject: [PATCH 43/77] update icdar2015 download --- doc/{ => datasets}/ic15_location_download.png | Bin doc/doc_ch/detection.md | 7 ++++--- doc/doc_en/detection_en.md | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) rename doc/{ => datasets}/ic15_location_download.png (100%) diff --git a/doc/ic15_location_download.png b/doc/datasets/ic15_location_download.png similarity index 100% rename from doc/ic15_location_download.png rename to doc/datasets/ic15_location_download.png diff --git a/doc/doc_ch/detection.md b/doc/doc_ch/detection.md index 57bfdc01e2..88cb197d5a 100644 --- a/doc/doc_ch/detection.md +++ b/doc/doc_ch/detection.md @@ -19,15 +19,16 @@ ## 1.1 数据准备 -icdar2015数据集可以从[官网](https://rrc.cvc.uab.es/?ch=4&com=downloads)下载到,首次下载需注册。 +icdar2015 TextLocalization数据集是文本检测的数据集,包含1000张训练图像和500张测试图像。 +icdar2015数据集可以从[官网](https://rrc.cvc.uab.es/?ch=4&com=downloads)下载到,首次下载需注册。 注册完成登陆后,下载下图中红色框标出的部分,其中, `Training Set Images`下载的内容保存为`icdar_c4_train_imgs`文件夹下,`Test Set Images` 下载的内容保存为`ch4_test_images`文件夹下

- +

-将下载到的数据集解压到工作目录下,假设解压在 PaddleOCR/train_data/ 下。另外,PaddleOCR将零散的标注文件整理成单独的标注文件 +将下载到的数据集解压到工作目录下,假设解压在 PaddleOCR/train_data/下。另外,PaddleOCR将零散的标注文件整理成单独的标注文件 ,您可以通过wget的方式进行下载。 ```shell # 在PaddleOCR路径下 diff --git a/doc/doc_en/detection_en.md b/doc/doc_en/detection_en.md index 8f12d42fe7..03b88179ba 100644 --- a/doc/doc_en/detection_en.md +++ b/doc/doc_en/detection_en.md @@ -18,13 +18,14 @@ This section uses the icdar2015 dataset as an example to introduce the training, evaluation, and testing of the detection model in PaddleOCR. ## 1.1 DATA PREPARATION -The icdar2015 dataset can be obtained from [official website](https://rrc.cvc.uab.es/?ch=4&com=downloads). Registration is required for downloading. + +The icdar2015 dataset contains train set which has 1000 images obtained with wearable cameras and test set which has 500 images obtained with wearable cameras. The icdar2015 can be obtained from [official website](https://rrc.cvc.uab.es/?ch=4&com=downloads). Registration is required for downloading. After registering and logging in, download the part marked in the red box in the figure below. And, the content downloaded by `Training Set Images` should be saved as the folder `icdar_c4_train_imgs`, and the content downloaded by `Test Set Images` is saved as the folder `ch4_test_images`

- +

Decompress the downloaded dataset to the working directory, assuming it is decompressed under PaddleOCR/train_data/. In addition, PaddleOCR organizes many scattered annotation files into two separate annotation files for train and test respectively, which can be downloaded by wget: From df4a2f6a7ee5efbf48a36b42a70c89511fdb4ac6 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 03:33:02 +0000 Subject: [PATCH 44/77] update rec_sar_head --- ppocr/losses/rec_sar_loss.py | 2 +- ppocr/modeling/heads/rec_sar_head.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ppocr/losses/rec_sar_loss.py b/ppocr/losses/rec_sar_loss.py index 1afb21fe8a..9e1c6495fb 100644 --- a/ppocr/losses/rec_sar_loss.py +++ b/ppocr/losses/rec_sar_loss.py @@ -9,7 +9,7 @@ from paddle import nn class SARLoss(nn.Layer): def __init__(self, **kwargs): super(SARLoss, self).__init__() - self.loss_func = paddle.nn.loss.CrossEntropyLoss(reduction="mean", ignore_index=92) + self.loss_func = paddle.nn.loss.CrossEntropyLoss(reduction="mean", ignore_index=96) def forward(self, predicts, batch): predict = predicts[:, :-1, :] # ignore last index of outputs to be in same seq_len with targets diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py index fb37b8cef2..98b00ed096 100644 --- a/ppocr/modeling/heads/rec_sar_head.py +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -118,8 +118,7 @@ class BaseDecoder(nn.Layer): class ParallelSARDecoder(BaseDecoder): """ Args: - num_classes (int): Output class number. - channels (list[int]): Network layer channels. + out_channels (int): Output class number. enc_bi_rnn (bool): If True, use bidirectional RNN in encoder. dec_bi_rnn (bool): If True, use bidirectional RNN in decoder. dec_drop_rnn (float): Dropout of RNN layer in decoder. @@ -137,7 +136,7 @@ class ParallelSARDecoder(BaseDecoder): """ def __init__(self, - num_classes=93, # 90 + unknown + start + padding + out_channels, # 90 + unknown + start + padding enc_bi_rnn=False, dec_bi_rnn=False, dec_drop_rnn=0.0, @@ -148,8 +147,6 @@ class ParallelSARDecoder(BaseDecoder): pred_dropout=0.1, max_text_length=30, mask=True, - start_idx=91, - padding_idx=92, # 92 pred_concat=True, **kwargs): super().__init__() @@ -157,7 +154,8 @@ class ParallelSARDecoder(BaseDecoder): self.num_classes = num_classes self.enc_bi_rnn = enc_bi_rnn self.d_k = d_k - self.start_idx = start_idx + self.start_idx = out_channels - 2 + self.padding_idx = out_channels - 1 self.max_seq_len = max_text_length self.mask = mask self.pred_concat = pred_concat @@ -191,7 +189,7 @@ class ParallelSARDecoder(BaseDecoder): # Decoder input embedding self.embedding = nn.Embedding( - self.num_classes, encoder_rnn_out_size, padding_idx=padding_idx) + self.num_classes, encoder_rnn_out_size, padding_idx=self.padding_idx) # Prediction layer self.pred_dropout = nn.Dropout(pred_dropout) @@ -330,6 +328,7 @@ class ParallelSARDecoder(BaseDecoder): class SARHead(nn.Layer): def __init__(self, + out_channels, enc_bi_rnn=False, enc_drop_rnn=0.1, enc_gru=False, @@ -351,7 +350,8 @@ class SARHead(nn.Layer): # decoder module self.decoder = ParallelSARDecoder( - enc_bi_rnn=enc_bi_rnn, + out_channels=out_channels, + enc_bi_rnn=enc_bi_rnn, dec_bi_rnn=dec_bi_rnn, dec_drop_rnn=dec_drop_rnn, dec_gru=dec_gru, @@ -375,4 +375,4 @@ class SARHead(nn.Layer): # (bsz, seq_len, num_classes) return final_out - \ No newline at end of file + From 46fffbf12f05600a85852c62be97cbbd1087c61a Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 11:35:30 +0800 Subject: [PATCH 45/77] add icdar2015 download --- doc/doc_ch/detection.md | 2 +- doc/doc_en/detection_en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doc_ch/detection.md b/doc/doc_ch/detection.md index 88cb197d5a..66295b2525 100644 --- a/doc/doc_ch/detection.md +++ b/doc/doc_ch/detection.md @@ -25,7 +25,7 @@ icdar2015数据集可以从[官网](https://rrc.cvc.uab.es/?ch=4&com=downloads) 注册完成登陆后,下载下图中红色框标出的部分,其中, `Training Set Images`下载的内容保存为`icdar_c4_train_imgs`文件夹下,`Test Set Images` 下载的内容保存为`ch4_test_images`文件夹下

- +

将下载到的数据集解压到工作目录下,假设解压在 PaddleOCR/train_data/下。另外,PaddleOCR将零散的标注文件整理成单独的标注文件 diff --git a/doc/doc_en/detection_en.md b/doc/doc_en/detection_en.md index 03b88179ba..d3f6f3da10 100644 --- a/doc/doc_en/detection_en.md +++ b/doc/doc_en/detection_en.md @@ -25,7 +25,7 @@ The icdar2015 dataset contains train set which has 1000 images obtained with wea After registering and logging in, download the part marked in the red box in the figure below. And, the content downloaded by `Training Set Images` should be saved as the folder `icdar_c4_train_imgs`, and the content downloaded by `Test Set Images` is saved as the folder `ch4_test_images`

- +

Decompress the downloaded dataset to the working directory, assuming it is decompressed under PaddleOCR/train_data/. In addition, PaddleOCR organizes many scattered annotation files into two separate annotation files for train and test respectively, which can be downloaded by wget: From cb40965dce04f1c49cd55bcf2b2ebc1b9b1305d9 Mon Sep 17 00:00:00 2001 From: DanielYang Date: Tue, 7 Sep 2021 11:37:28 +0800 Subject: [PATCH 46/77] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d10f86e9..7af7fdc8d2 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ 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 PP-OCRv2 model(11.6M) | ch_ppocrv2_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| +| Chinese and English ultra-lightweight PP-OCRv2 model(11.6M) | ch_ppocr_mobile_v2.1_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| | Chinese and English ultra-lightweight PP-OCR model (9.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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 PP-OCR model (143.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_traingit.tar) |[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) | From 0a8ca67a0c4a4ed468e82a575cc64ce73f21e068 Mon Sep 17 00:00:00 2001 From: DanielYang Date: Tue, 7 Sep 2021 11:37:56 +0800 Subject: [PATCH 47/77] Update README_ch.md --- README_ch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_ch.md b/README_ch.md index c5bd0c0d9f..ccc67ab304 100755 --- a/README_ch.md +++ b/README_ch.md @@ -81,7 +81,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 | 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 | | ------------ | --------------- | ----------------|---- | ---------- | -------- | -| 中英文超轻量PP-OCRv2模型(13.0M) | ch_ppocrv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_ppocr_mobile_v2.1_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| | 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | | 中英文通用PP-OCR server模型(143.4M) |ch_ppocr_server_v2.0_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | From 8123688a0941be22f5c9868c882d8c40e2472321 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 03:38:34 +0000 Subject: [PATCH 48/77] update rec_sar_head --- ppocr/modeling/heads/rec_sar_head.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py index 98b00ed096..ba0aa8ebe5 100644 --- a/ppocr/modeling/heads/rec_sar_head.py +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -151,11 +151,11 @@ class ParallelSARDecoder(BaseDecoder): **kwargs): super().__init__() - self.num_classes = num_classes + self.num_classes = out_channels self.enc_bi_rnn = enc_bi_rnn self.d_k = d_k self.start_idx = out_channels - 2 - self.padding_idx = out_channels - 1 + self.padding_idx = out_channels - 1 self.max_seq_len = max_text_length self.mask = mask self.pred_concat = pred_concat From 1c5d4489bcb507cace86e9a2de7510941759405b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 13:41:11 +0800 Subject: [PATCH 49/77] update PP-OCRv2 --- README.md | 2 +- README_ch.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7af7fdc8d2..34af2d7fa3 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ 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 PP-OCRv2 model(11.6M) | ch_ppocr_mobile_v2.1_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| +| Chinese and English ultra-lightweight PP-OCRv2 model(11.6M) | ch_PP-OCRv2_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar)| | Chinese and English ultra-lightweight PP-OCR model (9.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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 PP-OCR model (143.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_traingit.tar) |[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) | diff --git a/README_ch.md b/README_ch.md index ccc67ab304..88dfc63b36 100755 --- a/README_ch.md +++ b/README_ch.md @@ -81,7 +81,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 | 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 | | ------------ | --------------- | ----------------|---- | ---------- | -------- | -| 中英文超轻量PP-OCRv2模型(13.0M) | ch_ppocr_mobile_v2.1_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar)| +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar)| | 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | | 中英文通用PP-OCR server模型(143.4M) |ch_ppocr_server_v2.0_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | From 4383b7d8f38503b37a48bc0d337a232dddc80f97 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 13:46:20 +0800 Subject: [PATCH 50/77] update PP-OCRv2 --- .../det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml | 2 +- doc/doc_ch/models_list.md | 12 ++++++------ doc/doc_en/models_list_en.md | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml b/configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml index c8962ffafe..0f08909add 100644 --- a/configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml +++ b/configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml @@ -8,7 +8,7 @@ Global: # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] cal_metric_during_train: False - pretrained_model: ./pretrain_models/ch_ppocr_mobile_v2.1_det_distill_train/best_accuracy + pretrained_model: ./pretrain_models/ch_PP-OCRv2_det_distill_train/best_accuracy checkpoints: save_inference_dir: use_visualdl: False diff --git a/doc/doc_ch/models_list.md b/doc/doc_ch/models_list.md index 59a36b578e..38be8e1f0c 100644 --- a/doc/doc_ch/models_list.md +++ b/doc/doc_ch/models_list.md @@ -33,8 +33,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_ppocr_mobile_slim_v2.1_det|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_slim_quant_infer.tar)| -|ch_ppocr_mobile_v2.1_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|slim裁剪版超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)| 2.6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[推理模型](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)| |ch_ppocr_server_v2.0_det|通用模型,支持中英文、多语种文本检测,比超轻量模型更大,但效果更好|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[推理模型](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)| @@ -48,8 +48,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_ppocr_mobile_slim_v2.1_rec|slim量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_quant_train.tar) | -|ch_ppocr_mobile_v2.1_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|slim量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|slim裁剪量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|通用模型,支持中英文、数字识别|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | @@ -98,7 +98,7 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型版本|模型简介|模型大小|检测模型|文本方向分类模型|识别模型|Paddle-Lite版本| |---|---|---|---|---|---|---| -|V2.1|ppocr_v2.1蒸馏版超轻量中文OCR移动端模型|11M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_infer_opt.nb)|v2.9| -|V2.1(slim)|ppocr_v2.1蒸馏版超轻量中文OCR移动端模型|4.9M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_opt.nb)|v2.9| +|PP-OCRv2|蒸馏版超轻量中文OCR移动端模型|11M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| +|PP-OCRv2(slim)|蒸馏版超轻量中文OCR移动端模型|4.9M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| |V2.0|ppocr_v2.0超轻量中文OCR移动端模型|7.8M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_opt.nb)|v2.9| |V2.0(slim)|ppocr_v2.0超轻量中文OCR移动端模型|3.3M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_slim_opt.nb)|v2.9| diff --git a/doc/doc_en/models_list_en.md b/doc/doc_en/models_list_en.md index d699678e64..70775fa8c4 100644 --- a/doc/doc_en/models_list_en.md +++ b/doc/doc_en/models_list_en.md @@ -29,8 +29,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_ppocr_mobile_slim_v2.1_det|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_slim_quant_infer.tar)| -|ch_ppocr_mobile_v2.1_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|Slim pruned lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|2.6M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)| |ch_ppocr_server_v2.0_det|General model, which is larger than the lightweight model, but achieved better performance|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar)| @@ -43,8 +43,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_ppocr_mobile_slim_v2.1_rec|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_quant_train.tar) | -|ch_ppocr_mobile_v2.1_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|Slim pruned and quantized lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M | [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|Original lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|General model, supporting Chinese, English and number recognition|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | @@ -93,7 +93,7 @@ For more supported languages, please refer to : [Multi-language model](./multi_l ### 4. Paddle-Lite Model |Version|Introduction|Model size|Detection model|Text Direction model|Recognition model|Paddle-Lite branch| |---|---|---|---|---|---|---| -|V2.1|ppocr_v2.1 extra-lightweight chinese OCR optimized model|11M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_infer_opt.nb)|v2.9| -|V2.1(slim)|extra-lightweight chinese OCR optimized model|4.9M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_slim_opt.nb)|v2.9| +|PP-OCRv2|extra-lightweight chinese OCR optimized model|11M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| +|PP-OCRv2(slim)|extra-lightweight chinese OCR optimized model|4.9M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| |V2.0|ppocr_v2.0 extra-lightweight chinese OCR optimized model|7.8M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_opt.nb)|v2.9| |V2.0(slim)|ppovr_v2.0 extra-lightweight chinese OCR optimized model|3.3M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_slim_opt.nb)|v2.9| From 662d087efc3db5e0f798128f9f605d1fe73bd96d Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 13:57:39 +0800 Subject: [PATCH 51/77] dygraph2.1 to PP-OCRv2 --- README.md | 2 +- README_ch.md | 2 +- doc/doc_ch/models_list.md | 12 ++++++------ doc/doc_en/models_list_en.md | 12 ++++++------ paddleocr.py | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 34af2d7fa3..7eb030bdc6 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ 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 PP-OCRv2 model(11.6M) | ch_PP-OCRv2_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar)| +| Chinese and English ultra-lightweight PP-OCRv2 model(11.6M) | ch_PP-OCRv2_xx |Mobile&Server|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/ch/ch_PP-OCRv2_rec_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar)| | Chinese and English ultra-lightweight PP-OCR model (9.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[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 PP-OCR model (143.4M) | 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](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_traingit.tar) |[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) | diff --git a/README_ch.md b/README_ch.md index 88dfc63b36..7e8a8e241b 100755 --- a/README_ch.md +++ b/README_ch.md @@ -81,7 +81,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 | 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 | | ------------ | --------------- | ----------------|---- | ---------- | -------- | -| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar)| +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/chinese/ch_PP-OCRv2_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar)| | 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | | 中英文通用PP-OCR server模型(143.4M) |ch_ppocr_server_v2.0_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | diff --git a/doc/doc_ch/models_list.md b/doc/doc_ch/models_list.md index 38be8e1f0c..1760d269f9 100644 --- a/doc/doc_ch/models_list.md +++ b/doc/doc_ch/models_list.md @@ -33,8 +33,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_det_slim|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| -|ch_PP-OCRv2_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|slim裁剪版超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)| 2.6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[推理模型](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)| |ch_ppocr_server_v2.0_det|通用模型,支持中英文、多语种文本检测,比超轻量模型更大,但效果更好|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[推理模型](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)| @@ -48,8 +48,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_rec_slim|slim量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | -|ch_PP-OCRv2_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|slim量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|slim裁剪量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|通用模型,支持中英文、数字识别|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | @@ -98,7 +98,7 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型版本|模型简介|模型大小|检测模型|文本方向分类模型|识别模型|Paddle-Lite版本| |---|---|---|---|---|---|---| -|PP-OCRv2|蒸馏版超轻量中文OCR移动端模型|11M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| -|PP-OCRv2(slim)|蒸馏版超轻量中文OCR移动端模型|4.9M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| +|PP-OCRv2|蒸馏版超轻量中文OCR移动端模型|11M|[下载地址](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| +|PP-OCRv2(slim)|蒸馏版超轻量中文OCR移动端模型|4.9M|[下载地址](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| |V2.0|ppocr_v2.0超轻量中文OCR移动端模型|7.8M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_opt.nb)|v2.9| |V2.0(slim)|ppocr_v2.0超轻量中文OCR移动端模型|3.3M|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[下载地址](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_slim_opt.nb)|v2.9| diff --git a/doc/doc_en/models_list_en.md b/doc/doc_en/models_list_en.md index 70775fa8c4..4ae36eed66 100644 --- a/doc/doc_en/models_list_en.md +++ b/doc/doc_en/models_list_en.md @@ -29,8 +29,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_det_slim|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| -|ch_PP-OCRv2_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|Slim pruned lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|2.6M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)| |ch_ppocr_server_v2.0_det|General model, which is larger than the lightweight model, but achieved better performance|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar)| @@ -43,8 +43,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_rec_slim|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | -|ch_PP-OCRv2_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_PP-OCRv2_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|Slim pruned and quantized lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M | [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|Original lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|General model, supporting Chinese, English and number recognition|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | @@ -93,7 +93,7 @@ For more supported languages, please refer to : [Multi-language model](./multi_l ### 4. Paddle-Lite Model |Version|Introduction|Model size|Detection model|Text Direction model|Recognition model|Paddle-Lite branch| |---|---|---|---|---|---|---| -|PP-OCRv2|extra-lightweight chinese OCR optimized model|11M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| -|PP-OCRv2(slim)|extra-lightweight chinese OCR optimized model|4.9M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| +|PP-OCRv2|extra-lightweight chinese OCR optimized model|11M|[download link](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer_opt.nb)|v2.9| +|PP-OCRv2(slim)|extra-lightweight chinese OCR optimized model|4.9M|[download link](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_opt.nb)|v2.9| |V2.0|ppocr_v2.0 extra-lightweight chinese OCR optimized model|7.8M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_opt.nb)|v2.9| |V2.0(slim)|ppovr_v2.0 extra-lightweight chinese OCR optimized model|3.3M|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_det_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_cls_slim_opt.nb)|[download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/lite/ch_ppocr_mobile_v2.0_rec_slim_opt.nb)|v2.9| diff --git a/paddleocr.py b/paddleocr.py index de71244245..66554af54f 100644 --- a/paddleocr.py +++ b/paddleocr.py @@ -49,13 +49,13 @@ MODEL_URLS = { 'det': { 'ch': { 'url': - 'https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_det_infer.tar', + 'https://paddleocr.bj.bcebos.com/dPP-OCRv2/chinese/ch_ppocr_mobile_v2.1_det_infer.tar', }, }, 'rec': { 'ch': { 'url': - 'https://paddleocr.bj.bcebos.com/dygraph_v2.1/chinese/ch_ppocr_mobile_v2.1_rec_infer.tar', + 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_ppocr_mobile_v2.1_rec_infer.tar', 'dict_path': './ppocr/utils/ppocr_keys_v1.txt' } } From ae09ef607fd7b39d43aed73abec3212c756b10ee Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 06:09:59 +0000 Subject: [PATCH 52/77] fix code style --- ppocr/postprocess/rec_postprocess.py | 62 +++++++++++++++------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index 2bc6064882..39ef16ecfb 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -166,21 +166,21 @@ class NRTRLabelDecode(BaseRecLabelDecode): use_space_char=True, **kwargs): super(NRTRLabelDecode, self).__init__(character_dict_path, - character_type, use_space_char) + character_type, use_space_char) def __call__(self, preds, label=None, *args, **kwargs): if preds.dtype == paddle.int64: if isinstance(preds, paddle.Tensor): preds = preds.numpy() - if preds[0][0]==2: - preds_idx = preds[:,1:] + if preds[0][0] == 2: + preds_idx = preds[:, 1:] else: preds_idx = preds text = self.decode(preds_idx) if label is None: return text - label = self.decode(label[:,1:]) + label = self.decode(label[:, 1:]) else: if isinstance(preds, paddle.Tensor): preds = preds.numpy() @@ -189,13 +189,13 @@ class NRTRLabelDecode(BaseRecLabelDecode): text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) if label is None: return text - label = self.decode(label[:,1:]) + label = self.decode(label[:, 1:]) return text, label def add_special_char(self, dict_character): - dict_character = ['blank','','',''] + dict_character + dict_character = ['blank', '', '', ''] + dict_character return dict_character - + def decode(self, text_index, text_prob=None, is_remove_duplicate=False): """ convert text-index into text-label. """ result_list = [] @@ -204,10 +204,11 @@ class NRTRLabelDecode(BaseRecLabelDecode): char_list = [] conf_list = [] for idx in range(len(text_index[batch_idx])): - if text_index[batch_idx][idx] == 3: # end + if text_index[batch_idx][idx] == 3: # end break try: - char_list.append(self.character[int(text_index[batch_idx][idx])]) + char_list.append(self.character[int(text_index[batch_idx][ + idx])]) except: continue if text_prob is not None: @@ -219,7 +220,6 @@ class NRTRLabelDecode(BaseRecLabelDecode): return result_list - class AttnLabelDecode(BaseRecLabelDecode): """ Convert between text-label and text-index """ @@ -257,7 +257,8 @@ class AttnLabelDecode(BaseRecLabelDecode): if idx > 0 and text_index[batch_idx][idx - 1] == text_index[ batch_idx][idx]: continue - char_list.append(self.character[int(text_index[batch_idx][idx])]) + char_list.append(self.character[int(text_index[batch_idx][ + idx])]) if text_prob is not None: conf_list.append(text_prob[batch_idx][idx]) else: @@ -387,10 +388,9 @@ class SRNLabelDecode(BaseRecLabelDecode): class TableLabelDecode(object): """ """ - def __init__(self, - character_dict_path, - **kwargs): - list_character, list_elem = self.load_char_elem_dict(character_dict_path) + def __init__(self, character_dict_path, **kwargs): + list_character, list_elem = self.load_char_elem_dict( + character_dict_path) list_character = self.add_special_char(list_character) list_elem = self.add_special_char(list_elem) self.dict_character = {} @@ -409,7 +409,8 @@ class TableLabelDecode(object): list_elem = [] with open(character_dict_path, "rb") as fin: lines = fin.readlines() - substr = lines[0].decode('utf-8').strip("\n").strip("\r\n").split("\t") + substr = lines[0].decode('utf-8').strip("\n").strip("\r\n").split( + "\t") character_num = int(substr[0]) elem_num = int(substr[1]) for cno in range(1, 1 + character_num): @@ -429,14 +430,14 @@ class TableLabelDecode(object): def __call__(self, preds): structure_probs = preds['structure_probs'] loc_preds = preds['loc_preds'] - if isinstance(structure_probs,paddle.Tensor): + if isinstance(structure_probs, paddle.Tensor): structure_probs = structure_probs.numpy() - if isinstance(loc_preds,paddle.Tensor): + if isinstance(loc_preds, paddle.Tensor): loc_preds = loc_preds.numpy() structure_idx = structure_probs.argmax(axis=2) structure_probs = structure_probs.max(axis=2) - structure_str, structure_pos, result_score_list, result_elem_idx_list = self.decode(structure_idx, - structure_probs, 'elem') + structure_str, structure_pos, result_score_list, result_elem_idx_list = self.decode( + structure_idx, structure_probs, 'elem') res_html_code_list = [] res_loc_list = [] batch_num = len(structure_str) @@ -451,8 +452,13 @@ class TableLabelDecode(object): res_loc = np.array(res_loc) res_html_code_list.append(res_html_code) res_loc_list.append(res_loc) - return {'res_html_code': res_html_code_list, 'res_loc': res_loc_list, 'res_score_list': result_score_list, - 'res_elem_idx_list': result_elem_idx_list,'structure_str_list':structure_str} + return { + 'res_html_code': res_html_code_list, + 'res_loc': res_loc_list, + 'res_score_list': result_score_list, + 'res_elem_idx_list': result_elem_idx_list, + 'structure_str_list': structure_str + } def decode(self, text_index, structure_probs, char_or_elem): """convert text-label into text-index. @@ -528,9 +534,9 @@ class SARLabelDecode(BaseRecLabelDecode): use_space_char=False, **kwargs): super(SARLabelDecode, self).__init__(character_dict_path, - character_type, use_space_char) - - self.rm_symbol = kwargs.get('rm_symbol', True) + character_type, use_space_char) + + self.rm_symbol = kwargs.get('rm_symbol', True) def add_special_char(self, dict_character): beg_end_str = "" @@ -549,7 +555,7 @@ class SARLabelDecode(BaseRecLabelDecode): """ convert text-index into text-label. """ result_list = [] ignored_tokens = self.get_ignored_tokens() - + batch_size = len(text_index) for batch_idx in range(batch_size): char_list = [] @@ -558,7 +564,7 @@ class SARLabelDecode(BaseRecLabelDecode): if text_index[batch_idx][idx] in ignored_tokens: continue if int(text_index[batch_idx][idx]) == int(self.end_idx): - if text_prob is None and idx ==0: + if text_prob is None and idx == 0: continue else: break @@ -586,7 +592,7 @@ class SARLabelDecode(BaseRecLabelDecode): preds = preds.numpy() preds_idx = preds.argmax(axis=2) preds_prob = preds.max(axis=2) - + text = self.decode(preds_idx, preds_prob, is_remove_duplicate=False) if label is None: From d611515803d71a847f7b262704fe7e92607b0ef6 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 06:13:56 +0000 Subject: [PATCH 53/77] fix code style --- ppocr/modeling/heads/rec_sar_head.py | 179 ++++++++++++++------------- 1 file changed, 92 insertions(+), 87 deletions(-) diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py index ba0aa8ebe5..3c131c8b5d 100644 --- a/ppocr/modeling/heads/rec_sar_head.py +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -19,6 +19,7 @@ class SAREncoder(nn.Layer): d_enc (int): Dim of encoder RNN layer. mask (bool): If True, mask padding in RNN sequence. """ + def __init__(self, enc_bi_rnn=False, enc_drop_rnn=0.1, @@ -51,33 +52,31 @@ class SAREncoder(nn.Layer): num_layers=2, time_major=False, dropout=enc_drop_rnn, - direction=direction - ) + direction=direction) if enc_gru: self.rnn_encoder = nn.GRU(**kwargs) else: self.rnn_encoder = nn.LSTM(**kwargs) - + # global feature transformation encoder_rnn_out_size = d_enc * (int(enc_bi_rnn) + 1) self.linear = nn.Linear(encoder_rnn_out_size, encoder_rnn_out_size) - + def forward(self, feat, img_metas=None): if img_metas is not None: assert len(img_metas[0]) == feat.shape[0] - + valid_ratios = None if img_metas is not None and self.mask: valid_ratios = img_metas[-1] - - h_feat = feat.shape[2] # bsz c h w + + h_feat = feat.shape[2] # bsz c h w feat_v = F.max_pool2d( - feat, kernel_size=(h_feat, 1), stride=1, padding=0 - ) - feat_v = feat_v.squeeze(2) # bsz * C * W - feat_v = paddle.transpose(feat_v, perm=[0, 2, 1]) # bsz * W * C - holistic_feat = self.rnn_encoder(feat_v)[0] # bsz * T * C - + feat, kernel_size=(h_feat, 1), stride=1, padding=0) + feat_v = feat_v.squeeze(2) # bsz * C * W + feat_v = paddle.transpose(feat_v, perm=[0, 2, 1]) # bsz * W * C + holistic_feat = self.rnn_encoder(feat_v)[0] # bsz * T * C + if valid_ratios is not None: valid_hf = [] T = holistic_feat.shape[1] @@ -86,11 +85,11 @@ class SAREncoder(nn.Layer): valid_hf.append(holistic_feat[i, valid_step, :]) valid_hf = paddle.stack(valid_hf, axis=0) else: - valid_hf = holistic_feat[:, -1, :] # bsz * C - holistic_feat = self.linear(valid_hf) # bsz * C - + valid_hf = holistic_feat[:, -1, :] # bsz * C + holistic_feat = self.linear(valid_hf) # bsz * C + return holistic_feat - + class BaseDecoder(nn.Layer): def __init__(self, **kwargs): @@ -102,7 +101,7 @@ class BaseDecoder(nn.Layer): def forward_test(self, feat, out_enc, img_metas): raise NotImplementedError - def forward(self, + def forward(self, feat, out_enc, label=None, @@ -135,20 +134,21 @@ class ParallelSARDecoder(BaseDecoder): attention with holistic feature and hidden state. """ - def __init__(self, - out_channels, # 90 + unknown + start + padding - enc_bi_rnn=False, - dec_bi_rnn=False, - dec_drop_rnn=0.0, - dec_gru=False, - d_model=512, - d_enc=512, - d_k=64, - pred_dropout=0.1, - max_text_length=30, - mask=True, - pred_concat=True, - **kwargs): + def __init__( + self, + out_channels, # 90 + unknown + start + padding + enc_bi_rnn=False, + dec_bi_rnn=False, + dec_drop_rnn=0.0, + dec_gru=False, + d_model=512, + d_enc=512, + d_k=64, + pred_dropout=0.1, + max_text_length=30, + mask=True, + pred_concat=True, + **kwargs): super().__init__() self.num_classes = out_channels @@ -165,7 +165,8 @@ class ParallelSARDecoder(BaseDecoder): # 2D attention layer self.conv1x1_1 = nn.Linear(decoder_rnn_out_size, d_k) - self.conv3x3_1 = nn.Conv2D(d_model, d_k, kernel_size=3, stride=1, padding=1) + self.conv3x3_1 = nn.Conv2D( + d_model, d_k, kernel_size=3, stride=1, padding=1) self.conv1x1_2 = nn.Linear(d_k, 1) # Decoder RNN layer @@ -180,8 +181,7 @@ class ParallelSARDecoder(BaseDecoder): num_layers=2, time_major=False, dropout=dec_drop_rnn, - direction=direction - ) + direction=direction) if dec_gru: self.rnn_decoder = nn.GRU(**kwargs) else: @@ -189,8 +189,10 @@ class ParallelSARDecoder(BaseDecoder): # Decoder input embedding self.embedding = nn.Embedding( - self.num_classes, encoder_rnn_out_size, padding_idx=self.padding_idx) - + self.num_classes, + encoder_rnn_out_size, + padding_idx=self.padding_idx) + # Prediction layer self.pred_dropout = nn.Dropout(pred_dropout) pred_num_classes = num_classes - 1 @@ -205,11 +207,11 @@ class ParallelSARDecoder(BaseDecoder): feat, holistic_feat, valid_ratios=None): - + y = self.rnn_decoder(decoder_input)[0] # y: bsz * (seq_len + 1) * hidden_size - - attn_query = self.conv1x1_1(y) # bsz * (seq_len + 1) * attn_size + + attn_query = self.conv1x1_1(y) # bsz * (seq_len + 1) * attn_size bsz, seq_len, attn_size = attn_query.shape attn_query = paddle.unsqueeze(attn_query, axis=[3, 4]) # (bsz, seq_len + 1, attn_size, 1, 1) @@ -220,7 +222,7 @@ class ParallelSARDecoder(BaseDecoder): # bsz * 1 * attn_size * h * w attn_weight = paddle.tanh(paddle.add(attn_key, attn_query)) - + # bsz * (seq_len + 1) * attn_size * h * w attn_weight = paddle.transpose(attn_weight, perm=[0, 1, 3, 4, 2]) # bsz * (seq_len + 1) * h * w * attn_size @@ -237,25 +239,28 @@ class ParallelSARDecoder(BaseDecoder): attn_weight = paddle.reshape(attn_weight, [bsz, T, -1]) attn_weight = F.softmax(attn_weight, axis=-1) - + attn_weight = paddle.reshape(attn_weight, [bsz, T, h, w, c]) attn_weight = paddle.transpose(attn_weight, perm=[0, 1, 4, 2, 3]) # attn_weight: bsz * T * c * h * w # feat: bsz * c * h * w - attn_feat = paddle.sum(paddle.multiply(feat.unsqueeze(1), attn_weight), (3, 4), keepdim=False) + attn_feat = paddle.sum(paddle.multiply(feat.unsqueeze(1), attn_weight), + (3, 4), + keepdim=False) # bsz * (seq_len + 1) * C # Linear transformation if self.pred_concat: hf_c = holistic_feat.shape[-1] - holistic_feat = paddle.expand(holistic_feat, shape=[bsz, seq_len, hf_c]) + holistic_feat = paddle.expand( + holistic_feat, shape=[bsz, seq_len, hf_c]) y = self.prediction(paddle.concat((y, attn_feat, holistic_feat), 2)) else: y = self.prediction(attn_feat) # bsz * (seq_len + 1) * num_classes if self.train_mode: y = self.pred_dropout(y) - + return y def forward_train(self, feat, out_enc, label, img_metas): @@ -268,7 +273,7 @@ class ParallelSARDecoder(BaseDecoder): valid_ratios = None if img_metas is not None and self.mask: valid_ratios = img_metas[-1] - + label = label.cuda() lab_embedding = self.embedding(label) # bsz * seq_len * emb_dim @@ -277,11 +282,10 @@ class ParallelSARDecoder(BaseDecoder): in_dec = paddle.concat((out_enc, lab_embedding), axis=1) # bsz * (seq_len + 1) * C out_dec = self._2d_attention( - in_dec, feat, out_enc, valid_ratios=valid_ratios - ) + in_dec, feat, out_enc, valid_ratios=valid_ratios) # bsz * (seq_len + 1) * num_classes - - return out_dec[:, 1:, :] # bsz * seq_len * num_classes + + return out_dec[:, 1:, :] # bsz * seq_len * num_classes def forward_test(self, feat, out_enc, img_metas): if img_metas is not None: @@ -289,13 +293,12 @@ class ParallelSARDecoder(BaseDecoder): valid_ratios = None if img_metas is not None and self.mask: - valid_ratios = img_metas[-1] - + valid_ratios = img_metas[-1] + seq_len = self.max_seq_len bsz = feat.shape[0] - start_token = paddle.full((bsz, ), - fill_value=self.start_idx, - dtype='int64') + start_token = paddle.full( + (bsz, ), fill_value=self.start_idx, dtype='int64') # bsz start_token = self.embedding(start_token) # bsz * emb_dim @@ -311,68 +314,70 @@ class ParallelSARDecoder(BaseDecoder): outputs = [] for i in range(1, seq_len + 1): decoder_output = self._2d_attention( - decoder_input, feat, out_enc, valid_ratios=valid_ratios - ) - char_output = decoder_output[:, i, :] # bsz * num_classes + decoder_input, feat, out_enc, valid_ratios=valid_ratios) + char_output = decoder_output[:, i, :] # bsz * num_classes char_output = F.softmax(char_output, -1) outputs.append(char_output) max_idx = paddle.argmax(char_output, axis=1, keepdim=False) - char_embedding = self.embedding(max_idx) # bsz * emb_dim + char_embedding = self.embedding(max_idx) # bsz * emb_dim if i < seq_len: decoder_input[:, i + 1, :] = char_embedding - - outputs = paddle.stack(outputs, 1) # bsz * seq_len * num_classes + + outputs = paddle.stack(outputs, 1) # bsz * seq_len * num_classes return outputs class SARHead(nn.Layer): - def __init__(self, - out_channels, - enc_bi_rnn=False, - enc_drop_rnn=0.1, - enc_gru=False, - dec_bi_rnn=False, - dec_drop_rnn=0.0, - dec_gru=False, - d_k=512, - pred_dropout=0.1, - max_text_length=30, - pred_concat=True, - **kwargs): + def __init__(self, + out_channels, + enc_bi_rnn=False, + enc_drop_rnn=0.1, + enc_gru=False, + dec_bi_rnn=False, + dec_drop_rnn=0.0, + dec_gru=False, + d_k=512, + pred_dropout=0.1, + max_text_length=30, + pred_concat=True, + **kwargs): super(SARHead, self).__init__() # encoder module self.encoder = SAREncoder( - enc_bi_rnn=enc_bi_rnn, - enc_drop_rnn=enc_drop_rnn, - enc_gru=enc_gru) + enc_bi_rnn=enc_bi_rnn, enc_drop_rnn=enc_drop_rnn, enc_gru=enc_gru) # decoder module self.decoder = ParallelSARDecoder( out_channels=out_channels, - enc_bi_rnn=enc_bi_rnn, + enc_bi_rnn=enc_bi_rnn, dec_bi_rnn=dec_bi_rnn, dec_drop_rnn=dec_drop_rnn, dec_gru=dec_gru, d_k=d_k, pred_dropout=pred_dropout, max_text_length=max_text_length, - pred_concat=pred_concat) - + pred_concat=pred_concat) + def forward(self, feat, targets=None): ''' img_metas: [label, valid_ratio] ''' - holistic_feat = self.encoder(feat, targets) # bsz c - + holistic_feat = self.encoder(feat, targets) # bsz c + if self.training: - label = targets[0] # label + label = targets[0] # label label = paddle.to_tensor(label, dtype='int64') - final_out = self.decoder(feat, holistic_feat, label, img_metas=targets) + final_out = self.decoder( + feat, holistic_feat, label, img_metas=targets) if not self.training: - final_out = self.decoder(feat, holistic_feat, label=None, img_metas=targets, train_mode=False) + final_out = self.decoder( + feat, + holistic_feat, + label=None, + img_metas=targets, + train_mode=False) # (bsz, seq_len, num_classes) - + return final_out - From 190359478287724ae4a0add7b42c37f3ccee3888 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 14:14:58 +0800 Subject: [PATCH 54/77] update config yml --- .../ch_PP-OCR_det_cml.yml} | 0 .../ch_PP-OCR_det_distill.yml} | 0 .../ch_PP-OCR_det_dml.yml} | 0 .../ch_PP-OCR_det_student.yml} | 0 .../ch_PP-OCRv2_rec.yml} | 0 doc/doc_ch/knowledge_distillation.md | 2 +- doc/doc_ch/models_list.md | 8 ++++---- doc/doc_en/models_list_en.md | 8 ++++---- 8 files changed, 9 insertions(+), 9 deletions(-) rename configs/det/{ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml => ch_PP-OCRv2/ch_PP-OCR_det_cml.yml} (100%) rename configs/det/{ch_ppocr_v2.1/ch_det_lite_train_distill_v2.1.yml => ch_PP-OCRv2/ch_PP-OCR_det_distill.yml} (100%) rename configs/det/{ch_ppocr_v2.1/ch_det_lite_train_dml_v2.1.yml => ch_PP-OCRv2/ch_PP-OCR_det_dml.yml} (100%) rename configs/det/{ch_ppocr_v2.1/ch_det_mv3_db_v2.1_student.yml => ch_PP-OCRv2/ch_PP-OCR_det_student.yml} (100%) rename configs/rec/{ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml => ch_PP-OCRv2/ch_PP-OCRv2_rec.yml} (100%) diff --git a/configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml similarity index 100% rename from configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml rename to configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml diff --git a/configs/det/ch_ppocr_v2.1/ch_det_lite_train_distill_v2.1.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCR_det_distill.yml similarity index 100% rename from configs/det/ch_ppocr_v2.1/ch_det_lite_train_distill_v2.1.yml rename to configs/det/ch_PP-OCRv2/ch_PP-OCR_det_distill.yml diff --git a/configs/det/ch_ppocr_v2.1/ch_det_lite_train_dml_v2.1.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCR_det_dml.yml similarity index 100% rename from configs/det/ch_ppocr_v2.1/ch_det_lite_train_dml_v2.1.yml rename to configs/det/ch_PP-OCRv2/ch_PP-OCR_det_dml.yml diff --git a/configs/det/ch_ppocr_v2.1/ch_det_mv3_db_v2.1_student.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCR_det_student.yml similarity index 100% rename from configs/det/ch_ppocr_v2.1/ch_det_mv3_db_v2.1_student.yml rename to configs/det/ch_PP-OCRv2/ch_PP-OCR_det_student.yml diff --git a/configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml similarity index 100% rename from configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml rename to configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml diff --git a/doc/doc_ch/knowledge_distillation.md b/doc/doc_ch/knowledge_distillation.md index b561f71849..5827f48c81 100644 --- a/doc/doc_ch/knowledge_distillation.md +++ b/doc/doc_ch/knowledge_distillation.md @@ -39,7 +39,7 @@ PaddleOCR中集成了知识蒸馏的算法,具体地,有以下几个主要 ### 2.1 识别配置文件解析 -配置文件在[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)。 +配置文件在[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)。 #### 2.1.1 模型结构 diff --git a/doc/doc_ch/models_list.md b/doc/doc_ch/models_list.md index 1760d269f9..2731a1cafa 100644 --- a/doc/doc_ch/models_list.md +++ b/doc/doc_ch/models_list.md @@ -33,8 +33,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_det_slim|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| -|ch_PP-OCRv2_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim量化+蒸馏版超轻量模型,支持中英文、多语种文本检测|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml)| 3M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml)|3M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|slim裁剪版超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)| 2.6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|原始超轻量模型,支持中英文、多语种文本检测|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[推理模型](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)| |ch_ppocr_server_v2.0_det|通用模型,支持中英文、多语种文本检测,比超轻量模型更大,但效果更好|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[推理模型](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)| @@ -48,8 +48,8 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |模型名称|模型简介|配置文件|推理模型大小|下载地址| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_rec_slim|slim量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | -|ch_PP-OCRv2_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|slim量化版超轻量模型,支持中英文、数字识别|[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)| 9M |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|原始超轻量模型,支持中英文、数字识别|[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)|8.5M|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|slim裁剪量化版超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|原始超轻量模型,支持中英文、数字识别|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|通用模型,支持中英文、数字识别|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[推理模型](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_train.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | diff --git a/doc/doc_en/models_list_en.md b/doc/doc_en/models_list_en.md index 4ae36eed66..3b9b551870 100644 --- a/doc/doc_en/models_list_en.md +++ b/doc/doc_en/models_list_en.md @@ -29,8 +29,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_det_slim|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.yml](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| -|ch_PP-OCRv2_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_lite_train_cml_v2.1.ym](../../configs/det/ch_ppocr_v2.1/ch_det_lite_train_cml_v2.1.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| +|ch_PP-OCRv2_det_slim|slim quantization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml)| 3M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_slim_quant_infer.tar)| +|ch_PP-OCRv2_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_det_cml.yml](../../configs/det/ch_PP-OCRv2/ch_PP-OCR_det_cml.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| |ch_ppocr_mobile_slim_v2.0_det|Slim pruned lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|2.6M |[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/slim/ch_ppocr_mobile_v2.0_det_prune_infer.tar)| |ch_ppocr_mobile_v2.0_det|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_det_mv3_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml)|3M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)| |ch_ppocr_server_v2.0_det|General model, which is larger than the lightweight model, but achieved better performance|[ch_det_res18_db_v2.0.yml](../../configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml)|47M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar)| @@ -43,8 +43,8 @@ Relationship of the above models is as follows. |model name|description|config|model size|download| | --- | --- | --- | --- | --- | -|ch_PP-OCRv2_rec_slim|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | -|ch_PP-OCRv2_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[rec_chinese_lite_train_distillation_v2.1.yml](../../configs/rec/ch_ppocr_v2.1/rec_chinese_lite_train_distillation_v2.1.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | +|ch_PP-OCRv2_rec_slim|Slim qunatization with distillation lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)| 9M |[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_slim_quant_train.tar) | +|ch_PP-OCRv2_rec|Original lightweight model, supporting Chinese, English, multilingual text detection|[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)|8.5M|[inference model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar) | |ch_ppocr_mobile_slim_v2.0_rec|Slim pruned and quantized lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)| 6M | [inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_train.tar) | |ch_ppocr_mobile_v2.0_rec|Original lightweight model, supporting Chinese, English and number recognition|[rec_chinese_lite_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml)|5.2M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | |ch_ppocr_server_v2.0_rec|General model, supporting Chinese, English and number recognition|[rec_chinese_common_train_v2.0.yml](../../configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml)|94.8M|[inference model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_train.tar) / [pre-trained model](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | From 3fcbc05cab782fe9f91b032ba10e2dd6b8b47918 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 14:18:12 +0800 Subject: [PATCH 55/77] add blank commit --- doc/doc_ch/models_list.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/doc_ch/models_list.md b/doc/doc_ch/models_list.md index 2731a1cafa..5e78795bcd 100644 --- a/doc/doc_ch/models_list.md +++ b/doc/doc_ch/models_list.md @@ -93,6 +93,7 @@ PaddleOCR提供的可下载模型包括`推理模型`、`训练模型`、`预训 |ch_ppocr_mobile_slim_v2.0_cls|slim量化版模型,对检测到的文本行文字角度分类|[cls_mv3.yml](../../configs/cls/cls_mv3.yml)| 2.1M |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_slim_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_slim_infer.tar) | |ch_ppocr_mobile_v2.0_cls|原始分类器模型,对检测到的文本行文字角度分类|[cls_mv3.yml](../../configs/cls/cls_mv3.yml)|1.38M|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) | + ### 四、Paddle-Lite 模型 From 7fa72519505123c823673f3939c4161b5adc81f3 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 14:30:31 +0800 Subject: [PATCH 56/77] fix bug --- paddleocr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddleocr.py b/paddleocr.py index 66554af54f..9b6df44eff 100644 --- a/paddleocr.py +++ b/paddleocr.py @@ -49,7 +49,7 @@ MODEL_URLS = { 'det': { 'ch': { 'url': - 'https://paddleocr.bj.bcebos.com/dPP-OCRv2/chinese/ch_ppocr_mobile_v2.1_det_infer.tar', + 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_ppocr_mobile_v2.1_det_infer.tar', }, }, 'rec': { From adba814904eb4f0aeeec186f158cfb6c212a6e26 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 14:32:06 +0800 Subject: [PATCH 57/77] fix bug --- paddleocr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddleocr.py b/paddleocr.py index 9b6df44eff..a98efd3408 100644 --- a/paddleocr.py +++ b/paddleocr.py @@ -49,13 +49,13 @@ MODEL_URLS = { 'det': { 'ch': { 'url': - 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_ppocr_mobile_v2.1_det_infer.tar', + 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar', }, }, 'rec': { 'ch': { 'url': - 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_ppocr_mobile_v2.1_rec_infer.tar', + 'https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar', 'dict_path': './ppocr/utils/ppocr_keys_v1.txt' } } From b68c895827641b3459069fe804546407fd6c8711 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 07:39:24 +0000 Subject: [PATCH 58/77] fix code style --- ppocr/modeling/heads/rec_sar_head.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppocr/modeling/heads/rec_sar_head.py b/ppocr/modeling/heads/rec_sar_head.py index 3c131c8b5d..647f58200f 100644 --- a/ppocr/modeling/heads/rec_sar_head.py +++ b/ppocr/modeling/heads/rec_sar_head.py @@ -195,7 +195,7 @@ class ParallelSARDecoder(BaseDecoder): # Prediction layer self.pred_dropout = nn.Dropout(pred_dropout) - pred_num_classes = num_classes - 1 + pred_num_classes = self.num_classes - 1 if pred_concat: fc_in_channel = decoder_rnn_out_size + d_model + d_enc else: From 49e42a16a7f256c5c5e69169cacbede02200e205 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Tue, 7 Sep 2021 15:50:04 +0800 Subject: [PATCH 59/77] add service mode for prepare --- tests/prepare.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index 828705c380..f725b9b309 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -1,6 +1,6 @@ #!/bin/bash FILENAME=$1 -# MODE be one of ['lite_train_infer' 'whole_infer' 'whole_train_infer', 'infer'] +# MODE be one of ['lite_train_infer' 'whole_infer' 'whole_train_infer', 'infer', 'serving_infer'] MODE=$2 dataline=$(cat ${FILENAME}) @@ -75,13 +75,14 @@ else fi fi -# prepare serving env -python_name=$(func_parser_value "${lines[2]}") -${python_name} -m pip install install paddle-serving-server-gpu==0.6.1.post101 -${python_name} -m pip install paddle_serving_client==0.6.1 -${python_name} -m pip install paddle-serving-app==0.6.1 -wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar -wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar -cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar - +if [ ${MODE} = "serving_infer" ];then + # prepare serving env + python_name=$(func_parser_value "${lines[2]}") + ${python_name} -m pip install install paddle-serving-server-gpu==0.6.1.post101 + ${python_name} -m pip install paddle_serving_client==0.6.1 + ${python_name} -m pip install paddle-serving-app==0.6.1 + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar +fi From c1abab5ef3cad4176e54b4f83259e4ac4c7d1be4 Mon Sep 17 00:00:00 2001 From: xiaoting <31891223+tink2123@users.noreply.github.com> Date: Tue, 7 Sep 2021 15:53:56 +0800 Subject: [PATCH 60/77] Update prepare.sh --- tests/prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/prepare.sh b/tests/prepare.sh index d43c8a2e1e..aa6420054a 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -97,7 +97,7 @@ if [ ${MODE} = "serving_infer" ];then ${python_name} -m pip install paddle-serving-app==0.6.1 wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar - cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && cd ../ fi if [ ${MODE} = "cpp_infer" ];then From d2bace5a0e068909bb8b65a1df7a4801c9ea7645 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 08:00:23 +0000 Subject: [PATCH 61/77] fix yml --- tests/configs/det_mv3_db.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/configs/det_mv3_db.yml b/tests/configs/det_mv3_db.yml index 0845687192..d6d4c26cbc 100644 --- a/tests/configs/det_mv3_db.yml +++ b/tests/configs/det_mv3_db.yml @@ -23,9 +23,10 @@ Architecture: name: MobileNetV3 scale: 0.5 model_name: large + disable_se: True Neck: name: DBFPN - out_channels: 256 + out_channels: 96 Head: name: DBHead k: 50 @@ -34,8 +35,8 @@ Loss: name: DBLoss balance_loss: true main_loss_type: DiceLoss - alpha: 5 #5 - beta: 10 #10 + alpha: 5 + beta: 10 ohem_ratio: 3 Optimizer: From e10f71df100d9dd51d7f3e767da368f7d45e1c7b Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 09:47:09 +0000 Subject: [PATCH 62/77] update sar_yml --- configs/rec/rec_r31_sar.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index 7adb7136c5..053b1ae835 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -56,7 +56,6 @@ Metric: Train: dataset: name: SimpleDataSet - delimiter: ' ' label_file_list: ['./train_data/train_list.txt'] data_dir: ./train_data/ ratio_list: 1.0 From abc8e581482b090412933a3e9304c0c5c573cbbd Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 11:23:44 +0000 Subject: [PATCH 63/77] update results for opencv 4.4 --- tests/results/det_results_gpu_fp32.txt | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/results/det_results_gpu_fp32.txt b/tests/results/det_results_gpu_fp32.txt index 28af26d0b2..e370b491bf 100644 --- a/tests/results/det_results_gpu_fp32.txt +++ b/tests/results/det_results_gpu_fp32.txt @@ -1,49 +1,49 @@ -00008790.jpg [[[209, 406], [280, 406], [280, 419], [209, 419]], [[60, 398], [105, 398], [105, 411], [60, 411]], [[198, 389], [291, 389], [291, 402], [198, 402]], [[162, 391], [173, 391], [173, 401], [162, 401]], [[35, 380], [133, 380], [133, 393], [35, 393]], [[199, 371], [292, 371], [292, 384], [199, 384]], [[218, 310], [272, 310], [272, 324], [218, 324]], [[162, 305], [172, 305], [172, 314], [162, 314]], [[371, 302], [436, 302], [436, 316], [371, 316]], [[31, 302], [134, 301], [134, 315], [31, 316]], [[223, 292], [269, 292], [269, 306], [223, 306]], [[60, 225], [104, 225], [104, 236], [60, 236]], [[218, 223], [272, 223], [272, 237], [218, 237]], [[162, 219], [173, 219], [173, 227], [162, 227]], [[33, 207], [131, 207], [131, 220], [33, 220]], [[223, 206], [269, 206], [269, 220], [223, 220]], [[74, 146], [383, 146], [383, 159], [74, 159]], [[54, 120], [117, 120], [117, 134], [54, 134]], [[74, 51], [296, 51], [296, 65], [74, 65]], [[56, 18], [116, 18], [116, 32], [56, 32]]] +00008790.jpg [[[209, 406], [280, 406], [280, 419], [209, 419]], [[60, 398], [105, 398], [105, 411], [60, 411]], [[198, 389], [291, 389], [291, 402], [198, 402]], [[162, 391], [173, 391], [173, 401], [162, 401]], [[35, 380], [133, 380], [133, 393], [35, 393]], [[199, 371], [292, 371], [292, 384], [199, 384]], [[218, 310], [272, 310], [272, 324], [218, 324]], [[162, 305], [172, 305], [172, 314], [162, 314]], [[371, 302], [436, 302], [436, 316], [371, 316]], [[31, 302], [134, 301], [134, 315], [31, 316]], [[223, 292], [269, 292], [269, 306], [223, 306]], [[60, 225], [104, 225], [104, 236], [60, 236]], [[218, 223], [272, 223], [272, 237], [218, 237]], [[162, 219], [173, 219], [173, 227], [162, 227]], [[33, 207], [131, 207], [131, 220], [33, 220]], [[223, 206], [269, 206], [269, 220], [223, 220]], [[74, 146], [383, 146], [383, 159], [74, 159]], [[54, 120], [117, 120], [117, 134], [54, 134]], [[74, 51], [296, 51], [296, 65], [74, 65]], [[56, 17], [116, 17], [116, 31], [56, 31]]] 00018946.jpg [[[441, 328], [474, 328], [474, 339], [441, 339]], [[86, 284], [141, 286], [140, 307], [85, 305]], [[302, 279], [377, 279], [377, 297], [302, 297]], [[197, 265], [281, 274], [279, 293], [195, 284]], [[198, 197], [452, 219], [450, 242], [196, 220]], [[343, 182], [376, 182], [376, 192], [343, 192]], [[199, 164], [340, 171], [339, 192], [198, 185]], [[177, 101], [415, 118], [413, 145], [175, 128]]] 00034387.jpg [[[265, 460], [740, 460], [740, 484], [265, 484]], [[348, 417], [420, 417], [420, 443], [348, 443]], [[545, 418], [568, 418], [568, 442], [545, 442]], [[685, 417], [710, 417], [710, 443], [685, 443]], [[175, 415], [226, 415], [226, 443], [175, 443]], [[874, 414], [908, 414], [908, 446], [874, 446]], [[56, 417], [74, 417], [74, 442], [56, 442]], [[856, 373], [925, 373], [925, 400], [856, 400]], [[348, 372], [418, 372], [418, 397], [348, 397]], [[674, 372], [723, 372], [723, 401], [674, 401]], [[539, 373], [570, 373], [570, 400], [539, 400]], [[151, 365], [228, 369], [226, 402], [149, 398]], [[56, 372], [74, 372], [74, 397], [56, 397]], [[857, 329], [925, 329], [925, 355], [857, 355]], [[351, 330], [419, 330], [419, 356], [351, 356]], [[674, 328], [723, 328], [723, 356], [674, 356]], [[541, 329], [570, 329], [570, 357], [541, 357]], [[171, 327], [227, 324], [229, 355], [173, 358]], [[57, 330], [74, 330], [74, 356], [57, 356]], [[298, 327], [316, 327], [316, 334], [298, 334]], [[855, 286], [925, 286], [925, 312], [855, 312]], [[674, 286], [723, 286], [723, 313], [674, 313]], [[346, 286], [426, 283], [427, 313], [347, 316]], [[540, 285], [569, 285], [569, 312], [540, 312]], [[172, 282], [226, 282], [226, 313], [172, 313]], [[56, 287], [73, 287], [73, 312], [56, 312]], [[857, 242], [925, 242], [925, 268], [857, 268]], [[348, 242], [460, 242], [460, 268], [348, 268]], [[156, 242], [227, 242], [227, 269], [156, 269]], [[674, 241], [724, 241], [724, 269], [674, 269]], [[531, 241], [572, 241], [572, 270], [531, 270]], [[56, 242], [74, 242], [74, 268], [56, 268]], [[855, 197], [925, 200], [924, 226], [854, 224]], [[674, 198], [726, 198], [726, 226], [674, 226]], [[344, 200], [434, 195], [436, 223], [346, 228]], [[176, 197], [227, 197], [227, 225], [176, 225]], [[56, 200], [73, 200], [73, 226], [56, 226]], [[527, 194], [576, 194], [576, 226], [527, 226]], [[349, 155], [419, 155], [419, 181], [349, 181]], [[854, 154], [925, 154], [925, 180], [854, 180]], [[176, 154], [226, 154], [226, 183], [176, 183]], [[670, 153], [723, 153], [723, 181], [670, 181]], [[538, 154], [571, 154], [571, 182], [538, 182]], [[56, 156], [74, 156], [74, 182], [56, 182]], [[349, 111], [419, 111], [419, 137], [349, 137]], [[174, 111], [227, 111], [227, 139], [174, 139]], [[546, 113], [564, 113], [564, 137], [546, 137]], [[52, 112], [75, 112], [75, 139], [52, 139]], [[639, 108], [727, 105], [728, 138], [640, 141]], [[817, 103], [927, 110], [925, 139], [815, 132]], [[814, 68], [951, 68], [951, 92], [814, 92]], [[307, 66], [446, 68], [446, 93], [306, 90]], [[673, 67], [723, 67], [723, 93], [673, 93]], [[175, 65], [228, 68], [226, 95], [174, 92]], [[39, 65], [90, 68], [88, 97], [37, 94]], [[528, 65], [580, 65], [580, 94], [528, 94]], [[334, 20], [670, 20], [670, 43], [334, 43]]] 00037951.jpg [[[434, 976], [551, 978], [550, 993], [434, 991]], [[433, 932], [553, 932], [553, 969], [433, 969]], [[30, 522], [98, 522], [98, 545], [30, 545]], [[31, 443], [145, 443], [145, 464], [31, 464]], [[234, 335], [326, 332], [327, 354], [235, 356]], [[124, 252], [436, 252], [436, 284], [124, 284]], [[182, 206], [378, 206], [378, 227], [182, 227]], [[258, 106], [320, 123], [304, 181], [242, 163]], [[28, 65], [33, 65], [33, 71], [28, 71]], [[37, 58], [147, 58], [147, 80], [37, 80]]] 00044782.jpg [[[104, 218], [115, 218], [115, 227], [104, 227]], [[223, 216], [246, 216], [246, 228], [223, 228]], [[163, 216], [182, 216], [182, 229], [163, 229]], [[124, 191], [164, 191], [164, 202], [124, 202]], [[91, 84], [251, 84], [251, 98], [91, 98]], [[73, 63], [278, 63], [278, 78], [73, 78]], [[104, 15], [243, 15], [243, 44], [104, 44]]] -00067516.jpg [[[141, 808], [594, 809], [594, 822], [141, 821]], [[49, 784], [696, 784], [696, 798], [49, 798]], [[579, 751], [667, 751], [667, 764], [579, 764]], [[355, 750], [395, 750], [395, 767], [355, 767]], [[221, 751], [260, 751], [260, 765], [221, 765]], [[477, 750], [501, 750], [501, 768], [477, 768]], [[69, 748], [133, 751], [132, 765], [68, 761]], [[576, 682], [668, 682], [668, 699], [576, 699]], [[476, 682], [518, 682], [518, 700], [476, 700]], [[354, 682], [395, 682], [395, 700], [354, 700]], [[69, 681], [133, 684], [132, 699], [68, 695]], [[220, 679], [243, 682], [241, 700], [218, 697]], [[577, 615], [667, 615], [667, 632], [577, 632]], [[68, 612], [134, 615], [133, 632], [67, 629]], [[476, 614], [500, 614], [500, 633], [476, 633]], [[354, 613], [378, 613], [378, 634], [354, 634]], [[219, 612], [245, 612], [245, 633], [219, 633]], [[578, 547], [667, 547], [667, 564], [578, 564]], [[476, 546], [518, 546], [518, 565], [476, 565]], [[353, 545], [379, 545], [379, 566], [353, 566]], [[219, 545], [245, 545], [245, 566], [219, 566]], [[68, 542], [133, 546], [132, 563], [67, 560]], [[68, 478], [133, 482], [132, 499], [67, 496]], [[586, 481], [664, 481], [664, 497], [586, 497]], [[476, 480], [518, 480], [518, 498], [476, 498]], [[354, 480], [395, 480], [395, 498], [354, 498]], [[219, 479], [245, 479], [245, 500], [219, 500]], [[580, 425], [665, 429], [664, 449], [580, 446]], [[346, 429], [410, 429], [410, 447], [346, 447]], [[68, 426], [150, 429], [149, 449], [67, 447]], [[474, 427], [515, 427], [515, 449], [474, 449]], [[218, 427], [259, 427], [259, 449], [218, 449]], [[283, 398], [478, 399], [478, 419], [283, 418]], [[86, 318], [664, 318], [664, 332], [86, 332]], [[65, 279], [665, 279], [665, 292], [65, 292]], [[458, 210], [584, 210], [584, 224], [458, 224]], [[313, 209], [372, 209], [372, 226], [313, 226]], [[164, 209], [225, 209], [225, 226], [164, 226]], [[505, 151], [539, 151], [539, 166], [505, 166]], [[266, 48], [483, 48], [483, 68], [266, 68]]] -00088568.jpg [[[341, 446], [371, 446], [371, 453], [341, 453]], [[58, 445], [117, 445], [117, 455], [58, 455]], [[552, 433], [571, 433], [571, 440], [552, 440]], [[583, 431], [740, 431], [740, 442], [583, 442]], [[311, 415], [743, 415], [743, 428], [311, 428]], [[311, 377], [736, 377], [736, 390], [311, 390]], [[425, 340], [551, 340], [551, 350], [425, 350]], [[287, 324], [294, 332], [289, 337], [281, 330]], [[276, 294], [348, 296], [347, 311], [276, 309]], [[54, 288], [210, 288], [210, 301], [54, 301]], [[275, 265], [421, 265], [421, 278], [275, 278]], [[56, 264], [248, 264], [248, 277], [56, 277]], [[671, 248], [695, 248], [695, 261], [671, 261]], [[602, 248], [628, 248], [628, 261], [602, 261]], [[533, 248], [557, 248], [557, 261], [533, 261]], [[463, 248], [487, 248], [487, 261], [463, 261]], [[278, 248], [309, 248], [309, 260], [278, 260]], [[55, 240], [142, 240], [142, 254], [55, 254]], [[277, 231], [398, 231], [398, 244], [277, 244]], [[741, 228], [749, 237], [742, 245], [733, 236]], [[665, 230], [700, 230], [700, 244], [665, 244]], [[598, 230], [631, 230], [631, 244], [598, 244]], [[528, 230], [562, 230], [562, 244], [528, 244]], [[459, 230], [492, 230], [492, 244], [459, 244]], [[54, 215], [211, 217], [211, 231], [54, 229]], [[739, 211], [749, 221], [740, 229], [731, 220]], [[663, 214], [704, 214], [704, 228], [663, 228]], [[595, 215], [637, 215], [637, 226], [595, 226]], [[524, 215], [569, 215], [569, 226], [524, 226]], [[454, 215], [495, 215], [495, 226], [454, 226]], [[279, 215], [351, 215], [351, 226], [279, 226]], [[736, 199], [747, 199], [747, 208], [736, 208]], [[668, 197], [700, 197], [700, 208], [668, 208]], [[599, 196], [633, 196], [633, 210], [599, 210]], [[529, 197], [562, 197], [562, 208], [529, 208]], [[461, 197], [491, 197], [491, 208], [461, 208]], [[277, 195], [417, 196], [417, 211], [277, 209]], [[55, 192], [239, 192], [239, 205], [55, 205]], [[665, 181], [703, 181], [703, 192], [665, 192]], [[279, 180], [351, 181], [350, 192], [279, 191]], [[734, 180], [747, 180], [747, 193], [734, 193]], [[597, 180], [634, 180], [634, 191], [597, 191]], [[525, 179], [566, 179], [566, 193], [525, 193]], [[458, 180], [493, 180], [493, 191], [458, 191]], [[55, 170], [142, 170], [142, 184], [55, 184]], [[735, 165], [747, 165], [747, 175], [735, 175]], [[665, 163], [703, 163], [703, 175], [665, 175]], [[598, 163], [634, 163], [634, 175], [598, 175]], [[527, 163], [565, 163], [565, 175], [527, 175]], [[458, 163], [492, 163], [492, 175], [458, 175]], [[279, 162], [398, 162], [398, 176], [279, 176]], [[54, 146], [148, 146], [148, 159], [54, 159]], [[453, 147], [495, 147], [495, 158], [453, 158]], [[731, 143], [748, 146], [745, 161], [728, 158]], [[663, 145], [704, 145], [704, 159], [663, 159]], [[596, 146], [635, 146], [635, 157], [596, 157]], [[522, 145], [566, 142], [567, 157], [523, 159]], [[277, 144], [310, 144], [310, 158], [277, 158]], [[276, 121], [428, 121], [428, 139], [276, 139]], [[52, 120], [232, 121], [232, 139], [52, 138]], [[404, 91], [701, 91], [701, 106], [404, 106]], [[48, 79], [280, 79], [280, 97], [48, 97]], [[325, 69], [744, 70], [744, 84], [325, 83]], [[668, 48], [743, 48], [743, 63], [668, 63]], [[297, 48], [433, 48], [433, 62], [297, 62]]] +00067516.jpg [[[141, 808], [594, 809], [594, 822], [141, 821]], [[49, 784], [695, 784], [695, 798], [49, 798]], [[579, 751], [667, 751], [667, 764], [579, 764]], [[355, 750], [395, 750], [395, 767], [355, 767]], [[221, 751], [260, 751], [260, 765], [221, 765]], [[477, 750], [501, 750], [501, 768], [477, 768]], [[69, 748], [133, 751], [132, 765], [68, 761]], [[576, 682], [668, 682], [668, 699], [576, 699]], [[476, 682], [518, 682], [518, 700], [476, 700]], [[354, 682], [395, 682], [395, 700], [354, 700]], [[69, 681], [133, 684], [132, 699], [68, 695]], [[220, 679], [243, 682], [241, 700], [218, 697]], [[577, 615], [667, 615], [667, 632], [577, 632]], [[68, 612], [134, 615], [133, 632], [67, 629]], [[476, 614], [500, 614], [500, 633], [476, 633]], [[354, 613], [378, 613], [378, 634], [354, 634]], [[219, 612], [245, 612], [245, 633], [219, 633]], [[578, 547], [667, 547], [667, 564], [578, 564]], [[476, 546], [518, 546], [518, 565], [476, 565]], [[353, 545], [379, 545], [379, 566], [353, 566]], [[219, 545], [245, 545], [245, 566], [219, 566]], [[68, 542], [133, 546], [132, 563], [67, 560]], [[68, 478], [133, 482], [132, 499], [67, 496]], [[586, 481], [664, 481], [664, 497], [586, 497]], [[476, 480], [518, 480], [518, 498], [476, 498]], [[354, 480], [395, 480], [395, 498], [354, 498]], [[219, 479], [245, 479], [245, 500], [219, 500]], [[580, 425], [665, 429], [664, 449], [580, 446]], [[346, 429], [410, 429], [410, 447], [346, 447]], [[68, 426], [150, 429], [149, 449], [67, 447]], [[474, 427], [515, 427], [515, 449], [474, 449]], [[218, 427], [259, 427], [259, 449], [218, 449]], [[283, 398], [478, 399], [478, 419], [283, 418]], [[86, 318], [664, 318], [664, 332], [86, 332]], [[65, 279], [665, 279], [665, 292], [65, 292]], [[458, 210], [584, 210], [584, 224], [458, 224]], [[312, 209], [371, 209], [371, 226], [312, 226]], [[164, 209], [225, 209], [225, 226], [164, 226]], [[505, 151], [539, 151], [539, 166], [505, 166]], [[266, 48], [483, 48], [483, 68], [266, 68]]] +00088568.jpg [[[341, 446], [371, 446], [371, 453], [341, 453]], [[58, 445], [117, 445], [117, 455], [58, 455]], [[552, 433], [571, 433], [571, 440], [552, 440]], [[583, 431], [740, 431], [740, 442], [583, 442]], [[311, 415], [743, 415], [743, 428], [311, 428]], [[310, 376], [735, 376], [735, 389], [310, 389]], [[425, 340], [551, 340], [551, 350], [425, 350]], [[287, 324], [294, 332], [289, 337], [281, 330]], [[276, 294], [348, 296], [347, 311], [276, 309]], [[54, 288], [210, 288], [210, 301], [54, 301]], [[275, 265], [421, 265], [421, 278], [275, 278]], [[56, 264], [248, 264], [248, 277], [56, 277]], [[671, 248], [695, 248], [695, 261], [671, 261]], [[602, 248], [628, 248], [628, 261], [602, 261]], [[533, 248], [557, 248], [557, 261], [533, 261]], [[463, 248], [487, 248], [487, 261], [463, 261]], [[278, 248], [309, 248], [309, 260], [278, 260]], [[55, 240], [142, 240], [142, 254], [55, 254]], [[277, 231], [398, 231], [398, 244], [277, 244]], [[741, 228], [749, 237], [742, 245], [733, 236]], [[665, 230], [700, 230], [700, 244], [665, 244]], [[598, 230], [631, 230], [631, 244], [598, 244]], [[528, 230], [562, 230], [562, 244], [528, 244]], [[459, 230], [492, 230], [492, 244], [459, 244]], [[54, 215], [211, 217], [211, 231], [54, 229]], [[739, 211], [749, 221], [740, 229], [731, 220]], [[663, 214], [704, 214], [704, 228], [663, 228]], [[595, 215], [637, 215], [637, 226], [595, 226]], [[524, 215], [569, 215], [569, 226], [524, 226]], [[454, 215], [495, 215], [495, 226], [454, 226]], [[279, 215], [351, 215], [351, 226], [279, 226]], [[736, 199], [747, 199], [747, 208], [736, 208]], [[668, 197], [700, 197], [700, 208], [668, 208]], [[599, 196], [633, 196], [633, 210], [599, 210]], [[529, 197], [562, 197], [562, 208], [529, 208]], [[461, 197], [491, 197], [491, 208], [461, 208]], [[277, 195], [417, 196], [417, 211], [277, 209]], [[55, 192], [239, 192], [239, 205], [55, 205]], [[665, 181], [703, 181], [703, 192], [665, 192]], [[279, 180], [351, 181], [350, 192], [279, 191]], [[734, 180], [747, 180], [747, 193], [734, 193]], [[597, 180], [634, 180], [634, 191], [597, 191]], [[525, 179], [566, 179], [566, 193], [525, 193]], [[458, 180], [493, 180], [493, 191], [458, 191]], [[55, 170], [142, 170], [142, 184], [55, 184]], [[735, 165], [747, 165], [747, 175], [735, 175]], [[665, 163], [703, 163], [703, 175], [665, 175]], [[598, 163], [634, 163], [634, 175], [598, 175]], [[527, 163], [565, 163], [565, 175], [527, 175]], [[458, 163], [492, 163], [492, 175], [458, 175]], [[279, 162], [398, 162], [398, 176], [279, 176]], [[54, 146], [148, 146], [148, 159], [54, 159]], [[453, 147], [495, 147], [495, 158], [453, 158]], [[731, 143], [748, 146], [745, 161], [728, 158]], [[663, 145], [704, 145], [704, 159], [663, 159]], [[596, 146], [635, 146], [635, 157], [596, 157]], [[522, 145], [566, 142], [567, 157], [523, 159]], [[277, 144], [310, 144], [310, 158], [277, 158]], [[276, 121], [428, 121], [428, 139], [276, 139]], [[52, 120], [232, 121], [232, 139], [52, 138]], [[404, 91], [701, 91], [701, 106], [404, 106]], [[48, 79], [280, 79], [280, 97], [48, 97]], [[325, 69], [744, 70], [744, 84], [325, 83]], [[668, 48], [743, 48], [743, 63], [668, 63]], [[297, 48], [433, 48], [433, 62], [297, 62]]] 00091741.jpg [[[47, 336], [83, 336], [83, 358], [47, 358]], [[99, 211], [257, 211], [257, 230], [99, 230]], [[103, 190], [257, 191], [257, 205], [103, 204]], [[89, 101], [266, 99], [267, 181], [90, 184]], [[94, 48], [262, 55], [260, 114], [91, 107]], [[91, 12], [257, 14], [257, 37], [90, 35]]] -00105313.jpg [[[291, 262], [406, 262], [406, 275], [291, 275]], [[153, 262], [264, 262], [264, 274], [153, 274]], [[11, 258], [73, 261], [72, 274], [11, 272]], [[33, 231], [132, 231], [132, 244], [33, 244]], [[35, 217], [216, 217], [216, 227], [35, 227]], [[33, 200], [146, 200], [146, 213], [33, 213]], [[32, 183], [215, 184], [215, 197], [32, 196]], [[35, 170], [105, 170], [105, 181], [35, 181]], [[35, 155], [124, 155], [124, 164], [35, 164]], [[34, 137], [142, 138], [142, 149], [34, 148]], [[35, 123], [176, 123], [176, 133], [35, 133]], [[33, 106], [176, 106], [176, 119], [33, 119]], [[34, 92], [102, 92], [102, 102], [34, 102]], [[34, 77], [119, 77], [119, 87], [34, 87]], [[32, 60], [120, 60], [120, 73], [32, 73]], [[35, 46], [119, 46], [119, 55], [35, 55]], [[32, 29], [142, 29], [142, 42], [32, 42]], [[25, 12], [147, 12], [147, 24], [25, 24]]] -00134770.jpg [[[388, 646], [456, 646], [456, 656], [388, 656]], [[407, 620], [484, 619], [485, 633], [408, 634]], [[112, 534], [270, 531], [270, 549], [113, 551]], [[111, 502], [443, 497], [443, 514], [112, 519]], [[111, 471], [443, 467], [443, 484], [112, 488]], [[111, 439], [444, 434], [444, 451], [112, 457]], [[111, 409], [442, 405], [442, 421], [112, 425]], [[153, 376], [441, 373], [441, 390], [153, 394]], [[184, 338], [369, 336], [369, 356], [185, 358]], [[75, 98], [515, 104], [513, 218], [74, 212]]] +00105313.jpg [[[291, 262], [406, 262], [406, 275], [291, 275]], [[153, 262], [264, 262], [264, 274], [153, 274]], [[11, 258], [73, 261], [72, 274], [11, 272]], [[33, 231], [132, 231], [132, 244], [33, 244]], [[35, 217], [216, 217], [216, 227], [35, 227]], [[32, 200], [145, 200], [145, 213], [32, 213]], [[32, 183], [215, 184], [215, 197], [32, 196]], [[35, 170], [105, 170], [105, 181], [35, 181]], [[35, 155], [124, 155], [124, 164], [35, 164]], [[34, 137], [142, 138], [142, 149], [34, 148]], [[35, 123], [176, 123], [176, 133], [35, 133]], [[33, 106], [176, 106], [176, 119], [33, 119]], [[34, 92], [102, 92], [102, 102], [34, 102]], [[34, 77], [119, 77], [119, 87], [34, 87]], [[32, 60], [120, 60], [120, 73], [32, 73]], [[35, 46], [119, 46], [119, 55], [35, 55]], [[32, 29], [142, 29], [142, 42], [32, 42]], [[25, 12], [147, 12], [147, 24], [25, 24]]] +00134770.jpg [[[388, 645], [456, 645], [456, 655], [388, 655]], [[407, 620], [484, 619], [485, 633], [408, 634]], [[112, 534], [270, 531], [270, 549], [113, 551]], [[111, 502], [443, 497], [443, 514], [112, 519]], [[111, 471], [443, 467], [443, 484], [112, 488]], [[111, 439], [444, 434], [444, 451], [112, 457]], [[111, 409], [442, 405], [442, 421], [112, 425]], [[153, 376], [441, 373], [441, 390], [153, 394]], [[184, 338], [369, 336], [369, 356], [185, 358]], [[75, 98], [515, 104], [513, 218], [74, 212]]] 00145943.jpg [[[394, 248], [746, 279], [731, 449], [379, 418]], [[90, 92], [300, 92], [300, 119], [90, 119]], [[46, 41], [326, 39], [326, 75], [46, 77]]] -00147605.jpg [[[804, 615], [874, 616], [874, 627], [804, 626]], [[516, 607], [784, 605], [784, 628], [516, 629]], [[118, 522], [224, 522], [224, 560], [118, 560]], [[253, 524], [307, 524], [307, 557], [253, 557]], [[715, 501], [900, 505], [900, 538], [714, 534]], [[255, 502], [295, 502], [295, 517], [255, 517]], [[347, 481], [473, 481], [473, 515], [347, 515]], [[252, 484], [295, 484], [295, 499], [252, 499]], [[350, 456], [447, 456], [447, 470], [350, 470]], [[145, 444], [201, 444], [201, 467], [145, 467]], [[728, 371], [878, 371], [878, 420], [728, 420]], [[528, 369], [681, 369], [681, 418], [528, 418]], [[143, 369], [488, 369], [488, 420], [143, 420]], [[744, 315], [871, 315], [871, 336], [744, 336]], [[799, 157], [886, 154], [887, 188], [800, 191]], [[274, 142], [455, 142], [455, 160], [274, 160]], [[738, 116], [894, 119], [893, 157], [737, 153]], [[108, 112], [204, 112], [204, 130], [108, 130]], [[270, 92], [463, 96], [462, 132], [270, 129]]] -00150341.jpg [[[100, 645], [298, 645], [298, 662], [100, 662]], [[115, 617], [288, 617], [288, 631], [115, 631]], [[84, 593], [319, 592], [319, 609], [84, 610]], [[31, 565], [313, 562], [314, 580], [31, 582]], [[444, 560], [461, 560], [461, 569], [444, 569]], [[390, 557], [446, 557], [446, 572], [390, 572]], [[31, 515], [168, 515], [168, 529], [31, 529]], [[33, 490], [110, 490], [110, 504], [33, 504]], [[358, 459], [464, 463], [463, 485], [357, 481]], [[28, 459], [268, 460], [268, 481], [28, 480]], [[339, 439], [421, 444], [421, 460], [338, 455]], [[65, 439], [143, 439], [143, 453], [65, 453]], [[207, 416], [292, 416], [292, 434], [207, 434]], [[319, 408], [441, 413], [440, 438], [318, 433]], [[44, 405], [175, 409], [174, 434], [43, 430]], [[31, 383], [137, 383], [137, 404], [31, 404]]] -00150669.jpg [[[649, 700], [681, 700], [681, 716], [649, 716]], [[517, 685], [549, 685], [549, 720], [517, 720]], [[651, 688], [678, 688], [678, 701], [651, 701]], [[862, 687], [876, 687], [876, 695], [862, 695]], [[922, 675], [938, 675], [938, 685], [922, 685]], [[785, 671], [807, 671], [807, 687], [785, 687]], [[592, 672], [606, 672], [606, 686], [592, 686]], [[722, 679], [732, 669], [742, 678], [731, 688]], [[651, 680], [667, 665], [681, 679], [666, 695]], [[273, 667], [422, 667], [422, 688], [273, 688]], [[136, 666], [203, 666], [203, 688], [136, 688]], [[46, 666], [109, 666], [109, 687], [46, 687]], [[782, 629], [810, 629], [810, 661], [782, 661]], [[645, 627], [685, 627], [685, 665], [645, 665]], [[516, 628], [548, 628], [548, 664], [516, 664]], [[655, 619], [672, 619], [672, 627], [655, 627]], [[598, 617], [605, 624], [599, 629], [592, 622]], [[523, 619], [540, 619], [540, 627], [523, 627]], [[858, 618], [868, 618], [868, 627], [858, 627]], [[727, 618], [735, 618], [735, 627], [727, 627]], [[919, 620], [932, 611], [942, 624], [929, 633]], [[786, 616], [805, 616], [805, 629], [786, 629]], [[373, 604], [420, 604], [420, 619], [373, 619]], [[85, 603], [215, 605], [214, 621], [84, 619]], [[48, 603], [71, 603], [71, 622], [48, 622]], [[788, 561], [806, 561], [806, 572], [788, 572]], [[923, 560], [935, 560], [935, 574], [923, 574]], [[856, 560], [869, 560], [869, 574], [856, 574]], [[62, 554], [410, 554], [410, 568], [62, 568]], [[63, 532], [116, 535], [115, 545], [62, 543]], [[859, 527], [868, 527], [868, 539], [859, 539]], [[925, 526], [934, 526], [934, 540], [925, 540]], [[794, 520], [807, 529], [798, 542], [785, 533]], [[526, 526], [535, 526], [535, 536], [526, 536]], [[262, 513], [395, 513], [395, 526], [262, 526]], [[122, 514], [245, 514], [245, 524], [122, 524]], [[49, 514], [119, 514], [119, 525], [49, 525]], [[755, 492], [828, 492], [828, 507], [755, 507]], [[638, 492], [710, 492], [710, 507], [638, 507]], [[519, 492], [592, 492], [592, 507], [519, 507]], [[85, 450], [123, 450], [123, 461], [85, 461]], [[220, 450], [236, 447], [238, 459], [223, 462]], [[683, 445], [868, 445], [868, 459], [683, 459]], [[562, 445], [666, 445], [666, 459], [562, 459]], [[491, 446], [544, 446], [544, 458], [491, 458]], [[183, 437], [208, 437], [208, 459], [183, 459]], [[52, 431], [72, 438], [64, 462], [44, 455]], [[224, 432], [276, 432], [276, 443], [224, 443]], [[88, 432], [144, 432], [144, 443], [88, 443]], [[506, 383], [616, 382], [616, 397], [506, 398]], [[702, 381], [758, 381], [758, 399], [702, 399]], [[308, 373], [364, 373], [364, 384], [308, 384]], [[92, 373], [167, 373], [167, 384], [92, 384]], [[688, 335], [820, 335], [820, 350], [688, 350]], [[498, 335], [657, 335], [657, 350], [498, 350]], [[208, 316], [244, 316], [244, 331], [208, 331]], [[499, 289], [641, 289], [641, 302], [499, 302]], [[671, 287], [801, 287], [801, 301], [671, 301]], [[670, 241], [816, 241], [816, 255], [670, 255]], [[497, 241], [643, 241], [643, 255], [497, 255]], [[670, 194], [815, 194], [815, 208], [670, 208]], [[498, 194], [643, 194], [643, 208], [498, 208]], [[670, 145], [815, 145], [815, 160], [670, 160]], [[499, 145], [645, 145], [645, 160], [499, 160]], [[489, 103], [546, 103], [546, 120], [489, 120]], [[56, 89], [95, 89], [95, 97], [56, 97]], [[845, 26], [887, 20], [889, 39], [848, 44]], [[26, 20], [700, 20], [700, 37], [26, 37]], [[898, 11], [996, 16], [995, 45], [896, 40]]] +00147605.jpg [[[804, 615], [874, 616], [874, 627], [804, 626]], [[516, 607], [784, 605], [784, 628], [516, 629]], [[118, 522], [224, 522], [224, 560], [118, 560]], [[253, 524], [307, 524], [307, 557], [253, 557]], [[715, 501], [900, 505], [900, 538], [714, 534]], [[255, 502], [295, 502], [295, 517], [255, 517]], [[347, 481], [473, 481], [473, 515], [347, 515]], [[252, 484], [295, 484], [295, 499], [252, 499]], [[350, 456], [447, 456], [447, 470], [350, 470]], [[145, 444], [201, 444], [201, 467], [145, 467]], [[728, 371], [878, 371], [878, 420], [728, 420]], [[528, 369], [681, 369], [681, 418], [528, 418]], [[142, 368], [486, 368], [486, 419], [142, 419]], [[744, 315], [871, 315], [871, 336], [744, 336]], [[799, 157], [886, 154], [887, 188], [800, 191]], [[274, 142], [455, 142], [455, 160], [274, 160]], [[738, 116], [894, 119], [893, 157], [737, 153]], [[108, 112], [204, 112], [204, 130], [108, 130]], [[270, 92], [463, 96], [462, 132], [270, 129]]] +00150341.jpg [[[100, 645], [298, 645], [298, 662], [100, 662]], [[115, 617], [288, 617], [288, 631], [115, 631]], [[84, 593], [319, 592], [319, 609], [84, 610]], [[31, 565], [313, 562], [314, 580], [31, 582]], [[444, 560], [461, 560], [461, 569], [444, 569]], [[390, 557], [446, 557], [446, 572], [390, 572]], [[31, 515], [168, 515], [168, 529], [31, 529]], [[33, 490], [110, 490], [110, 504], [33, 504]], [[358, 459], [464, 463], [463, 485], [357, 481]], [[28, 459], [268, 460], [268, 481], [28, 480]], [[339, 439], [421, 444], [421, 460], [338, 455]], [[64, 439], [143, 439], [143, 453], [64, 453]], [[207, 416], [292, 416], [292, 434], [207, 434]], [[319, 408], [441, 413], [440, 438], [318, 433]], [[44, 405], [175, 409], [174, 434], [43, 430]], [[31, 383], [137, 383], [137, 404], [31, 404]]] +00150669.jpg [[[649, 700], [681, 700], [681, 716], [649, 716]], [[517, 685], [549, 685], [549, 720], [517, 720]], [[651, 688], [678, 688], [678, 701], [651, 701]], [[862, 687], [876, 687], [876, 695], [862, 695]], [[922, 675], [938, 675], [938, 685], [922, 685]], [[785, 671], [807, 671], [807, 687], [785, 687]], [[592, 672], [606, 672], [606, 686], [592, 686]], [[722, 679], [732, 669], [742, 678], [731, 688]], [[651, 680], [667, 665], [681, 679], [666, 695]], [[273, 667], [422, 667], [422, 688], [273, 688]], [[136, 666], [203, 666], [203, 688], [136, 688]], [[46, 666], [109, 666], [109, 687], [46, 687]], [[782, 629], [810, 629], [810, 661], [782, 661]], [[645, 627], [685, 627], [685, 665], [645, 665]], [[516, 628], [548, 628], [548, 664], [516, 664]], [[655, 619], [672, 619], [672, 627], [655, 627]], [[598, 617], [605, 624], [599, 629], [592, 622]], [[523, 619], [540, 619], [540, 627], [523, 627]], [[858, 618], [868, 618], [868, 627], [858, 627]], [[727, 618], [735, 618], [735, 627], [727, 627]], [[918, 621], [932, 611], [942, 624], [928, 634]], [[786, 616], [805, 616], [805, 629], [786, 629]], [[373, 604], [420, 604], [420, 619], [373, 619]], [[85, 603], [215, 605], [214, 621], [84, 619]], [[48, 603], [71, 603], [71, 622], [48, 622]], [[788, 561], [806, 561], [806, 572], [788, 572]], [[923, 560], [935, 560], [935, 574], [923, 574]], [[856, 560], [869, 560], [869, 574], [856, 574]], [[62, 553], [409, 553], [409, 567], [62, 567]], [[63, 532], [116, 535], [115, 545], [62, 543]], [[859, 527], [868, 527], [868, 539], [859, 539]], [[925, 526], [934, 526], [934, 540], [925, 540]], [[794, 520], [807, 529], [798, 542], [785, 533]], [[526, 526], [535, 526], [535, 536], [526, 536]], [[262, 513], [395, 513], [395, 526], [262, 526]], [[122, 514], [245, 514], [245, 524], [122, 524]], [[49, 514], [119, 514], [119, 525], [49, 525]], [[755, 492], [828, 492], [828, 507], [755, 507]], [[638, 492], [710, 492], [710, 507], [638, 507]], [[519, 492], [592, 492], [592, 507], [519, 507]], [[85, 450], [123, 450], [123, 461], [85, 461]], [[220, 450], [236, 447], [238, 459], [223, 462]], [[682, 445], [867, 445], [867, 459], [682, 459]], [[562, 445], [666, 445], [666, 459], [562, 459]], [[491, 446], [544, 446], [544, 458], [491, 458]], [[183, 437], [208, 437], [208, 459], [183, 459]], [[52, 431], [72, 438], [64, 462], [44, 455]], [[224, 432], [276, 432], [276, 443], [224, 443]], [[88, 432], [144, 432], [144, 443], [88, 443]], [[506, 383], [616, 382], [616, 397], [506, 398]], [[702, 381], [758, 381], [758, 399], [702, 399]], [[308, 373], [364, 373], [364, 384], [308, 384]], [[91, 372], [166, 372], [166, 383], [91, 383]], [[688, 335], [820, 335], [820, 350], [688, 350]], [[498, 335], [657, 335], [657, 350], [498, 350]], [[208, 316], [244, 316], [244, 331], [208, 331]], [[499, 289], [641, 289], [641, 302], [499, 302]], [[671, 287], [801, 287], [801, 301], [671, 301]], [[670, 241], [816, 241], [816, 255], [670, 255]], [[497, 241], [643, 241], [643, 255], [497, 255]], [[669, 193], [814, 193], [814, 207], [669, 207]], [[498, 193], [643, 193], [643, 207], [498, 207]], [[670, 145], [815, 145], [815, 160], [670, 160]], [[499, 145], [645, 145], [645, 160], [499, 160]], [[489, 103], [546, 103], [546, 120], [489, 120]], [[56, 89], [95, 89], [95, 97], [56, 97]], [[845, 26], [887, 20], [889, 39], [848, 44]], [[26, 20], [700, 20], [700, 37], [26, 37]], [[898, 11], [996, 16], [995, 45], [896, 40]]] 00152568.jpg [[[3, 252], [284, 254], [284, 280], [3, 278]], [[196, 233], [254, 233], [254, 240], [196, 240]], [[49, 229], [90, 229], [90, 240], [49, 240]], [[200, 159], [281, 165], [276, 229], [195, 222]]] 00155628.jpg [[[149, 901], [503, 903], [503, 922], [149, 920]], [[520, 893], [561, 896], [560, 911], [519, 908]], [[61, 885], [81, 885], [81, 894], [61, 894]], [[150, 878], [503, 882], [503, 900], [149, 896]], [[524, 834], [640, 839], [639, 856], [524, 852]], [[70, 834], [185, 835], [185, 853], [69, 852]], [[246, 555], [466, 555], [466, 569], [246, 569]], [[308, 507], [403, 509], [403, 524], [308, 522]], [[244, 482], [459, 484], [459, 502], [244, 500]], [[252, 422], [459, 424], [458, 452], [251, 450]], [[195, 378], [517, 380], [516, 408], [195, 406]], [[474, 194], [624, 196], [624, 210], [473, 208]], [[73, 129], [641, 131], [641, 160], [73, 158]], [[483, 41], [597, 37], [599, 98], [486, 102]], [[68, 25], [135, 16], [139, 43], [72, 52]]] -00173364.jpg [[[8, 178], [57, 178], [57, 200], [8, 200]], [[137, 120], [194, 120], [194, 133], [137, 133]], [[39, 76], [86, 76], [86, 105], [39, 105]], [[249, 20], [310, 20], [310, 36], [249, 36]], [[21, 16], [104, 16], [104, 39], [21, 39]]] +00173364.jpg [[[8, 178], [57, 178], [57, 200], [8, 200]], [[137, 120], [194, 120], [194, 133], [137, 133]], [[39, 76], [86, 76], [86, 105], [39, 105]], [[250, 20], [311, 20], [311, 36], [250, 36]], [[21, 16], [104, 16], [104, 39], [21, 39]]] 00175503.jpg [[[43, 260], [500, 255], [501, 358], [44, 363]], [[52, 200], [349, 178], [354, 251], [58, 273]]] 00193218.jpg [[[283, 375], [410, 375], [410, 388], [283, 388]], [[172, 375], [221, 375], [221, 389], [172, 389]], [[110, 375], [161, 375], [161, 389], [110, 389]], [[276, 358], [357, 358], [357, 371], [276, 371]], [[171, 359], [220, 359], [220, 370], [171, 370]], [[409, 357], [492, 357], [492, 370], [409, 370]], [[26, 187], [62, 187], [62, 202], [26, 202]], [[501, 185], [557, 185], [557, 199], [501, 199]], [[381, 187], [420, 185], [421, 199], [382, 201]], [[284, 186], [310, 186], [310, 201], [284, 201]], [[174, 186], [196, 186], [196, 201], [174, 201]], [[499, 165], [540, 165], [540, 176], [499, 176]], [[381, 164], [409, 164], [409, 177], [381, 177]], [[262, 163], [302, 163], [302, 177], [262, 177]], [[176, 163], [230, 163], [230, 177], [176, 177]], [[26, 163], [79, 163], [79, 177], [26, 177]], [[387, 140], [488, 140], [488, 153], [387, 153]], [[28, 139], [131, 139], [131, 152], [28, 152]], [[443, 117], [537, 119], [537, 133], [443, 132]], [[346, 119], [405, 119], [405, 130], [346, 130]], [[261, 119], [302, 119], [302, 130], [261, 130]], [[30, 113], [228, 116], [228, 131], [30, 129]], [[131, 91], [394, 94], [394, 109], [131, 105]], [[562, 82], [583, 82], [583, 107], [562, 107]]] -00195033.jpg [[[488, 263], [533, 265], [532, 280], [487, 278]], [[126, 250], [192, 250], [192, 283], [126, 283]], [[338, 249], [362, 249], [362, 266], [338, 266]], [[319, 222], [380, 225], [380, 238], [319, 236]], [[431, 224], [450, 224], [450, 235], [431, 235]], [[365, 203], [538, 203], [538, 216], [365, 216]], [[89, 200], [146, 203], [146, 217], [89, 214]], [[329, 201], [354, 201], [354, 212], [329, 212]], [[371, 181], [449, 181], [449, 194], [371, 194]], [[329, 181], [352, 181], [352, 192], [329, 192]], [[96, 179], [240, 179], [240, 193], [96, 193]], [[456, 162], [555, 162], [555, 175], [456, 175]], [[129, 150], [287, 151], [287, 165], [129, 164]], [[36, 145], [73, 149], [72, 163], [35, 159]], [[527, 146], [552, 146], [552, 155], [527, 155]], [[102, 145], [120, 145], [120, 153], [102, 153]], [[371, 129], [503, 128], [503, 139], [371, 140]], [[99, 126], [193, 126], [193, 139], [99, 139]], [[322, 127], [337, 127], [337, 135], [322, 135]], [[37, 123], [77, 123], [77, 134], [37, 134]], [[324, 106], [337, 106], [337, 115], [324, 115]], [[309, 107], [315, 107], [315, 112], [309, 112]], [[372, 103], [501, 103], [501, 116], [372, 116]], [[349, 105], [360, 105], [360, 114], [349, 114]], [[38, 103], [80, 103], [80, 113], [38, 113]], [[99, 100], [205, 101], [205, 115], [99, 114]], [[306, 90], [317, 90], [317, 97], [306, 97]], [[347, 88], [362, 88], [362, 96], [347, 96]], [[321, 87], [340, 87], [340, 99], [321, 99]], [[358, 84], [513, 82], [513, 95], [358, 97]], [[41, 83], [89, 83], [89, 93], [41, 93]], [[94, 79], [241, 80], [241, 94], [94, 93]], [[313, 66], [394, 66], [394, 79], [313, 79]], [[242, 66], [288, 66], [288, 77], [242, 77]], [[185, 54], [220, 54], [220, 65], [185, 65]], [[469, 48], [547, 48], [547, 61], [469, 61]], [[423, 36], [436, 36], [436, 54], [423, 54]], [[465, 30], [551, 30], [551, 43], [465, 43]], [[207, 21], [329, 23], [328, 41], [207, 39]]] -00208502.jpg [[[247, 566], [282, 566], [282, 573], [247, 573]], [[558, 534], [629, 539], [627, 570], [556, 565]], [[205, 540], [284, 540], [284, 552], [205, 552]], [[143, 513], [189, 513], [189, 525], [143, 525]], [[249, 512], [307, 512], [307, 524], [249, 524]], [[44, 500], [118, 500], [118, 519], [44, 519]], [[467, 491], [556, 491], [556, 508], [467, 508]], [[667, 490], [678, 494], [675, 503], [664, 499]], [[788, 489], [794, 495], [789, 499], [783, 494]], [[726, 491], [737, 491], [737, 501], [726, 501]], [[42, 452], [117, 450], [117, 469], [42, 470]], [[175, 450], [236, 450], [236, 464], [175, 464]], [[614, 407], [638, 407], [638, 422], [614, 422]], [[95, 405], [119, 405], [119, 422], [95, 422]], [[49, 399], [64, 414], [50, 427], [36, 413]], [[209, 401], [226, 401], [226, 415], [209, 415]], [[40, 357], [58, 357], [58, 374], [40, 374]], [[94, 356], [119, 356], [119, 373], [94, 373]], [[188, 341], [246, 339], [247, 361], [189, 364]], [[459, 321], [549, 319], [549, 337], [460, 339]], [[459, 273], [551, 273], [551, 290], [459, 290]], [[563, 272], [735, 269], [735, 286], [564, 289]], [[517, 225], [547, 225], [547, 245], [517, 245]], [[459, 226], [480, 226], [480, 244], [459, 244]], [[621, 187], [673, 187], [673, 201], [621, 201]], [[457, 132], [548, 130], [548, 147], [458, 149]], [[572, 106], [787, 99], [787, 120], [573, 126]], [[122, 48], [290, 48], [290, 97], [122, 97]], [[539, 39], [708, 39], [708, 89], [539, 89]]] -00224225.jpg [[[134, 429], [153, 426], [157, 445], [138, 448]], [[202, 404], [478, 411], [476, 459], [201, 452]], [[205, 230], [469, 230], [469, 390], [205, 390]], [[131, 265], [172, 265], [172, 279], [131, 279]], [[345, 207], [456, 207], [456, 231], [345, 231]], [[199, 189], [346, 196], [344, 239], [197, 232]], [[10, 44], [157, 41], [158, 112], [11, 115]]] +00195033.jpg [[[488, 263], [533, 265], [532, 280], [487, 278]], [[126, 250], [192, 250], [192, 283], [126, 283]], [[338, 249], [362, 249], [362, 266], [338, 266]], [[319, 222], [380, 225], [380, 238], [319, 236]], [[431, 224], [450, 224], [450, 235], [431, 235]], [[365, 203], [538, 203], [538, 216], [365, 216]], [[89, 200], [146, 203], [146, 217], [89, 214]], [[329, 201], [354, 201], [354, 212], [329, 212]], [[371, 181], [449, 181], [449, 194], [371, 194]], [[329, 181], [352, 181], [352, 192], [329, 192]], [[96, 179], [240, 179], [240, 193], [96, 193]], [[456, 161], [555, 161], [555, 174], [456, 174]], [[129, 150], [287, 151], [287, 165], [129, 164]], [[36, 145], [73, 149], [72, 163], [35, 159]], [[527, 146], [552, 146], [552, 155], [527, 155]], [[102, 145], [120, 145], [120, 153], [102, 153]], [[371, 129], [503, 128], [503, 139], [371, 140]], [[99, 126], [193, 126], [193, 139], [99, 139]], [[322, 127], [337, 127], [337, 135], [322, 135]], [[37, 123], [77, 123], [77, 134], [37, 134]], [[324, 106], [337, 106], [337, 115], [324, 115]], [[309, 107], [315, 107], [315, 112], [309, 112]], [[372, 103], [501, 103], [501, 116], [372, 116]], [[349, 105], [360, 105], [360, 114], [349, 114]], [[38, 103], [80, 103], [80, 113], [38, 113]], [[99, 100], [205, 101], [205, 115], [99, 114]], [[306, 90], [317, 90], [317, 97], [306, 97]], [[347, 88], [362, 88], [362, 96], [347, 96]], [[321, 87], [340, 87], [340, 99], [321, 99]], [[358, 84], [513, 82], [513, 95], [358, 97]], [[41, 83], [89, 83], [89, 93], [41, 93]], [[94, 79], [241, 80], [241, 94], [94, 93]], [[313, 66], [394, 66], [394, 79], [313, 79]], [[242, 66], [288, 66], [288, 77], [242, 77]], [[185, 54], [220, 54], [220, 65], [185, 65]], [[469, 48], [547, 48], [547, 61], [469, 61]], [[423, 36], [436, 36], [436, 54], [423, 54]], [[465, 30], [551, 30], [551, 43], [465, 43]], [[207, 21], [329, 23], [328, 41], [207, 39]]] +00208502.jpg [[[247, 566], [282, 566], [282, 573], [247, 573]], [[558, 534], [629, 539], [627, 570], [556, 565]], [[205, 540], [284, 540], [284, 552], [205, 552]], [[143, 513], [189, 513], [189, 525], [143, 525]], [[249, 512], [307, 512], [307, 524], [249, 524]], [[44, 500], [118, 500], [118, 519], [44, 519]], [[467, 491], [556, 491], [556, 508], [467, 508]], [[667, 490], [678, 494], [675, 503], [664, 499]], [[788, 489], [794, 495], [789, 499], [783, 494]], [[726, 491], [737, 491], [737, 501], [726, 501]], [[42, 452], [117, 450], [117, 469], [42, 470]], [[175, 450], [236, 450], [236, 464], [175, 464]], [[614, 407], [638, 407], [638, 422], [614, 422]], [[95, 405], [119, 405], [119, 422], [95, 422]], [[49, 399], [63, 413], [49, 427], [35, 414]], [[209, 401], [226, 401], [226, 415], [209, 415]], [[40, 357], [58, 357], [58, 374], [40, 374]], [[94, 356], [119, 356], [119, 373], [94, 373]], [[188, 341], [246, 339], [247, 361], [189, 364]], [[459, 321], [549, 319], [549, 337], [460, 339]], [[459, 273], [551, 273], [551, 290], [459, 290]], [[563, 272], [735, 269], [735, 286], [564, 289]], [[517, 225], [547, 225], [547, 245], [517, 245]], [[459, 226], [480, 226], [480, 244], [459, 244]], [[621, 187], [673, 187], [673, 201], [621, 201]], [[457, 132], [548, 130], [548, 147], [458, 149]], [[572, 106], [787, 99], [787, 120], [573, 126]], [[122, 48], [290, 48], [290, 97], [122, 97]], [[539, 39], [708, 39], [708, 89], [539, 89]]] +00224225.jpg [[[134, 429], [153, 426], [157, 445], [138, 448]], [[202, 404], [478, 411], [476, 459], [201, 452]], [[205, 230], [469, 230], [469, 390], [205, 390]], [[131, 265], [172, 265], [172, 279], [131, 279]], [[344, 207], [455, 207], [455, 231], [344, 231]], [[199, 189], [346, 196], [344, 239], [197, 232]], [[10, 44], [157, 41], [158, 112], [11, 115]]] 00227746.jpg [[[190, 232], [258, 232], [258, 238], [190, 238]], [[160, 232], [183, 232], [183, 238], [160, 238]], [[123, 232], [150, 232], [150, 238], [123, 238]], [[290, 209], [345, 207], [346, 221], [291, 223]], [[172, 181], [249, 181], [249, 194], [172, 194]], [[143, 178], [165, 180], [162, 208], [140, 206]], [[142, 164], [157, 162], [160, 177], [145, 180]], [[173, 157], [203, 157], [203, 164], [173, 164]], [[200, 154], [347, 154], [347, 167], [200, 167]], [[144, 111], [277, 114], [277, 134], [144, 131]], [[201, 52], [387, 53], [386, 69], [201, 68]], [[139, 47], [191, 45], [192, 62], [140, 64]], [[40, 26], [61, 26], [61, 42], [40, 42]]] 00229605.jpg [[[743, 529], [881, 529], [881, 544], [743, 544]], [[236, 499], [589, 498], [589, 522], [236, 523]], [[6, 498], [227, 498], [227, 522], [6, 522]], [[736, 496], [883, 499], [883, 520], [735, 517]], [[606, 495], [716, 489], [718, 515], [608, 521]], [[4, 245], [863, 230], [864, 288], [5, 303]], [[478, 28], [883, 28], [883, 76], [478, 76]]] 00233011.jpg [[[63, 227], [291, 227], [291, 242], [63, 242]], [[12, 219], [41, 219], [41, 250], [12, 250]], [[61, 177], [119, 177], [119, 195], [61, 195]], [[11, 173], [40, 169], [44, 200], [14, 203]], [[61, 129], [147, 131], [147, 147], [61, 144]], [[12, 124], [43, 124], [43, 154], [12, 154]], [[125, 89], [238, 89], [238, 103], [125, 103]], [[148, 51], [216, 51], [216, 65], [148, 65]], [[258, 46], [353, 50], [352, 69], [257, 65]], [[9, 49], [52, 49], [52, 68], [9, 68]], [[277, 12], [345, 12], [345, 31], [277, 31]], [[28, 11], [73, 11], [73, 31], [28, 31]]] 00233625.jpg [[[375, 397], [632, 399], [632, 443], [375, 440]], [[71, 214], [932, 207], [933, 321], [71, 328]]] 00233634.jpg [[[215, 639], [261, 639], [261, 703], [215, 703]], [[523, 635], [570, 635], [570, 695], [523, 695]], [[643, 523], [682, 523], [682, 568], [643, 568]], [[97, 516], [152, 516], [152, 589], [97, 589]], [[755, 395], [760, 395], [760, 401], [755, 401]], [[26, 395], [32, 395], [32, 400], [26, 400]], [[678, 364], [728, 362], [731, 430], [681, 432]], [[54, 361], [107, 361], [107, 434], [54, 434]], [[78, 208], [155, 208], [155, 280], [78, 280]], [[643, 205], [693, 205], [693, 272], [643, 272]], [[210, 88], [260, 86], [263, 164], [213, 166]], [[363, 48], [426, 45], [430, 115], [367, 118]]] -00234400.jpg [[[446, 421], [738, 421], [738, 438], [446, 438]], [[157, 421], [454, 421], [454, 438], [157, 438]], [[158, 394], [652, 394], [652, 411], [158, 411]], [[40, 391], [127, 391], [127, 412], [40, 412]], [[158, 342], [304, 345], [304, 363], [158, 360]], [[38, 344], [123, 344], [123, 362], [38, 362]], [[520, 295], [703, 295], [703, 314], [520, 314]], [[394, 292], [483, 290], [484, 314], [394, 317]], [[157, 293], [270, 293], [270, 313], [157, 313]], [[37, 293], [125, 293], [125, 313], [37, 313]], [[156, 243], [358, 243], [358, 267], [156, 267]], [[36, 243], [82, 243], [82, 269], [36, 269]], [[29, 152], [158, 152], [158, 175], [29, 175]], [[282, 98], [507, 98], [507, 111], [282, 111]], [[315, 46], [475, 50], [474, 88], [314, 85]], [[518, 51], [663, 53], [662, 67], [517, 65]], [[487, 19], [706, 17], [706, 43], [487, 45]]] -00234883.jpg [[[66, 125], [316, 120], [317, 190], [67, 195]], [[79, 138], [109, 141], [108, 152], [78, 148]], [[72, 120], [120, 120], [120, 130], [72, 130]], [[383, 63], [504, 62], [504, 74], [383, 75]], [[58, 29], [365, 26], [366, 112], [59, 115]], [[387, 28], [501, 26], [501, 45], [387, 47]]] +00234400.jpg [[[446, 421], [738, 421], [738, 438], [446, 438]], [[157, 421], [454, 421], [454, 438], [157, 438]], [[158, 394], [652, 394], [652, 411], [158, 411]], [[40, 391], [127, 391], [127, 412], [40, 412]], [[158, 342], [304, 345], [304, 363], [158, 360]], [[38, 344], [123, 344], [123, 362], [38, 362]], [[520, 295], [703, 295], [703, 314], [520, 314]], [[394, 292], [483, 290], [484, 314], [394, 317]], [[157, 293], [270, 293], [270, 313], [157, 313]], [[37, 293], [125, 293], [125, 313], [37, 313]], [[156, 243], [358, 243], [358, 267], [156, 267]], [[36, 243], [82, 243], [82, 269], [36, 269]], [[28, 151], [157, 151], [157, 174], [28, 174]], [[282, 98], [507, 98], [507, 111], [282, 111]], [[315, 46], [475, 50], [474, 88], [314, 85]], [[518, 51], [663, 53], [662, 67], [517, 65]], [[487, 19], [706, 17], [706, 43], [487, 45]]] +00234883.jpg [[[66, 125], [316, 120], [317, 190], [67, 195]], [[79, 138], [109, 140], [108, 151], [78, 148]], [[72, 120], [120, 120], [120, 130], [72, 130]], [[383, 63], [504, 62], [504, 74], [383, 75]], [[58, 29], [365, 26], [366, 112], [59, 115]], [[387, 28], [501, 26], [501, 45], [387, 47]]] test_add_0.jpg [[[311, 521], [391, 521], [391, 534], [311, 534]], [[277, 500], [424, 500], [424, 514], [277, 514]], [[261, 446], [437, 446], [437, 459], [261, 459]], [[212, 428], [485, 428], [485, 441], [212, 441]], [[247, 388], [457, 388], [457, 409], [247, 409]], [[222, 328], [474, 328], [474, 372], [222, 372]], [[208, 207], [492, 211], [490, 277], [207, 272]], [[266, 164], [422, 166], [421, 197], [265, 195]], [[18, 20], [201, 18], [201, 43], [18, 45]]] test_add_1.png [] test_add_10.png [[[157, 124], [186, 124], [186, 172], [157, 172]], [[65, 117], [95, 117], [95, 168], [65, 168]], [[161, 106], [183, 106], [183, 127], [161, 127]], [[69, 100], [94, 100], [94, 128], [69, 128]], [[117, 46], [154, 45], [157, 174], [121, 175]], [[66, 34], [97, 34], [97, 112], [66, 112]]] -test_add_11.jpg [[[1525, 773], [1564, 756], [1575, 780], [1536, 798]], [[1390, 757], [1483, 757], [1483, 791], [1390, 791]], [[1013, 754], [1207, 754], [1207, 800], [1013, 800]], [[685, 755], [875, 755], [875, 796], [685, 796]], [[356, 753], [566, 747], [567, 793], [358, 798]], [[78, 751], [264, 745], [265, 793], [79, 798]], [[602, 647], [1152, 647], [1152, 703], [602, 703]], [[601, 564], [1148, 555], [1149, 611], [602, 620]], [[598, 480], [1066, 472], [1067, 526], [599, 535]], [[598, 393], [1090, 388], [1090, 439], [599, 444]], [[603, 306], [1057, 306], [1057, 357], [603, 357]], [[357, 184], [1517, 184], [1517, 261], [357, 261]], [[60, 43], [257, 37], [259, 83], [61, 89]], [[1305, 41], [1492, 41], [1492, 87], [1305, 87]], [[973, 40], [1171, 34], [1172, 80], [974, 86]], [[670, 40], [862, 34], [864, 80], [671, 86]], [[363, 34], [558, 34], [558, 85], [363, 85]]] +test_add_11.jpg [[[1525, 773], [1564, 756], [1575, 780], [1536, 798]], [[1390, 757], [1483, 757], [1483, 791], [1390, 791]], [[1013, 754], [1207, 754], [1207, 800], [1013, 800]], [[685, 755], [875, 755], [875, 796], [685, 796]], [[356, 753], [566, 747], [567, 793], [358, 798]], [[78, 751], [264, 745], [265, 793], [79, 798]], [[602, 647], [1152, 647], [1152, 703], [602, 703]], [[601, 564], [1148, 555], [1149, 611], [602, 620]], [[598, 480], [1066, 472], [1067, 526], [599, 535]], [[598, 393], [1090, 388], [1090, 439], [599, 444]], [[603, 306], [1057, 306], [1057, 357], [603, 357]], [[357, 184], [1515, 184], [1515, 261], [357, 261]], [[60, 43], [257, 37], [259, 83], [61, 89]], [[1305, 41], [1492, 41], [1492, 87], [1305, 87]], [[973, 40], [1171, 34], [1172, 80], [974, 86]], [[670, 40], [862, 34], [864, 80], [671, 86]], [[363, 34], [558, 34], [558, 85], [363, 85]]] test_add_12.jpg [[[11, 592], [136, 594], [135, 613], [11, 611]], [[109, 521], [907, 526], [907, 569], [109, 565]], [[635, 451], [902, 448], [903, 478], [635, 481]], [[112, 447], [466, 449], [466, 486], [112, 483]], [[582, 306], [680, 304], [681, 348], [583, 351]], [[369, 261], [565, 266], [563, 357], [367, 353]], [[64, 85], [853, 88], [853, 161], [64, 159]]] test_add_13.jpg [[[68, 94], [117, 97], [116, 114], [67, 111]]] test_add_14.jpg [[[30, 97], [235, 95], [236, 127], [31, 129]], [[30, 52], [239, 50], [239, 86], [30, 87]]] test_add_15.jpg [[[141, 253], [353, 253], [353, 266], [141, 266]], [[205, 214], [406, 219], [406, 232], [204, 227]], [[106, 212], [193, 213], [193, 227], [106, 226]], [[154, 156], [286, 161], [286, 174], [154, 170]], [[148, 136], [305, 142], [305, 156], [147, 150]], [[108, 137], [145, 137], [145, 148], [108, 148]], [[108, 102], [275, 109], [275, 125], [107, 117]], [[107, 72], [245, 79], [245, 96], [106, 88]], [[107, 39], [209, 42], [209, 62], [106, 59]]] -test_add_16.jpg [[[398, 842], [408, 842], [408, 852], [398, 852]], [[382, 742], [746, 742], [746, 776], [382, 776]], [[362, 703], [468, 703], [468, 725], [362, 725]], [[1552, 701], [1576, 701], [1576, 746], [1552, 746]], [[1256, 695], [1442, 695], [1442, 721], [1256, 721]], [[1244, 661], [1448, 661], [1448, 687], [1244, 687]], [[386, 645], [668, 645], [668, 679], [386, 679]], [[1226, 625], [1470, 623], [1470, 651], [1226, 653]], [[360, 604], [580, 604], [580, 629], [360, 629]], [[1202, 592], [1494, 592], [1494, 617], [1202, 617]], [[1166, 556], [1530, 556], [1530, 582], [1166, 582]], [[380, 552], [638, 552], [638, 586], [380, 586]], [[356, 502], [516, 502], [516, 536], [356, 536]], [[774, 260], [1124, 260], [1124, 300], [774, 300]], [[374, 210], [504, 210], [504, 300], [374, 300]], [[776, 212], [1088, 217], [1088, 252], [776, 248]]] +test_add_16.jpg [[[398, 842], [408, 842], [408, 852], [398, 852]], [[382, 741], [746, 741], [746, 774], [382, 774]], [[362, 703], [468, 703], [468, 725], [362, 725]], [[1552, 701], [1576, 701], [1576, 746], [1552, 746]], [[1256, 695], [1442, 695], [1442, 721], [1256, 721]], [[1244, 661], [1448, 661], [1448, 687], [1244, 687]], [[386, 645], [668, 645], [668, 679], [386, 679]], [[1226, 625], [1470, 623], [1470, 651], [1226, 653]], [[360, 604], [580, 604], [580, 629], [360, 629]], [[1202, 592], [1494, 592], [1494, 617], [1202, 617]], [[1166, 556], [1530, 556], [1530, 582], [1166, 582]], [[380, 552], [638, 552], [638, 586], [380, 586]], [[356, 502], [516, 502], [516, 536], [356, 536]], [[774, 260], [1124, 260], [1124, 300], [774, 300]], [[374, 210], [504, 210], [504, 300], [374, 300]], [[776, 212], [1088, 217], [1088, 252], [776, 248]]] test_add_17.jpg [[[321, 255], [393, 258], [392, 271], [320, 269]], [[307, 222], [411, 228], [411, 241], [306, 236]], [[96, 137], [385, 143], [384, 206], [94, 201]], [[72, 95], [399, 103], [398, 124], [71, 117]], [[68, 76], [224, 79], [223, 93], [67, 90]], [[66, 59], [226, 62], [225, 76], [65, 74]]] test_add_18.jpg [[[466, 788], [715, 790], [715, 813], [466, 811]], [[553, 752], [665, 757], [663, 791], [552, 786]], [[119, 539], [189, 539], [189, 570], [119, 570]], [[116, 473], [674, 486], [673, 528], [115, 516]], [[121, 429], [669, 441], [668, 470], [121, 457]], [[122, 376], [673, 383], [673, 409], [122, 402]], [[556, 262], [675, 264], [675, 278], [556, 277]], [[165, 259], [335, 259], [335, 273], [165, 273]], [[344, 195], [456, 197], [455, 220], [343, 217]], [[309, 175], [490, 175], [490, 190], [309, 190]], [[255, 128], [537, 131], [537, 169], [254, 165]], [[347, 92], [486, 94], [486, 109], [346, 107]], [[285, 41], [567, 49], [566, 82], [284, 74]], [[236, 32], [266, 32], [266, 60], [236, 60]]] -test_add_19.jpg [[[24, 294], [42, 294], [42, 302], [24, 302]], [[64, 293], [105, 293], [105, 303], [64, 303]], [[145, 287], [163, 287], [163, 304], [145, 304]], [[63, 280], [106, 280], [106, 290], [63, 290]], [[9, 281], [26, 281], [26, 288], [9, 288]], [[220, 279], [245, 279], [245, 291], [220, 291]], [[177, 279], [208, 279], [208, 290], [177, 290]], [[23, 279], [51, 279], [51, 290], [23, 290]], [[145, 278], [162, 278], [162, 292], [145, 292]], [[8, 267], [18, 267], [18, 276], [8, 276]], [[221, 265], [243, 265], [243, 277], [221, 277]], [[24, 265], [47, 265], [47, 277], [24, 277]], [[142, 263], [163, 263], [163, 279], [142, 279]], [[218, 252], [249, 252], [249, 265], [218, 265]], [[65, 253], [131, 253], [131, 263], [65, 263]], [[24, 252], [43, 252], [43, 264], [24, 264]], [[8, 253], [18, 253], [18, 262], [8, 262]], [[8, 240], [17, 240], [17, 249], [8, 249]], [[63, 237], [114, 237], [114, 251], [63, 251]], [[25, 236], [47, 239], [45, 251], [23, 249]], [[144, 234], [166, 237], [163, 253], [142, 249]], [[494, 226], [531, 226], [531, 239], [494, 239]], [[335, 226], [354, 226], [354, 237], [335, 237]], [[288, 226], [314, 226], [314, 237], [288, 237]], [[63, 226], [113, 226], [113, 236], [63, 236]], [[7, 227], [17, 227], [17, 234], [7, 234]], [[221, 225], [248, 225], [248, 235], [221, 235]], [[143, 225], [165, 222], [167, 234], [145, 237]], [[24, 224], [48, 224], [48, 238], [24, 238]], [[495, 213], [524, 213], [524, 224], [495, 224]], [[420, 212], [437, 212], [437, 225], [420, 225]], [[336, 212], [398, 212], [398, 223], [336, 223]], [[292, 212], [320, 212], [320, 223], [292, 223]], [[222, 212], [249, 212], [249, 223], [222, 223]], [[145, 212], [166, 212], [166, 223], [145, 223]], [[61, 211], [113, 209], [114, 222], [62, 224]], [[26, 211], [48, 211], [48, 223], [26, 223]], [[337, 199], [383, 199], [383, 209], [337, 209]], [[65, 200], [87, 200], [87, 207], [65, 207]], [[493, 197], [541, 197], [541, 211], [493, 211]], [[445, 202], [455, 196], [462, 206], [452, 212]], [[178, 198], [205, 198], [205, 208], [178, 208]], [[146, 199], [157, 199], [157, 208], [146, 208]], [[32, 194], [43, 204], [33, 214], [22, 203]], [[422, 193], [440, 201], [432, 215], [415, 207]], [[65, 186], [132, 186], [132, 196], [65, 196]], [[337, 185], [399, 185], [399, 196], [337, 196]], [[445, 190], [456, 182], [465, 191], [454, 200]], [[292, 188], [308, 182], [313, 193], [297, 200]], [[220, 183], [255, 183], [255, 197], [220, 197]], [[142, 184], [158, 184], [158, 197], [142, 197]], [[493, 182], [518, 182], [518, 197], [493, 197]], [[425, 180], [437, 191], [427, 202], [414, 190]], [[32, 179], [42, 189], [32, 199], [22, 189]], [[182, 179], [195, 185], [188, 198], [175, 192]], [[335, 172], [400, 169], [400, 183], [336, 185]], [[492, 170], [519, 170], [519, 185], [492, 185]], [[412, 177], [428, 164], [440, 178], [425, 190]], [[293, 171], [315, 171], [315, 185], [293, 185]], [[220, 170], [251, 170], [251, 184], [220, 184]], [[178, 172], [188, 172], [188, 183], [178, 183]], [[64, 172], [125, 170], [125, 181], [64, 182]], [[454, 168], [464, 176], [454, 185], [445, 176]], [[142, 172], [159, 168], [163, 180], [145, 185]], [[30, 165], [43, 174], [34, 186], [20, 177]], [[493, 160], [523, 160], [523, 170], [493, 170]], [[402, 161], [435, 161], [435, 168], [402, 168]], [[335, 159], [401, 159], [401, 169], [335, 169]], [[296, 159], [325, 159], [325, 170], [296, 170]], [[221, 158], [251, 158], [251, 169], [221, 169]], [[174, 161], [183, 156], [190, 167], [181, 172]], [[145, 158], [162, 158], [162, 170], [145, 170]], [[61, 158], [125, 157], [125, 168], [62, 169]], [[20, 161], [33, 154], [40, 167], [28, 174]], [[492, 143], [542, 143], [542, 157], [492, 157]], [[450, 144], [479, 144], [479, 157], [450, 157]], [[335, 143], [439, 143], [439, 156], [335, 156]], [[294, 143], [327, 143], [327, 157], [294, 157]], [[220, 143], [253, 143], [253, 157], [220, 157]], [[178, 145], [187, 145], [187, 156], [178, 156]], [[63, 144], [104, 144], [104, 155], [63, 155]], [[144, 140], [164, 145], [160, 159], [141, 154]], [[31, 137], [44, 149], [31, 162], [17, 149]], [[286, 135], [291, 135], [291, 140], [286, 140]], [[177, 133], [193, 133], [193, 144], [177, 144]], [[336, 132], [388, 132], [388, 141], [336, 141]], [[492, 131], [525, 131], [525, 141], [492, 141]], [[450, 131], [477, 131], [477, 141], [450, 141]], [[292, 131], [321, 131], [321, 141], [292, 141]], [[218, 132], [255, 130], [256, 141], [219, 144]], [[63, 131], [95, 131], [95, 141], [63, 141]], [[417, 130], [437, 130], [437, 141], [417, 141]], [[145, 130], [159, 130], [159, 143], [145, 143]], [[30, 124], [43, 133], [32, 147], [19, 138]], [[493, 118], [535, 118], [535, 129], [493, 129]], [[336, 118], [388, 118], [388, 129], [336, 129]], [[218, 118], [255, 118], [255, 128], [218, 128]], [[451, 117], [478, 117], [478, 129], [451, 129]], [[418, 117], [438, 117], [438, 130], [418, 130]], [[177, 116], [209, 116], [209, 130], [177, 130]], [[145, 117], [162, 117], [162, 130], [145, 130]], [[62, 116], [88, 116], [88, 131], [62, 131]], [[19, 121], [33, 111], [43, 124], [29, 134]], [[491, 107], [523, 107], [523, 113], [491, 113]], [[449, 107], [477, 107], [477, 113], [449, 113]], [[420, 107], [436, 107], [436, 113], [420, 113]], [[295, 107], [319, 107], [319, 114], [295, 114]], [[220, 107], [242, 107], [242, 113], [220, 113]], [[176, 107], [203, 107], [203, 113], [176, 113]], [[145, 107], [161, 107], [161, 114], [145, 114]], [[334, 105], [372, 105], [372, 114], [334, 114]], [[63, 106], [86, 106], [86, 113], [63, 113]], [[483, 89], [522, 89], [522, 99], [483, 99]], [[331, 88], [380, 88], [380, 99], [331, 99]], [[276, 88], [325, 88], [325, 99], [276, 99]], [[214, 88], [246, 88], [246, 99], [214, 99]], [[411, 86], [474, 86], [474, 100], [411, 100]], [[6, 86], [102, 86], [102, 100], [6, 100]], [[415, 66], [461, 66], [461, 77], [415, 77]], [[288, 66], [333, 66], [333, 77], [288, 77]], [[157, 64], [206, 64], [206, 78], [157, 78]], [[416, 48], [523, 49], [523, 63], [415, 62]], [[288, 49], [375, 49], [375, 63], [288, 63]], [[159, 49], [269, 49], [269, 62], [159, 62]], [[24, 53], [36, 46], [45, 59], [33, 67]], [[416, 36], [481, 36], [481, 46], [416, 46]], [[25, 38], [39, 32], [46, 46], [33, 52]], [[157, 34], [205, 34], [205, 47], [157, 47]], [[412, 4], [527, 4], [527, 17], [412, 17]], [[146, 4], [345, 2], [345, 15], [146, 17]]] -test_add_20.jpg [[[31, 346], [605, 346], [605, 370], [31, 370]], [[217, 294], [510, 294], [510, 322], [217, 322]], [[473, 271], [525, 271], [525, 286], [473, 286]], [[220, 267], [287, 267], [287, 286], [220, 286]], [[219, 239], [484, 239], [484, 263], [219, 263]], [[221, 217], [303, 217], [303, 234], [221, 234]], [[402, 192], [417, 192], [417, 205], [402, 205]], [[222, 187], [341, 187], [341, 207], [222, 207]], [[221, 162], [287, 162], [287, 180], [221, 180]], [[375, 122], [475, 124], [475, 146], [375, 143]], [[222, 124], [356, 122], [356, 143], [222, 146]], [[218, 81], [352, 84], [352, 116], [218, 113]], [[440, 35], [605, 35], [605, 60], [440, 60]], [[72, 16], [398, 16], [398, 44], [72, 44]]] +test_add_19.jpg [[[24, 294], [42, 294], [42, 302], [24, 302]], [[64, 293], [105, 293], [105, 303], [64, 303]], [[145, 287], [163, 287], [163, 304], [145, 304]], [[63, 280], [106, 280], [106, 290], [63, 290]], [[9, 281], [26, 281], [26, 288], [9, 288]], [[220, 279], [245, 279], [245, 291], [220, 291]], [[177, 279], [208, 279], [208, 290], [177, 290]], [[23, 279], [51, 279], [51, 290], [23, 290]], [[145, 278], [162, 278], [162, 292], [145, 292]], [[8, 267], [18, 267], [18, 276], [8, 276]], [[221, 265], [243, 265], [243, 277], [221, 277]], [[24, 265], [47, 265], [47, 277], [24, 277]], [[142, 263], [163, 263], [163, 279], [142, 279]], [[218, 252], [249, 252], [249, 265], [218, 265]], [[65, 253], [131, 253], [131, 263], [65, 263]], [[24, 252], [43, 252], [43, 264], [24, 264]], [[8, 253], [18, 253], [18, 262], [8, 262]], [[8, 240], [17, 240], [17, 249], [8, 249]], [[63, 237], [114, 237], [114, 251], [63, 251]], [[25, 236], [47, 239], [45, 251], [23, 249]], [[144, 234], [166, 237], [163, 253], [142, 249]], [[494, 226], [531, 226], [531, 239], [494, 239]], [[335, 226], [354, 226], [354, 237], [335, 237]], [[288, 226], [314, 226], [314, 237], [288, 237]], [[63, 226], [113, 226], [113, 236], [63, 236]], [[7, 227], [17, 227], [17, 234], [7, 234]], [[221, 225], [248, 225], [248, 235], [221, 235]], [[143, 225], [165, 222], [167, 234], [145, 237]], [[24, 224], [48, 224], [48, 238], [24, 238]], [[495, 213], [524, 213], [524, 224], [495, 224]], [[420, 212], [437, 212], [437, 225], [420, 225]], [[336, 212], [398, 212], [398, 223], [336, 223]], [[292, 212], [320, 212], [320, 223], [292, 223]], [[222, 212], [249, 212], [249, 223], [222, 223]], [[145, 212], [166, 212], [166, 223], [145, 223]], [[61, 211], [113, 209], [114, 222], [62, 224]], [[26, 211], [48, 211], [48, 223], [26, 223]], [[337, 199], [383, 199], [383, 209], [337, 209]], [[65, 200], [87, 200], [87, 207], [65, 207]], [[493, 197], [541, 197], [541, 211], [493, 211]], [[445, 202], [455, 196], [462, 206], [452, 212]], [[178, 198], [205, 198], [205, 208], [178, 208]], [[146, 199], [157, 199], [157, 208], [146, 208]], [[32, 194], [43, 204], [33, 214], [22, 203]], [[422, 193], [440, 201], [432, 215], [415, 207]], [[64, 186], [131, 186], [131, 196], [64, 196]], [[337, 185], [399, 185], [399, 196], [337, 196]], [[445, 190], [456, 182], [465, 191], [454, 200]], [[292, 188], [308, 182], [313, 193], [297, 200]], [[220, 183], [255, 183], [255, 197], [220, 197]], [[142, 184], [158, 184], [158, 197], [142, 197]], [[493, 182], [518, 182], [518, 197], [493, 197]], [[425, 180], [437, 191], [427, 202], [414, 190]], [[32, 179], [42, 189], [32, 199], [22, 189]], [[182, 179], [196, 185], [188, 199], [175, 193]], [[335, 172], [400, 169], [400, 183], [336, 185]], [[492, 170], [519, 170], [519, 185], [492, 185]], [[412, 177], [428, 164], [440, 178], [425, 190]], [[293, 171], [315, 171], [315, 185], [293, 185]], [[220, 170], [251, 170], [251, 184], [220, 184]], [[178, 172], [188, 172], [188, 183], [178, 183]], [[64, 172], [125, 170], [125, 181], [64, 182]], [[454, 168], [464, 176], [454, 185], [445, 176]], [[145, 168], [163, 172], [159, 185], [142, 180]], [[30, 165], [43, 174], [34, 186], [20, 177]], [[493, 160], [523, 160], [523, 170], [493, 170]], [[402, 161], [435, 161], [435, 168], [402, 168]], [[335, 159], [401, 159], [401, 169], [335, 169]], [[296, 159], [325, 159], [325, 170], [296, 170]], [[221, 158], [251, 158], [251, 169], [221, 169]], [[174, 161], [183, 156], [190, 167], [181, 172]], [[145, 158], [162, 158], [162, 170], [145, 170]], [[61, 158], [125, 157], [125, 168], [62, 169]], [[20, 161], [33, 154], [40, 167], [28, 174]], [[492, 143], [542, 143], [542, 157], [492, 157]], [[450, 144], [479, 144], [479, 157], [450, 157]], [[335, 143], [439, 143], [439, 156], [335, 156]], [[294, 143], [327, 143], [327, 157], [294, 157]], [[220, 143], [253, 143], [253, 157], [220, 157]], [[178, 145], [187, 145], [187, 156], [178, 156]], [[63, 144], [104, 144], [104, 155], [63, 155]], [[144, 140], [164, 145], [160, 159], [141, 154]], [[31, 137], [44, 149], [31, 162], [17, 149]], [[286, 135], [291, 135], [291, 140], [286, 140]], [[177, 133], [193, 133], [193, 144], [177, 144]], [[336, 132], [388, 132], [388, 141], [336, 141]], [[492, 131], [525, 131], [525, 141], [492, 141]], [[450, 131], [477, 131], [477, 141], [450, 141]], [[292, 131], [321, 131], [321, 141], [292, 141]], [[218, 132], [255, 130], [256, 141], [219, 144]], [[63, 131], [95, 131], [95, 141], [63, 141]], [[417, 130], [437, 130], [437, 141], [417, 141]], [[145, 130], [159, 130], [159, 143], [145, 143]], [[30, 124], [43, 133], [32, 147], [19, 138]], [[493, 118], [535, 118], [535, 129], [493, 129]], [[335, 118], [387, 118], [387, 129], [335, 129]], [[218, 118], [255, 118], [255, 128], [218, 128]], [[451, 117], [478, 117], [478, 129], [451, 129]], [[418, 117], [438, 117], [438, 130], [418, 130]], [[177, 116], [209, 116], [209, 130], [177, 130]], [[145, 117], [162, 117], [162, 130], [145, 130]], [[62, 116], [88, 116], [88, 131], [62, 131]], [[19, 121], [33, 111], [43, 124], [29, 134]], [[491, 107], [523, 107], [523, 113], [491, 113]], [[449, 107], [477, 107], [477, 113], [449, 113]], [[420, 107], [436, 107], [436, 113], [420, 113]], [[295, 107], [319, 107], [319, 114], [295, 114]], [[220, 107], [242, 107], [242, 113], [220, 113]], [[176, 107], [203, 107], [203, 113], [176, 113]], [[145, 107], [161, 107], [161, 114], [145, 114]], [[334, 105], [372, 105], [372, 114], [334, 114]], [[63, 106], [86, 106], [86, 113], [63, 113]], [[483, 89], [522, 89], [522, 99], [483, 99]], [[331, 88], [380, 88], [380, 99], [331, 99]], [[276, 88], [325, 88], [325, 99], [276, 99]], [[214, 88], [246, 88], [246, 99], [214, 99]], [[411, 86], [474, 86], [474, 100], [411, 100]], [[6, 86], [102, 86], [102, 100], [6, 100]], [[415, 66], [461, 66], [461, 77], [415, 77]], [[288, 66], [333, 66], [333, 77], [288, 77]], [[157, 64], [206, 64], [206, 78], [157, 78]], [[33, 61], [43, 66], [37, 77], [27, 72]], [[416, 48], [523, 49], [523, 63], [415, 62]], [[288, 49], [375, 49], [375, 63], [288, 63]], [[159, 49], [269, 49], [269, 62], [159, 62]], [[24, 53], [36, 46], [45, 59], [33, 67]], [[416, 36], [481, 36], [481, 46], [416, 46]], [[25, 38], [39, 32], [46, 45], [32, 52]], [[157, 34], [205, 34], [205, 47], [157, 47]], [[412, 4], [527, 4], [527, 17], [412, 17]], [[146, 4], [345, 2], [345, 15], [146, 17]]] +test_add_20.jpg [[[31, 346], [605, 346], [605, 370], [31, 370]], [[217, 294], [510, 294], [510, 322], [217, 322]], [[473, 271], [525, 271], [525, 286], [473, 286]], [[220, 267], [287, 267], [287, 286], [220, 286]], [[219, 239], [484, 239], [484, 263], [219, 263]], [[221, 217], [303, 217], [303, 234], [221, 234]], [[402, 192], [417, 192], [417, 205], [402, 205]], [[222, 187], [341, 187], [341, 207], [222, 207]], [[221, 162], [287, 162], [287, 180], [221, 180]], [[375, 122], [475, 124], [475, 146], [375, 143]], [[222, 124], [356, 122], [356, 143], [222, 146]], [[218, 81], [352, 84], [352, 116], [218, 113]], [[440, 34], [605, 34], [605, 59], [440, 59]], [[72, 16], [398, 16], [398, 44], [72, 44]]] test_add_3.jpg [[[169, 327], [337, 326], [337, 341], [169, 342]], [[170, 288], [307, 290], [307, 312], [170, 310]], [[171, 221], [323, 221], [323, 234], [171, 234]], [[340, 221], [449, 217], [449, 231], [341, 234]], [[169, 201], [372, 201], [372, 214], [169, 214]], [[170, 183], [418, 183], [418, 196], [170, 196]], [[170, 149], [416, 149], [416, 163], [170, 163]], [[171, 119], [418, 119], [418, 140], [171, 140]], [[326, 64], [478, 64], [478, 91], [326, 91]], [[173, 64], [306, 60], [306, 89], [174, 93]]] test_add_4.png [] test_add_5.png [[[48, 164], [108, 164], [108, 174], [48, 174]], [[52, 121], [169, 121], [169, 134], [52, 134]], [[50, 102], [165, 102], [165, 118], [50, 118]], [[52, 83], [164, 83], [164, 100], [52, 100]], [[51, 68], [166, 68], [166, 84], [51, 84]], [[51, 50], [145, 47], [145, 64], [52, 67]]] test_add_6.jpg [[[123, 223], [219, 227], [218, 251], [122, 247]], [[172, 172], [186, 186], [172, 200], [158, 186]]] -test_add_7.jpg [[[48, 938], [174, 936], [174, 962], [48, 964]], [[227, 873], [629, 876], [628, 953], [226, 949]], [[56, 745], [638, 745], [638, 790], [56, 790]], [[150, 674], [545, 678], [544, 721], [150, 718]], [[73, 504], [633, 504], [633, 601], [73, 601]], [[59, 270], [655, 279], [652, 441], [56, 432]], [[513, 193], [553, 193], [553, 223], [513, 223]], [[61, 175], [532, 175], [532, 239], [61, 239]], [[533, 178], [642, 178], [642, 236], [533, 236]]] +test_add_7.jpg [[[48, 938], [174, 936], [174, 962], [48, 964]], [[227, 873], [629, 876], [628, 953], [226, 949]], [[56, 744], [637, 744], [637, 789], [56, 789]], [[150, 674], [545, 678], [544, 721], [150, 718]], [[73, 504], [633, 504], [633, 601], [73, 601]], [[59, 270], [655, 279], [652, 441], [56, 432]], [[513, 193], [553, 193], [553, 223], [513, 223]], [[61, 175], [532, 175], [532, 239], [61, 239]], [[533, 178], [642, 178], [642, 236], [533, 236]]] test_add_8.jpg [[[251, 586], [454, 580], [454, 606], [252, 613]], [[107, 533], [457, 527], [457, 560], [108, 566]], [[336, 494], [384, 494], [384, 507], [336, 507]], [[27, 307], [355, 297], [356, 320], [28, 330]], [[22, 259], [445, 251], [445, 274], [23, 282]], [[78, 209], [445, 205], [445, 225], [78, 229]], [[160, 23], [319, 30], [317, 79], [158, 72]]] -test_add_9.png [[[266, 687], [486, 687], [486, 696], [266, 696]], [[196, 668], [554, 668], [554, 681], [196, 681]], [[154, 596], [597, 596], [597, 606], [154, 606]], [[215, 578], [541, 578], [541, 588], [215, 588]], [[85, 543], [665, 543], [665, 553], [85, 553]], [[96, 522], [653, 522], [653, 535], [96, 535]], [[362, 449], [389, 449], [389, 460], [362, 460]], [[238, 376], [513, 376], [513, 389], [238, 389]], [[177, 356], [574, 356], [574, 368], [177, 368]], [[344, 281], [408, 283], [407, 297], [343, 294]], [[257, 205], [493, 205], [493, 219], [257, 219]]] +test_add_9.png [[[266, 687], [486, 687], [486, 696], [266, 696]], [[196, 668], [554, 668], [554, 681], [196, 681]], [[153, 596], [597, 596], [597, 606], [153, 606]], [[215, 578], [541, 578], [541, 588], [215, 588]], [[85, 542], [664, 542], [664, 552], [85, 552]], [[96, 522], [653, 522], [653, 535], [96, 535]], [[362, 449], [389, 449], [389, 460], [362, 460]], [[238, 376], [513, 376], [513, 389], [238, 389]], [[177, 356], [574, 356], [574, 368], [177, 368]], [[344, 281], [408, 283], [407, 297], [343, 294]], [[256, 205], [492, 205], [492, 219], [256, 219]]] From 38fb2ba3c99edcb6da322239f3f781e22cbec5a2 Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 7 Sep 2021 11:31:23 +0000 Subject: [PATCH 64/77] update rec postprocess --- ppocr/postprocess/rec_postprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppocr/postprocess/rec_postprocess.py b/ppocr/postprocess/rec_postprocess.py index 39ef16ecfb..6ff375eb43 100644 --- a/ppocr/postprocess/rec_postprocess.py +++ b/ppocr/postprocess/rec_postprocess.py @@ -536,7 +536,7 @@ class SARLabelDecode(BaseRecLabelDecode): super(SARLabelDecode, self).__init__(character_dict_path, character_type, use_space_char) - self.rm_symbol = kwargs.get('rm_symbol', True) + self.rm_symbol = kwargs.get('rm_symbol', False) def add_special_char(self, dict_character): beg_end_str = "" From 0368e7a67806083862c38d50ae4c129075c80931 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 7 Sep 2021 12:54:10 +0000 Subject: [PATCH 65/77] set batch dim dynamic --- tools/infer/utility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 7f60773c3e..466f824c29 100755 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -236,11 +236,11 @@ def create_predictor(args, mode, logger): max_input_shape.update(max_pact_shape) opt_input_shape.update(opt_pact_shape) elif mode == "rec": - min_input_shape = {"x": [args.rec_batch_num, 3, 32, 10]} + min_input_shape = {"x": [1, 3, 32, 10]} max_input_shape = {"x": [args.rec_batch_num, 3, 32, 2000]} opt_input_shape = {"x": [args.rec_batch_num, 3, 32, 320]} elif mode == "cls": - min_input_shape = {"x": [args.rec_batch_num, 3, 48, 10]} + min_input_shape = {"x": [1, 3, 48, 10]} max_input_shape = {"x": [args.rec_batch_num, 3, 48, 2000]} opt_input_shape = {"x": [args.rec_batch_num, 3, 48, 320]} else: From b9c73d9a72b05ab7afd1fab0f3f46c7f8eed61ce Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Tue, 7 Sep 2021 13:16:35 +0000 Subject: [PATCH 66/77] support rec for cpp cice --- deploy/cpp_infer/src/main.cpp | 63 +++++++++++++++++++++++++++-------- tests/ocr_rec_params.txt | 15 +++++++++ tests/prepare.sh | 17 +++++++++- 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/deploy/cpp_infer/src/main.cpp b/deploy/cpp_infer/src/main.cpp index 6e8ded7f8d..3165b72ddc 100644 --- a/deploy/cpp_infer/src/main.cpp +++ b/deploy/cpp_infer/src/main.cpp @@ -148,12 +148,28 @@ int main_rec(std::vector cv_all_img_names) { time_info[1] += rec_times[1]; time_info[2] += rec_times[2]; } - + + if (FLAGS_benchmark) { + AutoLogger autolog("ocr_rec", + FLAGS_use_gpu, + FLAGS_use_tensorrt, + FLAGS_enable_mkldnn, + FLAGS_cpu_threads, + 1, + "dynamic", + FLAGS_precision, + time_info, + cv_all_img_names.size()); + autolog.report(); + } return 0; } int main_system(std::vector cv_all_img_names) { + std::vector time_info_det = {0, 0, 0}; + std::vector time_info_rec = {0, 0, 0}; + DBDetector det(FLAGS_det_model_dir, FLAGS_use_gpu, FLAGS_gpu_id, FLAGS_gpu_mem, FLAGS_cpu_threads, FLAGS_enable_mkldnn, FLAGS_max_side_len, FLAGS_det_db_thresh, @@ -174,8 +190,6 @@ int main_system(std::vector cv_all_img_names) { FLAGS_enable_mkldnn, FLAGS_char_list_file, FLAGS_use_tensorrt, FLAGS_precision); - auto start = std::chrono::system_clock::now(); - for (int i = 0; i < cv_all_img_names.size(); ++i) { LOG(INFO) << "The predict img: " << cv_all_img_names[i]; @@ -189,7 +203,10 @@ int main_system(std::vector cv_all_img_names) { std::vector rec_times; det.Run(srcimg, boxes, &det_times); - + time_info_det[0] += det_times[0]; + time_info_det[1] += det_times[1]; + time_info_det[2] += det_times[2]; + cv::Mat crop_img; for (int j = 0; j < boxes.size(); j++) { crop_img = Utility::GetRotateCropImage(srcimg, boxes[j]); @@ -198,18 +215,36 @@ int main_system(std::vector cv_all_img_names) { crop_img = cls->Run(crop_img); } rec.Run(crop_img, &rec_times); + time_info_rec[0] += rec_times[0]; + time_info_rec[1] += rec_times[1]; + time_info_rec[2] += rec_times[2]; } - - auto end = std::chrono::system_clock::now(); - auto duration = - std::chrono::duration_cast(end - start); - std::cout << "Cost " - << double(duration.count()) * - std::chrono::microseconds::period::num / - std::chrono::microseconds::period::den - << "s" << std::endl; } - + if (FLAGS_benchmark) { + AutoLogger autolog_det("ocr_det", + FLAGS_use_gpu, + FLAGS_use_tensorrt, + FLAGS_enable_mkldnn, + FLAGS_cpu_threads, + 1, + "dynamic", + FLAGS_precision, + time_info_det, + cv_all_img_names.size()); + AutoLogger autolog_rec("ocr_rec", + FLAGS_use_gpu, + FLAGS_use_tensorrt, + FLAGS_enable_mkldnn, + FLAGS_cpu_threads, + 1, + "dynamic", + FLAGS_precision, + time_info_rec, + cv_all_img_names.size()); + autolog_det.report(); + std::cout << endl; + autolog_rec.report(); + } return 0; } diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index 2d27a9ee3b..a801c0afc7 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -49,3 +49,18 @@ inference:tools/infer/predict_rec.py --save_log_path:./test/output/ --benchmark:True null:null +===========================cpp_infer_params=========================== +use_opencv:True +infer_model:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr rec +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +--save_log_path:null +--benchmark:True \ No newline at end of file diff --git a/tests/prepare.sh b/tests/prepare.sh index aa6420054a..77fc46e05c 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -64,7 +64,7 @@ elif [ ${MODE} = "whole_infer" ];then cd ./train_data/ && tar xf icdar2015_infer.tar && tar xf ic15_data.tar ln -s ./icdar2015_infer ./icdar2015 cd ../ -elif [ ${MODE} = "infer" ] || [ ${MODE} = "cpp_infer" ];then +elif [ ${MODE} = "infer" ];then if [ ${model_name} = "ocr_det" ]; then eval_model_name="ch_ppocr_mobile_v2.0_det_train" rm -rf ./train_data/icdar2015 @@ -87,6 +87,21 @@ elif [ ${MODE} = "infer" ] || [ ${MODE} = "cpp_infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar cd ./inference && tar xf ${eval_model_name}.tar && tar xf rec_inference.tar && cd ../ fi +elif [ ${MODE} = "cpp_infer" ];then + if [ ${model_name} = "ocr_det" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ + elif [ ${model_name} = "ocr_rec" ]; then + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ocr_system" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + fi fi if [ ${MODE} = "serving_infer" ];then From 611df3b613b7369ce31459ab712359b13c1089d5 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 8 Sep 2021 02:43:27 +0000 Subject: [PATCH 67/77] surpport ocr_system for cpp cice --- deploy/cpp_infer/src/main.cpp | 3 ++- tests/ocr_det_params.txt | 2 +- tests/ocr_ppocr_mobile_params.txt | 4 ++-- tests/test.sh | 9 ++++++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/deploy/cpp_infer/src/main.cpp b/deploy/cpp_infer/src/main.cpp index 3165b72ddc..5a40cbdde7 100644 --- a/deploy/cpp_infer/src/main.cpp +++ b/deploy/cpp_infer/src/main.cpp @@ -63,6 +63,7 @@ DEFINE_double(cls_thresh, 0.9, "Threshold of cls_thresh."); DEFINE_string(rec_model_dir, "", "Path of rec inference model."); DEFINE_int32(rec_batch_num, 1, "rec_batch_num."); DEFINE_string(char_list_file, "../../ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); +// DEFINE_string(char_list_file, "./ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); using namespace std; @@ -193,7 +194,7 @@ int main_system(std::vector cv_all_img_names) { for (int i = 0; i < cv_all_img_names.size(); ++i) { LOG(INFO) << "The predict img: " << cv_all_img_names[i]; - cv::Mat srcimg = cv::imread(FLAGS_image_dir, cv::IMREAD_COLOR); + cv::Mat srcimg = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR); if (!srcimg.data) { std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << endl; exit(1); diff --git a/tests/ocr_det_params.txt b/tests/ocr_det_params.txt index 7be1430a1a..4ea7474662 100644 --- a/tests/ocr_det_params.txt +++ b/tests/ocr_det_params.txt @@ -62,7 +62,7 @@ inference:./deploy/cpp_infer/build/ppocr det --precision:fp32|fp16 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ ---save_log_path:null +null:null --benchmark:True ===========================serving_params=========================== trans_model:-m paddle_serving_client.convert diff --git a/tests/ocr_ppocr_mobile_params.txt b/tests/ocr_ppocr_mobile_params.txt index 7f0e65596d..30b9a03807 100644 --- a/tests/ocr_ppocr_mobile_params.txt +++ b/tests/ocr_ppocr_mobile_params.txt @@ -53,7 +53,7 @@ inference:tools/infer/predict_system.py use_opencv:True infer_model:./inference/ch_ppocr_mobile_v2.0_det_infer/ infer_quant:False -inference:./deploy/cpp_infer/build/ppocr det +inference:./deploy/cpp_infer/build/ppocr system --use_gpu:True|False --enable_mkldnn:True|False --cpu_threads:1|6 @@ -62,6 +62,6 @@ inference:./deploy/cpp_infer/build/ppocr det --precision:fp32|fp16 --det_model_dir: --image_dir:./inference/ch_det_data_50/all-sum-510/ ---save_log_path:null +--rec_model_dir:./inference/ch_ppocr_mobile_v2.0_rec_infer/ --benchmark:True diff --git a/tests/test.sh b/tests/test.sh index 4a67366748..3444f96f8f 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -192,7 +192,8 @@ if [ ${MODE} = "cpp_infer" ]; then cpp_infer_model_key=$(func_parser_key "${lines[62]}") cpp_image_dir_key=$(func_parser_key "${lines[63]}") cpp_infer_img_dir=$(func_parser_value "${lines[63]}") - cpp_save_log_key=$(func_parser_key "${lines[64]}") + cpp_rec_model_key=$(func_parser_key "${lines[64]}") + cpp_rec_model_value=$(func_parser_value "${lines[64]}") cpp_benchmark_key=$(func_parser_key "${lines[65]}") cpp_benchmark_value=$(func_parser_value "${lines[65]}") fi @@ -368,7 +369,8 @@ function func_cpp_inference(){ set_batchsize=$(func_set_params "${cpp_batch_size_key}" "${batch_size}") set_cpu_threads=$(func_set_params "${cpp_cpu_threads_key}" "${threads}") set_model_dir=$(func_set_params "${cpp_infer_model_key}" "${_model_dir}") - command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${cpp_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} > ${_save_log_path} 2>&1 " + set_infer_params1=$(func_set_params "${cpp_rec_model_key}" "${cpp_rec_model_value}") + command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${cpp_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} > ${_save_log_path} 2>&1 " eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" @@ -396,7 +398,8 @@ function func_cpp_inference(){ set_tensorrt=$(func_set_params "${cpp_use_trt_key}" "${use_trt}") set_precision=$(func_set_params "${cpp_precision_key}" "${precision}") set_model_dir=$(func_set_params "${cpp_infer_model_key}" "${_model_dir}") - command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} > ${_save_log_path} 2>&1 " + set_infer_params1=$(func_set_params "${cpp_rec_model_key}" "${cpp_rec_model_value}") + command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} > ${_save_log_path} 2>&1 " eval $command last_status=${PIPESTATUS[0]} eval "cat ${_save_log_path}" From 96e1ce3d9f5f630b351dcc52f8ee488ce7268362 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 8 Sep 2021 02:45:20 +0000 Subject: [PATCH 68/77] fix --- tests/ocr_rec_params.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index a801c0afc7..d1dc3c311e 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -62,5 +62,5 @@ inference:./deploy/cpp_infer/build/ppocr rec --precision:fp32|fp16 --rec_model_dir: --image_dir:./inference/rec_inference/ ---save_log_path:null +null:null --benchmark:True \ No newline at end of file From 7be68dbd9d96f2d093443bf1c92c14f038f821f0 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 8 Sep 2021 03:13:42 +0000 Subject: [PATCH 69/77] fix readme --- tests/readme.md | 46 ++++++++++++++++++++++++++++------------------ tests/test.sh | 8 ++++---- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/tests/readme.md b/tests/readme.md index 1c5e0faee9..592f621424 100644 --- a/tests/readme.md +++ b/tests/readme.md @@ -23,36 +23,46 @@ test.sh和params.txt文件配合使用,完成OCR轻量检测和识别模型从 ```bash tests/ -├── ocr_det_params.txt # 测试OCR检测模型的参数配置文件 -├── ocr_rec_params.txt # 测试OCR识别模型的参数配置文件 -└── prepare.sh # 完成test.sh运行所需要的数据和模型下载 -└── test.sh # 根据 +├── ocr_det_params.txt # 测试OCR检测模型的参数配置文件 +├── ocr_rec_params.txt # 测试OCR识别模型的参数配置文件 +├── ocr_ppocr_mobile_params.txt # 测试OCR检测+识别模型串联的参数配置文件 +└── prepare.sh # 完成test.sh运行所需要的数据和模型下载 +└── test.sh # 测试主程序 ``` # 使用方法 + test.sh包含四种运行模式,每种模式的运行数据不同,分别用于测试速度和精度,分别是: -- 模式1 lite_train_infer,使用少量数据训练,用于快速验证训练到预测的走通流程,不验证精度和速度; -``` + +- 模式1:lite_train_infer,使用少量数据训练,用于快速验证训练到预测的走通流程,不验证精度和速度; +```shell bash test/prepare.sh ./tests/ocr_det_params.txt 'lite_train_infer' bash tests/test.sh ./tests/ocr_det_params.txt 'lite_train_infer' -``` -- 模式2 whole_infer,使用少量数据训练,一定量数据预测,用于验证训练后的模型执行预测,预测速度是否合理; -``` +``` + +- 模式2:whole_infer,使用少量数据训练,一定量数据预测,用于验证训练后的模型执行预测,预测速度是否合理; +```shell bash tests/prepare.sh ./tests/ocr_det_params.txt 'whole_infer' bash tests/test.sh ./tests/ocr_det_params.txt 'whole_infer' -``` +``` -- 模式3 infer 不训练,全量数据预测,走通开源模型评估、动转静,检查inference model预测时间和精度; -``` +- 模式3:infer 不训练,全量数据预测,走通开源模型评估、动转静,检查inference model预测时间和精度; +```shell bash tests/prepare.sh ./tests/ocr_det_params.txt 'infer' -用法1: +# 用法1: bash tests/test.sh ./tests/ocr_det_params.txt 'infer' -用法2: 指定GPU卡预测,第三个传入参数为GPU卡号 +# 用法2: 指定GPU卡预测,第三个传入参数为GPU卡号 bash tests/test.sh ./tests/ocr_det_params.txt 'infer' '1' -``` +``` -模式4: whole_train_infer , CE: 全量数据训练,全量数据预测,验证模型训练精度,预测精度,预测速度 -``` +- 模式4:whole_train_infer , CE: 全量数据训练,全量数据预测,验证模型训练精度,预测精度,预测速度; +```shell bash tests/prepare.sh ./tests/ocr_det_params.txt 'whole_train_infer' bash tests/test.sh ./tests/ocr_det_params.txt 'whole_train_infer' -``` +``` + +- 模式5:cpp_infer , CE: 验证inference model的c++预测是否走通; +```shell +bash tests/prepare.sh ./tests/ocr_det_params.txt 'cpp_infer' +bash tests/test.sh ./tests/ocr_det_params.txt 'cpp_infer' +``` diff --git a/tests/test.sh b/tests/test.sh index 3444f96f8f..8040793f1d 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -192,8 +192,8 @@ if [ ${MODE} = "cpp_infer" ]; then cpp_infer_model_key=$(func_parser_key "${lines[62]}") cpp_image_dir_key=$(func_parser_key "${lines[63]}") cpp_infer_img_dir=$(func_parser_value "${lines[63]}") - cpp_rec_model_key=$(func_parser_key "${lines[64]}") - cpp_rec_model_value=$(func_parser_value "${lines[64]}") + cpp_infer_key1=$(func_parser_key "${lines[64]}") + cpp_infer_value1=$(func_parser_value "${lines[64]}") cpp_benchmark_key=$(func_parser_key "${lines[65]}") cpp_benchmark_value=$(func_parser_value "${lines[65]}") fi @@ -369,7 +369,7 @@ function func_cpp_inference(){ set_batchsize=$(func_set_params "${cpp_batch_size_key}" "${batch_size}") set_cpu_threads=$(func_set_params "${cpp_cpu_threads_key}" "${threads}") set_model_dir=$(func_set_params "${cpp_infer_model_key}" "${_model_dir}") - set_infer_params1=$(func_set_params "${cpp_rec_model_key}" "${cpp_rec_model_value}") + set_infer_params1=$(func_set_params "${cpp_infer_key1}" "${cpp_infer_value1}") command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${cpp_use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} > ${_save_log_path} 2>&1 " eval $command last_status=${PIPESTATUS[0]} @@ -398,7 +398,7 @@ function func_cpp_inference(){ set_tensorrt=$(func_set_params "${cpp_use_trt_key}" "${use_trt}") set_precision=$(func_set_params "${cpp_precision_key}" "${precision}") set_model_dir=$(func_set_params "${cpp_infer_model_key}" "${_model_dir}") - set_infer_params1=$(func_set_params "${cpp_rec_model_key}" "${cpp_rec_model_value}") + set_infer_params1=$(func_set_params "${cpp_infer_key1}" "${cpp_infer_value1}") command="${_script} ${cpp_use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} > ${_save_log_path} 2>&1 " eval $command last_status=${PIPESTATUS[0]} From 08335787bc41931e4312285ed43e8247d1a32e2b Mon Sep 17 00:00:00 2001 From: tink2123 Date: Wed, 8 Sep 2021 11:33:06 +0800 Subject: [PATCH 70/77] update benchmark doc --- doc/doc_ch/benchmark.md | 39 +++++++++++++------------------------- doc/doc_en/benchmark_en.md | 35 ++++++++++------------------------ 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/doc/doc_ch/benchmark.md b/doc/doc_ch/benchmark.md index 520a2fcea3..7ab829576e 100644 --- a/doc/doc_ch/benchmark.md +++ b/doc/doc_ch/benchmark.md @@ -12,40 +12,27 @@ ## 评估指标 说明: -- v1.0是未添加优化策略的DB+CRNN模型,v1.1是添加多种优化策略和方向分类器的PP-OCR模型。slim_v1.1是使用裁剪或量化的模型。 + - 检测输入图像的的长边尺寸是960。 -- 评估耗时阶段为图像输入到结果输出的完整阶段,包括了图像的预处理和后处理。 +- 评估耗时阶段为图像预测耗时,不包括图像的预处理和后处理。 - `Intel至强6148`为服务器端CPU型号,测试中使用Intel MKL-DNN 加速。 - `骁龙855`为移动端处理平台型号。 -不同预测模型大小和整体识别精度对比 +预测模型大小和整体识别精度对比 | 模型名称 | 整体模型
大小\(M\) | 检测模型
大小\(M\) | 方向分类器
模型大小\(M\) | 识别模型
大小\(M\) | 整体识别
F\-score | |:-:|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.5193 | -| ch\_ppocr\_server\_v1\.1 | 155\.1 | 47\.2 | 0\.9 | 107 | 0\.5414 | -| ch\_ppocr\_mobile\_v1\.0 | 8\.6 | 4\.1 | \- | 4\.5 | 0\.393 | -| ch\_ppocr\_server\_v1\.0 | 203\.8 | 98\.5 | \- | 105\.3 | 0\.4436 | +| PP-OCRv2 | 11\.6 | 3\.0 | 0\.9 | 8\.6 | 0\.5224 | +| PP-OCR mobile | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.503 | +| PP-OCR server | 155\.1 | 47\.2 | 0\.9 | 107 | 0\.570 | -不同预测模型在T4 GPU上预测速度对比,单位ms -| 模型名称 | 整体 | 检测 | 方向分类器 | 识别 | -|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 137 | 35 | 24 | 78 | -| ch\_ppocr\_server\_v1\.1 | 204 | 39 | 25 | 140 | -| ch\_ppocr\_mobile\_v1\.0 | 117 | 41 | \- | 76 | -| ch\_ppocr\_server\_v1\.0 | 199 | 52 | \- | 147 | +预测模型在CPU和GPU上的速度对比,单位ms -不同预测模型在CPU上预测速度对比,单位ms +| 模型名称 | CPU | T4 GPU | +|:-:|:-:|:-:| +| PP-OCRv2 | 330 | 111 | +| PP-OCR mobile | 356 | 11 6| +| PP-OCR server | 1056 | 200 | -| 模型名称 | 整体 | 检测 | 方向分类器 | 识别 | -|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 421 | 164 | 51 | 206 | -| ch\_ppocr\_mobile\_v1\.0 | 398 | 219 | \- | 179 | - -裁剪量化模型和原始模型模型大小,整体识别精度和在SD 855上预测速度对比 - -| 模型名称 | 整体模型
大小\(M\) | 检测模型
大小\(M\) | 方向分类器
模型大小\(M\) | 识别模型
大小\(M\) | 整体识别
F\-score | SD 855
\(ms\) | -|:-:|:-:|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.5193 | 306 | -| ch\_ppocr\_mobile\_slim\_v1\.1 | 3\.5 | 1\.4 | 0\.5 | 1\.6 | 0\.521 | 268 | +更多 PP-OCR 系列模型的预测指标可以参考[PP-OCR Benchamrk](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.2/doc/doc_ch/benchmark.md) diff --git a/doc/doc_en/benchmark_en.md b/doc/doc_en/benchmark_en.md index 91b0159419..0d3ffaecc5 100755 --- a/doc/doc_en/benchmark_en.md +++ b/doc/doc_en/benchmark_en.md @@ -13,7 +13,6 @@ We collected 300 images for different real application scenarios to evaluate the ## MEASUREMENT Explanation: -- v1.0 indicates DB+CRNN models without the strategies. v1.1 indicates the PP-OCR models with the strategies and the direction classify. slim_v1.1 indicates the PP-OCR models with prunner or quantization. - The long size of the input for the text detector is 960. @@ -27,30 +26,16 @@ Compares the model size and F-score: | Model Name | Model Size
of the
Whole System\(M\) | Model Size
of the Text
Detector\(M\) | Model Size
of the Direction
Classifier\(M\) | Model Size
of the Text
Recognizer \(M\) | F\-score | |:-:|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.5193 | -| ch\_ppocr\_server\_v1\.1 | 155\.1 | 47\.2 | 0\.9 | 107 | 0\.5414 | -| ch\_ppocr\_mobile\_v1\.0 | 8\.6 | 4\.1 | \- | 4\.5 | 0\.393 | -| ch\_ppocr\_server\_v1\.0 | 203\.8 | 98\.5 | \- | 105\.3 | 0\.4436 | +| PP-OCRv2 | 11\.6 | 3\.0 | 0\.9 | 8\.6 | 0\.5224 | +| PP-OCR mobile | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.503 | +| PP-OCR server | 155\.1 | 47\.2 | 0\.9 | 107 | 0\.570 | -Compares the time-consuming on T4 GPU (ms): +Compares the time-consuming on CPU and T4 GPU (ms): -| Model Name | Overall | Text Detector | Direction Classifier | Text Recognizer | -|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 137 | 35 | 24 | 78 | -| ch\_ppocr\_server\_v1\.1 | 204 | 39 | 25 | 140 | -| ch\_ppocr\_mobile\_v1\.0 | 117 | 41 | \- | 76 | -| ch\_ppocr\_server\_v1\.0 | 199 | 52 | \- | 147 | +| Model Name | CPU | T4 GPU | +|:-:|:-:|:-:| +| PP-OCRv2 | 330 | 111 | +| PP-OCR mobile | 356 | 116| +| PP-OCR server | 1056 | 200 | -Compares the time-consuming on CPU (ms): - -| Model Name | Overall | Text Detector | Direction Classifier | Text Recognizer | -|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 421 | 164 | 51 | 206 | -| ch\_ppocr\_mobile\_v1\.0 | 398 | 219 | \- | 179 | - -Compares the model size, F-score, the time-consuming on SD 855 of between the slim models and the original models: - -| Model Name | Model Size
of the
Whole System\(M\) | Model Size
of the Text
Detector\(M\) | Model Size
of the Direction
Classifier\(M\) | Model Size
of the Text
Recognizer \(M\) | F\-score | SD 855
\(ms\) | -|:-:|:-:|:-:|:-:|:-:|:-:|:-:| -| ch\_ppocr\_mobile\_v1\.1 | 8\.1 | 2\.6 | 0\.9 | 4\.6 | 0\.5193 | 306 | -| ch\_ppocr\_mobile\_slim\_v1\.1 | 3\.5 | 1\.4 | 0\.5 | 1\.6 | 0\.521 | 268 | +More indicators of PP-OCR series models can be referred to [PP-OCR Benchamrk](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.2/doc/doc_en/benchmark_en.md) From f5f402e3fab164559b6667d2d72d63c00c5300e0 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Wed, 8 Sep 2021 15:57:18 +0800 Subject: [PATCH 71/77] polish tests for rec and server --- tests/ocr_ppocr_mobile_params.txt | 2 +- tests/ocr_ppocr_server_params.txt | 66 +++++++++++++++++++++++++++++++ tests/ocr_rec_params.txt | 17 +++++++- tests/prepare.sh | 9 ++++- 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 tests/ocr_ppocr_server_params.txt diff --git a/tests/ocr_ppocr_mobile_params.txt b/tests/ocr_ppocr_mobile_params.txt index 30b9a03807..bb6e0960a7 100644 --- a/tests/ocr_ppocr_mobile_params.txt +++ b/tests/ocr_ppocr_mobile_params.txt @@ -1,5 +1,5 @@ ===========================train_params=========================== -model_name:ocr_system +model_name:ocr_system_mobile python:python3.7 gpu_list:null Global.use_gpu:null diff --git a/tests/ocr_ppocr_server_params.txt b/tests/ocr_ppocr_server_params.txt new file mode 100644 index 0000000000..9c49f7ddf4 --- /dev/null +++ b/tests/ocr_ppocr_server_params.txt @@ -0,0 +1,66 @@ +===========================train_params=========================== +model_name:ocr_system_server +python:python3.7 +gpu_list:null +Global.use_gpu:null +Global.auto_cast:null +Global.epoch_num:null +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:null +Global.pretrained_model:null +train_model_name:null +train_infer_img_dir:null +null:null +## +trainer: +norm_train:null +pact_train:null +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:null +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.pretrained_model: +norm_export:null +quant_export:null +fpgm_export:null +distill_export:null +export1:null +export2:null +## +infer_model:./inference/ch_ppocr_server_v2.0_det_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_system.py +--use_gpu:True +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16|int8 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--save_log_path:null +--benchmark:True +--rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +===========================cpp_infer_params=========================== +use_opencv:True +infer_model:./inference/ch_ppocr_server_v2.0_det_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr system +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--det_model_dir: +--image_dir:./inference/ch_det_data_50/all-sum-510/ +--rec_model_dir:./inference/ch_ppocr_server_v2.0_rec_infer/ +--benchmark:True \ No newline at end of file diff --git a/tests/ocr_rec_params.txt b/tests/ocr_rec_params.txt index d1dc3c311e..f9c4078972 100644 --- a/tests/ocr_rec_params.txt +++ b/tests/ocr_rec_params.txt @@ -63,4 +63,19 @@ inference:./deploy/cpp_infer/build/ppocr rec --rec_model_dir: --image_dir:./inference/rec_inference/ null:null ---benchmark:True \ No newline at end of file +--benchmark:True +===========================serving_params=========================== +trans_model:-m paddle_serving_client.convert +--dirname:./inference/ch_ppocr_mobile_v2.0_rec_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--serving_server:./deploy/pdserving/ppocr_rec_mobile_2.0_serving/ +--serving_client:./deploy/pdserving/ppocr_rec_mobile_2.0_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency=1 +op.rec.local_service_conf.devices:null|0 +op.rec.local_service_conf.use_mkldnn:True|False +op.rec.local_service_conf.thread_num:1|6 +op.rec.local_service_conf.use_trt:False|True +op.rec.local_service_conf.precision:fp32|fp16|int8 +pipline:pipeline_http_client.py --image_dir=../../doc/imgs_words_en \ No newline at end of file diff --git a/tests/prepare.sh b/tests/prepare.sh index 77fc46e05c..a2ad4f7115 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -75,12 +75,17 @@ elif [ ${MODE} = "infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_det_data_50.tar && cd ../ - elif [ ${model_name} = "ocr_system" ]; then + elif [ ${model_name} = "ocr_system_mobile" ]; then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ - else + elif [ ${model_name} = "ocr_system_server" ]; then + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ + else rm -rf ./train_data/ic15_data eval_model_name="ch_ppocr_mobile_v2.0_rec_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar From 2d7af5b8b25f7c498a1e57bf3093c8ba615133f1 Mon Sep 17 00:00:00 2001 From: MissPenguin Date: Wed, 8 Sep 2021 09:49:04 +0000 Subject: [PATCH 72/77] fix label path --- deploy/cpp_infer/src/main.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/deploy/cpp_infer/src/main.cpp b/deploy/cpp_infer/src/main.cpp index 5a40cbdde7..ef400cfc89 100644 --- a/deploy/cpp_infer/src/main.cpp +++ b/deploy/cpp_infer/src/main.cpp @@ -44,7 +44,7 @@ DEFINE_int32(cpu_threads, 10, "Num of threads with CPU."); DEFINE_bool(enable_mkldnn, false, "Whether use mkldnn with CPU."); DEFINE_bool(use_tensorrt, false, "Whether use tensorrt."); DEFINE_string(precision, "fp32", "Precision be one of fp32/fp16/int8"); -DEFINE_bool(benchmark, true, "Whether use benchmark."); +DEFINE_bool(benchmark, false, "Whether use benchmark."); DEFINE_string(save_log_path, "./log_output/", "Save benchmark log path."); // detection related DEFINE_string(image_dir, "", "Dir of input image."); @@ -63,7 +63,6 @@ DEFINE_double(cls_thresh, 0.9, "Threshold of cls_thresh."); DEFINE_string(rec_model_dir, "", "Path of rec inference model."); DEFINE_int32(rec_batch_num, 1, "rec_batch_num."); DEFINE_string(char_list_file, "../../ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); -// DEFINE_string(char_list_file, "./ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); using namespace std; @@ -128,9 +127,15 @@ int main_det(std::vector cv_all_img_names) { int main_rec(std::vector cv_all_img_names) { std::vector time_info = {0, 0, 0}; + + std::string char_list_file = FLAGS_char_list_file; + if (FLAGS_benchmark) + char_list_file = FLAGS_char_list_file.substr(6); + cout << "label file: " << char_list_file << endl; + CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id, FLAGS_gpu_mem, FLAGS_cpu_threads, - FLAGS_enable_mkldnn, FLAGS_char_list_file, + FLAGS_enable_mkldnn, char_list_file, FLAGS_use_tensorrt, FLAGS_precision); for (int i = 0; i < cv_all_img_names.size(); ++i) { @@ -186,9 +191,14 @@ int main_system(std::vector cv_all_img_names) { FLAGS_use_tensorrt, FLAGS_precision); } + std::string char_list_file = FLAGS_char_list_file; + if (FLAGS_benchmark) + char_list_file = FLAGS_char_list_file.substr(6); + cout << "label file: " << char_list_file << endl; + CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id, FLAGS_gpu_mem, FLAGS_cpu_threads, - FLAGS_enable_mkldnn, FLAGS_char_list_file, + FLAGS_enable_mkldnn, char_list_file, FLAGS_use_tensorrt, FLAGS_precision); for (int i = 0; i < cv_all_img_names.size(); ++i) { From a027e9e15c7cce767f58e75d05091bfbd9691e36 Mon Sep 17 00:00:00 2001 From: tink2123 Date: Thu, 9 Sep 2021 14:56:56 +0800 Subject: [PATCH 73/77] add server_rec params and update prepare for serving --- tests/configs/rec_icdar15_r34_train.yml | 99 +++++++++++++++++++++++++ tests/ocr_rec_server_params.txt | 81 ++++++++++++++++++++ tests/prepare.sh | 17 ++++- 3 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 tests/configs/rec_icdar15_r34_train.yml create mode 100644 tests/ocr_rec_server_params.txt diff --git a/tests/configs/rec_icdar15_r34_train.yml b/tests/configs/rec_icdar15_r34_train.yml new file mode 100644 index 0000000000..5825c3e962 --- /dev/null +++ b/tests/configs/rec_icdar15_r34_train.yml @@ -0,0 +1,99 @@ +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] + cal_metric_during_train: True + pretrained_model: + checkpoints: + save_inference_dir: ./ + use_visualdl: False + infer_img: doc/imgs_words_en/word_10.png + # for data or label process + character_dict_path: ppocr/utils/en_dict.txt + character_type: EN + max_text_length: 25 + infer_mode: False + use_space_char: False + save_res_path: ./output/rec/predicts_ic15.txt + +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/ic15_data/ + label_file_list: ["./train_data/ic15_data/rec_gt_train.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - CTCLabelEncode: # Class handling label + - 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 + use_shared_memory: False + +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ic15_data + label_file_list: ["./train_data/ic15_data/rec_gt_test.txt"] + transforms: + - DecodeImage: # load image + img_mode: BGR + channel_first: False + - CTCLabelEncode: # Class handling label + - 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 + use_shared_memory: False diff --git a/tests/ocr_rec_server_params.txt b/tests/ocr_rec_server_params.txt new file mode 100644 index 0000000000..7d151fcf0b --- /dev/null +++ b/tests/ocr_rec_server_params.txt @@ -0,0 +1,81 @@ +===========================train_params=========================== +model_name:ocr_server_rec +python:python3.7 +gpu_list:0|0,1 +Global.use_gpu:True|True +Global.auto_cast:null +Global.epoch_num:lite_train_infer=2|whole_train_infer=300 +Global.save_model_dir:./output/ +Train.loader.batch_size_per_card:lite_train_infer=128|whole_train_infer=128 +Global.pretrained_model:null +train_model_name:latest +train_infer_img_dir:./inference/rec_inference +null:null +## +trainer:norm_train|pact_train +norm_train:tools/train.py -c tests/configs/rec_icdar15_r34_train.yml -o +pact_train:deploy/slim/quantization/quant.py -c tests/configs/rec_icdar15_r34_train.yml -o +fpgm_train:null +distill_train:null +null:null +null:null +## +===========================eval_params=========================== +eval:tools/eval.py -c tests/configs/rec_icdar15_r34_train.yml -o +null:null +## +===========================infer_params=========================== +Global.save_inference_dir:./output/ +Global.pretrained_model: +norm_export:tools/export_model.py -c tests/configs/rec_icdar15_r34_train.yml -o +quant_export:deploy/slim/quantization/export_model.py -c tests/configs/rec_icdar15_r34_train.yml -o +fpgm_export:null +distill_export:null +export1:null +export2:null +## +infer_model:./inference/ch_ppocr_server_v2.0_rec_infer/ +infer_export:null +infer_quant:False +inference:tools/infer/predict_rec.py +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1|6 +--use_tensorrt:True|False +--precision:fp32|fp16|int8 +--rec_model_dir: +--image_dir:./inference/rec_inference +--save_log_path:./test/output/ +--benchmark:True +null:null +===========================cpp_infer_params=========================== +use_opencv:True +infer_model:./inference/ch_ppocr_server_v2.0_rec_infer/ +infer_quant:False +inference:./deploy/cpp_infer/build/ppocr rec +--use_gpu:True|False +--enable_mkldnn:True|False +--cpu_threads:1|6 +--rec_batch_num:1 +--use_tensorrt:False|True +--precision:fp32|fp16 +--rec_model_dir: +--image_dir:./inference/rec_inference/ +null:null +--benchmark:True +===========================serving_params=========================== +trans_model:-m paddle_serving_client.convert +--dirname:./inference/ch_ppocr_server_v2.0_rec_infer/ +--model_filename:inference.pdmodel +--params_filename:inference.pdiparams +--serving_server:./deploy/pdserving/ppocr_rec_server_2.0_serving/ +--serving_client:./deploy/pdserving/ppocr_rec_server_2.0_client/ +serving_dir:./deploy/pdserving +web_service:web_service_rec.py --config=config.yml --opt op.rec.concurrency=1 +op.rec.local_service_conf.devices:null|0 +op.rec.local_service_conf.use_mkldnn:True|False +op.rec.local_service_conf.thread_num:1|6 +op.rec.local_service_conf.use_trt:False|True +op.rec.local_service_conf.precision:fp32|fp16|int8 +pipline:pipeline_http_client.py --image_dir=../../doc/imgs_words_en \ No newline at end of file diff --git a/tests/prepare.sh b/tests/prepare.sh index a2ad4f7115..ef021fa385 100644 --- a/tests/prepare.sh +++ b/tests/prepare.sh @@ -85,12 +85,18 @@ elif [ ${MODE} = "infer" ];then wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/ch_det_data_50.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar cd ./inference && tar xf ch_ppocr_server_v2.0_det_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_det_data_50.tar && cd ../ - else + elif [ ${model_name} = "ocr_rec" ]; then rm -rf ./train_data/ic15_data eval_model_name="ch_ppocr_mobile_v2.0_rec_infer" wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar cd ./inference && tar xf ${eval_model_name}.tar && tar xf rec_inference.tar && cd ../ + elif [ ${model_name} = "ocr_server_rec" ]; then + rm -rf ./train_data/ic15_data + eval_model_name="ch_ppocr_server_v2.0_rec_infer" + wget -nc -P ./inference/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/rec_inference.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar + cd ./inference && tar xf ${eval_model_name}.tar && tar xf rec_inference.tar && cd ../ fi elif [ ${MODE} = "cpp_infer" ];then if [ ${model_name} = "ocr_det" ]; then @@ -112,12 +118,15 @@ fi if [ ${MODE} = "serving_infer" ];then # prepare serving env python_name=$(func_parser_value "${lines[2]}") - ${python_name} -m pip install install paddle-serving-server-gpu==0.6.1.post101 + wget https://paddle-serving.bj.bcebos.com/chain/paddle_serving_server_gpu-0.0.0.post101-py3-none-any.whl + ${python_name} -m pip install install paddle_serving_server_gpu-0.0.0.post101-py3-none-any.whl ${python_name} -m pip install paddle_serving_client==0.6.1 - ${python_name} -m pip install paddle-serving-app==0.6.1 + ${python_name} -m pip install paddle-serving-app==0.6.3 wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar - cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && cd ../ + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar + wget -nc -P ./inference https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar + cd ./inference && tar xf ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_rec_infer.tar && tar xf ch_ppocr_server_v2.0_det_infer.tar cd ../ fi if [ ${MODE} = "cpp_infer" ];then From 7401906d654d88e52d744fd5d34781cae27bb1c6 Mon Sep 17 00:00:00 2001 From: Leif <4603009@qq.com> Date: Thu, 9 Sep 2021 19:06:00 +0800 Subject: [PATCH 74/77] Update joinus.png --- doc/joinus.PNG | Bin 192891 -> 198519 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/joinus.PNG b/doc/joinus.PNG index 6bd6f54d5bd91c55501caaab79a72f7b129fc359..89af4f70ed64b5efe88edb74a69048491109dd23 100644 GIT binary patch literal 198519 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 z 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

NHI|k`Rf@eEu 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%0D$n@x9$i9MPKFA^8fpGZY1q#KO(QY{84yh2=z^ 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

Xo|DkfvW!U58I%KT= z1f%7T2y6^yA-yL;w$I`LbUq9yEI1%AdbOWQGn(i9i#YJWcR})_kfJ}Ss%y^=wnu9I zRW=Bvktz(XL_oWGtu}>TgJI+n?hIqNW2*rwCpYu3E)%vICpYCO7aFtpCs0)}^{*ZRmG!lxh{)$U*lW8rd)gO^t3OYKNT<#a`3 zyTJA6ORRIbj%}@{;|qB4*anb&rIPWUhFJ!j(_abV@<(9t9Mc<8Iq6=p=$xopp-+8} zs%L3~MT4bsWbqMUwo2mM#bTS{B?5XeAphdLIn)XvWukZqG)9+h0HT zen*frpMtnh&nL1k)*C-q8;K~VJCf9g`vn!H55etD;1XHO9Vc9rm53qV4qwYLVQHss zj_xfddm6zzPk)>4ST;Fv1!EsntQeH;wd)27F-M))N27m3%LY3q_I2hM$7I#83cCKW zfISsN*>KPEJ(DA;p&th9!6MJig%!sO4cCSvSL0N?|N zE^5Yh&2Gp|ir)1wFM(#IZMU?#7JpD@Zf-(2N(X&^VN?HDTZF#+S`H|CNwgMlgP>ZR zke6k&Wu3$G)Iz+~8TY`%Y^o@{zX}@9b-_3t?d* zC}FomMoDiX_Q6pZ^~}r8_^97^H~?H>;o->pW}idr>SVkZJ-331V`vqBYBc;_UcvCHJ$xf&Y*LkJpJjG2$-y! zU|?ggj)kqbG)G0e3d<-__6F)|?;{`9jJsp4Sb;=elDH5l(t~y$8gQewST1wh0p)tl zNPgmK;z|JLr6Yan%9$f{s}yG13XAr3JsJ!x^yNc0!aY1sc)TcmQF_y2c zL?_Yr!9pHmbfS#UZ!gC{ydASPY*CI9d1}Myrj_J=x&E0^;ClSkI@br_RM9paUUB$8 z!Y1&~SRdz3JoMkM|KDU!|4Vh$|EK>OOyY`Ysj1-CrN7@FSf8L)KL!8&|L_O3lAhs5 UZSB}2$ZKh9=wB{Wv%mj;0PqTU;{X5v literal 192891 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

KjeSr12f=7#8@9|Km)2Eb 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 From f08c3b148117622754ac0a031a6820b8b4a033ba Mon Sep 17 00:00:00 2001 From: Double_V Date: Thu, 9 Sep 2021 21:09:06 +0800 Subject: [PATCH 75/77] fix readme (#3998) --- README_ch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_ch.md b/README_ch.md index 7e8a8e241b..7c6dcf5ea7 100755 --- a/README_ch.md +++ b/README_ch.md @@ -81,7 +81,7 @@ PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力 | 模型简介 | 模型名称 |推荐场景 | 检测模型 | 方向分类器 | 识别模型 | | ------------ | --------------- | ----------------|---- | ---------- | -------- | -| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/chinese/ch_PP-OCRv2_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar)| +| 中英文超轻量PP-OCRv2模型(13.0M) | ch_PP-OCRv2_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_distill_train.tar)| [推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_infer.tar) / [训练模型](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar)| | 中英文超轻量PP-OCR mobile模型(9.4M) | ch_ppocr_mobile_v2.0_xx |移动端&服务器端|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar)|[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_pre.tar) | | 中英文通用PP-OCR server模型(143.4M) |ch_ppocr_server_v2.0_xx|服务器端 |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_det_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar) |[推理模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_infer.tar) / [预训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_server_v2.0_rec_pre.tar) | From cc24646a876773e2b28de3b76a2dafbcefdbc729 Mon Sep 17 00:00:00 2001 From: littletomatodonkey Date: Thu, 9 Sep 2021 23:51:48 +0800 Subject: [PATCH 76/77] fix rec distillation (#3995) * fix rec distillation * add dist cfg * fix cfg --- configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml | 88 +++------- .../ch_PP-OCRv2_rec_distillation.yml | 160 ++++++++++++++++++ doc/doc_ch/knowledge_distillation.md | 35 +++- ppocr/losses/basic_loss.py | 29 ++-- ppocr/losses/combined_loss.py | 14 +- ppocr/losses/distillation_loss.py | 14 +- ppocr/utils/save_load.py | 10 +- 7 files changed, 255 insertions(+), 95 deletions(-) create mode 100644 configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml diff --git a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml index 27ba4fd70b..38f77f7372 100644 --- a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml +++ b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_lite_distillation_v2.1 + save_model_dir: ./output/rec_mobile_pp-OCRv2 save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -19,7 +19,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_chinese_lite_distillation_v2.1.txt + save_res_path: ./output/rec/predicts_mobile_pp-OCRv2.txt Optimizer: @@ -35,79 +35,32 @@ Optimizer: name: L2 factor: 2.0e-05 + Architecture: - model_type: &model_type "rec" - name: DistillationModel - algorithm: Distillation - Models: - Teacher: - pretrained: - freeze_params: false - return_all_feats: true - model_type: *model_type - algorithm: CRNN - Transform: - Backbone: - name: MobileNetV1Enhance - scale: 0.5 - Neck: - name: SequenceEncoder - encoder_type: rnn - hidden_size: 64 - Head: - name: CTCHead - mid_channels: 96 - fc_decay: 0.00002 - Student: - pretrained: - freeze_params: false - return_all_feats: true - model_type: *model_type - algorithm: CRNN - Transform: - Backbone: - name: MobileNetV1Enhance - scale: 0.5 - Neck: - name: SequenceEncoder - encoder_type: rnn - hidden_size: 64 - Head: - name: CTCHead - mid_channels: 96 - fc_decay: 0.00002 - + model_type: rec + algorithm: CRNN + Transform: + Backbone: + name: MobileNetV1Enhance + scale: 0.5 + Neck: + name: SequenceEncoder + encoder_type: rnn + hidden_size: 64 + Head: + name: CTCHead + mid_channels: 96 + fc_decay: 0.00002 Loss: - name: CombinedLoss - loss_config_list: - - DistillationCTCLoss: - weight: 1.0 - model_name_list: ["Student", "Teacher"] - key: head_out - - DistillationDMLLoss: - weight: 1.0 - act: "softmax" - model_name_pairs: - - ["Student", "Teacher"] - key: head_out - - DistillationDistanceLoss: - weight: 1.0 - mode: "l2" - model_name_pairs: - - ["Student", "Teacher"] - key: backbone_out + name: CTCLoss PostProcess: - name: DistillationCTCLabelDecode - model_name: ["Student", "Teacher"] - key: head_out + name: CTCLabelDecode Metric: - name: DistillationMetric - base_metric_name: RecMetric + name: RecMetric main_indicator: acc - key: "Student" Train: dataset: @@ -132,7 +85,6 @@ Train: shuffle: true batch_size_per_card: 128 drop_last: true - num_sections: 1 num_workers: 8 Eval: dataset: diff --git a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml new file mode 100644 index 0000000000..d2308fd574 --- /dev/null +++ b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml @@ -0,0 +1,160 @@ +Global: + debug: false + use_gpu: true + epoch_num: 800 + log_smooth_window: 20 + print_batch_step: 10 + save_model_dir: ./output/rec_pp-OCRv2_distillation + save_epoch_step: 3 + eval_batch_step: [0, 2000] + cal_metric_during_train: true + pretrained_model: + checkpoints: + save_inference_dir: + use_visualdl: false + infer_img: doc/imgs_words/ch/word_1.jpg + character_dict_path: ppocr/utils/ppocr_keys_v1.txt + character_type: ch + max_text_length: 25 + infer_mode: false + use_space_char: true + distributed: true + save_res_path: ./output/rec/predicts_pp-OCRv2_distillation.txt + + +Optimizer: + name: Adam + beta1: 0.9 + beta2: 0.999 + lr: + name: Piecewise + decay_epochs : [700, 800] + values : [0.001, 0.0001] + warmup_epoch: 5 + regularizer: + name: L2 + factor: 2.0e-05 + +Architecture: + model_type: &model_type "rec" + name: DistillationModel + algorithm: Distillation + Models: + Teacher: + pretrained: + freeze_params: false + return_all_feats: true + model_type: *model_type + algorithm: CRNN + Transform: + Backbone: + name: MobileNetV1Enhance + scale: 0.5 + Neck: + name: SequenceEncoder + encoder_type: rnn + hidden_size: 64 + Head: + name: CTCHead + mid_channels: 96 + fc_decay: 0.00002 + Student: + pretrained: + freeze_params: false + return_all_feats: true + model_type: *model_type + algorithm: CRNN + Transform: + Backbone: + name: MobileNetV1Enhance + scale: 0.5 + Neck: + name: SequenceEncoder + encoder_type: rnn + hidden_size: 64 + Head: + name: CTCHead + mid_channels: 96 + fc_decay: 0.00002 + + +Loss: + name: CombinedLoss + loss_config_list: + - DistillationCTCLoss: + weight: 1.0 + model_name_list: ["Student", "Teacher"] + key: head_out + - DistillationDMLLoss: + weight: 1.0 + act: "softmax" + use_log: true + model_name_pairs: + - ["Student", "Teacher"] + key: head_out + - DistillationDistanceLoss: + weight: 1.0 + mode: "l2" + model_name_pairs: + - ["Student", "Teacher"] + key: backbone_out + +PostProcess: + name: DistillationCTCLabelDecode + model_name: ["Student", "Teacher"] + key: head_out + +Metric: + name: DistillationMetric + base_metric_name: RecMetric + main_indicator: acc + key: "Student" + +Train: + dataset: + name: SimpleDataSet + data_dir: ./train_data/ + label_file_list: + - ./train_data/train_list.txt + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - RecAug: + - CTCLabelEncode: + - RecResizeImg: + image_shape: [3, 32, 320] + - KeepKeys: + keep_keys: + - image + - label + - length + loader: + shuffle: true + batch_size_per_card: 128 + drop_last: true + num_sections: 1 + num_workers: 8 +Eval: + dataset: + name: SimpleDataSet + data_dir: ./train_data + label_file_list: + - ./train_data/val_list.txt + transforms: + - DecodeImage: + img_mode: BGR + channel_first: false + - CTCLabelEncode: + - RecResizeImg: + image_shape: [3, 32, 320] + - KeepKeys: + keep_keys: + - image + - label + - length + loader: + shuffle: false + drop_last: false + batch_size_per_card: 128 + num_workers: 8 diff --git a/doc/doc_ch/knowledge_distillation.md b/doc/doc_ch/knowledge_distillation.md index 5827f48c81..b2772454d9 100644 --- a/doc/doc_ch/knowledge_distillation.md +++ b/doc/doc_ch/knowledge_distillation.md @@ -39,7 +39,7 @@ PaddleOCR中集成了知识蒸馏的算法,具体地,有以下几个主要 ### 2.1 识别配置文件解析 -配置文件在[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml)。 +配置文件在[ch_PP-OCRv2_rec_distillation.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml)。 #### 2.1.1 模型结构 @@ -246,6 +246,39 @@ Metric: 关于`DistillationMetric`更加具体的实现可以参考: [distillation_metric.py](../../ppocr/metrics/distillation_metric.py#L24)。 +#### 2.1.5 蒸馏模型微调 + +对蒸馏得到的识别蒸馏进行微调有2种方式。 + +(1)基于知识蒸馏的微调:这种情况比较简单,下载预训练模型,在[ch_PP-OCRv2_rec_distillation.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml)中配置好预训练模型路径以及自己的数据路径,即可进行模型微调训练。 + +(2)微调时不使用知识蒸馏:这种情况,需要首先将预训练模型中的学生模型参数提取出来,具体步骤如下。 + +* 首先下载预训练模型并解压。 +```shell +# 下面预训练模型并解压 +wget https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_rec_train.tar +tar -xf ch_PP-OCRv2_rec_train.tar +``` + +* 然后使用python,对其中的学生模型参数进行提取 + +```python +import paddle +# 加载预训练模型 +all_params = paddle.load("ch_PP-OCRv2_rec_train/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 学生模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看学生模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "ch_PP-OCRv2_rec_train/student.pdparams") +``` + +转化完成之后,使用[ch_PP-OCRv2_rec.yml](../../configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml),修改预训练模型的路径(为导出的`student.pdparams`模型路径)以及自己的数据路径,即可进行模型微调。 + ### 2.2 检测配置文件解析 * coming soon! diff --git a/ppocr/losses/basic_loss.py b/ppocr/losses/basic_loss.py index 8306523ac1..d2ef5e5ac9 100644 --- a/ppocr/losses/basic_loss.py +++ b/ppocr/losses/basic_loss.py @@ -56,31 +56,34 @@ class CELoss(nn.Layer): class KLJSLoss(object): def __init__(self, mode='kl'): - assert mode in ['kl', 'js', 'KL', 'JS'], "mode can only be one of ['kl', 'js', 'KL', 'JS']" + assert mode in ['kl', 'js', 'KL', 'JS' + ], "mode can only be one of ['kl', 'js', 'KL', 'JS']" self.mode = mode def __call__(self, p1, p2, reduction="mean"): - loss = paddle.multiply(p2, paddle.log( (p2+1e-5)/(p1+1e-5) + 1e-5)) + loss = paddle.multiply(p2, paddle.log((p2 + 1e-5) / (p1 + 1e-5) + 1e-5)) if self.mode.lower() == "js": - loss += paddle.multiply(p1, paddle.log((p1+1e-5)/(p2+1e-5) + 1e-5)) + loss += paddle.multiply( + p1, paddle.log((p1 + 1e-5) / (p2 + 1e-5) + 1e-5)) loss *= 0.5 if reduction == "mean": - loss = paddle.mean(loss, axis=[1,2]) - elif reduction=="none" or reduction is None: - return loss + loss = paddle.mean(loss, axis=[1, 2]) + elif reduction == "none" or reduction is None: + return loss else: - loss = paddle.sum(loss, axis=[1,2]) + loss = paddle.sum(loss, axis=[1, 2]) + + return loss - return loss class DMLLoss(nn.Layer): """ DMLLoss """ - def __init__(self, act=None): + def __init__(self, act=None, use_log=False): super().__init__() if act is not None: assert act in ["softmax", "sigmoid"] @@ -90,20 +93,24 @@ class DMLLoss(nn.Layer): self.act = nn.Sigmoid() else: self.act = None - + + self.use_log = use_log + self.jskl_loss = KLJSLoss(mode="js") def forward(self, out1, out2): if self.act is not None: out1 = self.act(out1) out2 = self.act(out2) - if len(out1.shape) < 2: + if self.use_log: + # for recognition distillation, log is needed for feature map log_out1 = paddle.log(out1) log_out2 = paddle.log(out2) loss = (F.kl_div( log_out1, out2, reduction='batchmean') + F.kl_div( log_out2, out1, reduction='batchmean')) / 2.0 else: + # for detection distillation log is not needed loss = self.jskl_loss(out1, out2) return loss diff --git a/ppocr/losses/combined_loss.py b/ppocr/losses/combined_loss.py index 0d6fe968d0..f3bb36cf5a 100644 --- a/ppocr/losses/combined_loss.py +++ b/ppocr/losses/combined_loss.py @@ -49,11 +49,15 @@ class CombinedLoss(nn.Layer): loss = loss_func(input, batch, **kargs) if isinstance(loss, paddle.Tensor): loss = {"loss_{}_{}".format(str(loss), idx): loss} + weight = self.loss_weight[idx] - for key in loss.keys(): - if key == "loss": - loss_all += loss[key] * weight - else: - loss_dict["{}_{}".format(key, idx)] = loss[key] + + loss = {key: loss[key] * weight for key in loss} + + if "loss" in loss: + loss_all += loss["loss"] + else: + loss_all += paddle.add_n(list(loss.values())) + loss_dict.update(loss) loss_dict["loss"] = loss_all return loss_dict diff --git a/ppocr/losses/distillation_loss.py b/ppocr/losses/distillation_loss.py index 75f0a77315..73d3ae2ad2 100644 --- a/ppocr/losses/distillation_loss.py +++ b/ppocr/losses/distillation_loss.py @@ -44,20 +44,22 @@ class DistillationDMLLoss(DMLLoss): def __init__(self, model_name_pairs=[], act=None, + use_log=False, key=None, maps_name=None, name="dml"): - super().__init__(act=act) + super().__init__(act=act, use_log=use_log) assert isinstance(model_name_pairs, list) self.key = key self.model_name_pairs = self._check_model_name_pairs(model_name_pairs) self.name = name self.maps_name = self._check_maps_name(maps_name) - + def _check_model_name_pairs(self, model_name_pairs): if not isinstance(model_name_pairs, list): return [] - elif isinstance(model_name_pairs[0], list) and isinstance(model_name_pairs[0][0], str): + elif isinstance(model_name_pairs[0], list) and isinstance( + model_name_pairs[0][0], str): return model_name_pairs else: return [model_name_pairs] @@ -112,9 +114,9 @@ class DistillationDMLLoss(DMLLoss): loss_dict["{}_{}_{}_{}_{}".format(key, pair[ 0], pair[1], map_name, idx)] = loss[key] else: - loss_dict["{}_{}_{}".format(self.name, self.maps_name[_c], - idx)] = loss - + loss_dict["{}_{}_{}".format(self.name, self.maps_name[ + _c], idx)] = loss + loss_dict = _sum_loss(loss_dict) return loss_dict diff --git a/ppocr/utils/save_load.py b/ppocr/utils/save_load.py index 3bb022ed98..a7d24dd71a 100644 --- a/ppocr/utils/save_load.py +++ b/ppocr/utils/save_load.py @@ -108,14 +108,15 @@ def load_dygraph_params(config, model, logger, optimizer): for k1, k2 in zip(state_dict.keys(), params.keys()): if list(state_dict[k1].shape) == list(params[k2].shape): new_state_dict[k1] = params[k2] - else: - logger.info( - f"The shape of model params {k1} {state_dict[k1].shape} not matched with loaded params {k2} {params[k2].shape} !" - ) + else: + logger.info( + f"The shape of model params {k1} {state_dict[k1].shape} not matched with loaded params {k2} {params[k2].shape} !" + ) model.set_state_dict(new_state_dict) logger.info(f"loaded pretrained_model successful from {pm}") return {} + def load_pretrained_params(model, path): if path is None: return False @@ -138,6 +139,7 @@ def load_pretrained_params(model, path): print(f"load pretrain successful from {path}") return model + def save_model(model, optimizer, model_path, From f4b3d49bd4dddda0e2762c3403aa1fa06a5021be Mon Sep 17 00:00:00 2001 From: andyjpaddle Date: Tue, 14 Sep 2021 03:31:45 +0000 Subject: [PATCH 77/77] update sar config --- configs/rec/rec_r31_sar.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index 053b1ae835..41609fdf28 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -79,7 +79,7 @@ Train: Eval: dataset: name: LMDBDataSet - data_dir: ./eval_data/evaluation/ + data_dir: ./train_data/data_lmdb_release/evaluation/ transforms: - DecodeImage: # load image img_mode: BGR