This commit is contained in:
13
deploy/hubserving/kie_ser/__init__.py
Normal file
13
deploy/hubserving/kie_ser/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/kie_ser/config.json
Normal file
15
deploy/hubserving/kie_ser/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"kie_ser": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8871,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
152
deploy/hubserving/kie_ser/module.py
Normal file
152
deploy/hubserving/kie_ser/module.py
Normal file
@@ -0,0 +1,152 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from ppstructure.kie.predict_kie_token_ser import SerPredictor
|
||||
from ppstructure.utility import parse_args
|
||||
|
||||
from deploy.hubserving.kie_ser.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="kie_ser",
|
||||
version="1.0.0",
|
||||
summary="kie ser service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/KIE_SER",
|
||||
)
|
||||
class KIESer(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.ser_predictor = SerPredictor(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of chinese texts and save path of images.
|
||||
"""
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
starttime = time.time()
|
||||
ser_res, _, elapse = self.ser_predictor(img)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
all_results.append(ser_res)
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = KIESer()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs/11.jpg",
|
||||
"./doc/imgs/12.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
38
deploy/hubserving/kie_ser/params.py
Executable file
38
deploy/hubserving/kie_ser/params.py
Executable file
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from deploy.hubserving.ocr_system.params import read_params as pp_ocr_read_params
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = pp_ocr_read_params()
|
||||
|
||||
# SER params
|
||||
cfg.kie_algorithm = "LayoutXLM"
|
||||
cfg.use_visual_backbone = False
|
||||
|
||||
cfg.ser_model_dir = "./inference/ser_vi_layoutxlm_xfund_infer"
|
||||
cfg.ser_dict_path = "train_data/XFUND/class_list_xfun.txt"
|
||||
cfg.vis_font_path = "./doc/fonts/simfang.ttf"
|
||||
cfg.ocr_order_method = "tb-yx"
|
||||
|
||||
return cfg
|
||||
13
deploy/hubserving/kie_ser_re/__init__.py
Normal file
13
deploy/hubserving/kie_ser_re/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/kie_ser_re/config.json
Normal file
15
deploy/hubserving/kie_ser_re/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"kie_ser_re": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8872,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
154
deploy/hubserving/kie_ser_re/module.py
Normal file
154
deploy/hubserving/kie_ser_re/module.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from ppstructure.kie.predict_kie_token_ser_re import SerRePredictor
|
||||
from ppstructure.utility import parse_args
|
||||
|
||||
from deploy.hubserving.kie_ser_re.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="kie_ser_re",
|
||||
version="1.0.0",
|
||||
summary="kie ser re service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/KIE_SER_RE",
|
||||
)
|
||||
class KIESerRE(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.ser_re_predictor = SerRePredictor(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of chinese texts and save path of images.
|
||||
"""
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
print(img.shape)
|
||||
starttime = time.time()
|
||||
re_res, _ = self.ser_re_predictor(img)
|
||||
print(re_res)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
all_results.append(re_res)
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = KIESerRE()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs/11.jpg",
|
||||
"./doc/imgs/12.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
40
deploy/hubserving/kie_ser_re/params.py
Executable file
40
deploy/hubserving/kie_ser_re/params.py
Executable file
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from deploy.hubserving.ocr_system.params import read_params as pp_ocr_read_params
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = pp_ocr_read_params()
|
||||
|
||||
# SER params
|
||||
cfg.kie_algorithm = "LayoutXLM"
|
||||
cfg.use_visual_backbone = False
|
||||
|
||||
cfg.ser_model_dir = "./inference/ser_vi_layoutxlm_xfund_infer"
|
||||
cfg.re_model_dir = "./inference/re_vi_layoutxlm_xfund_infer"
|
||||
|
||||
cfg.ser_dict_path = "train_data/XFUND/class_list_xfun.txt"
|
||||
cfg.vis_font_path = "./doc/fonts/simfang.ttf"
|
||||
cfg.ocr_order_method = "tb-yx"
|
||||
|
||||
return cfg
|
||||
13
deploy/hubserving/ocr_cls/__init__.py
Normal file
13
deploy/hubserving/ocr_cls/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/ocr_cls/config.json
Normal file
15
deploy/hubserving/ocr_cls/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_cls": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8866,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
160
deploy/hubserving/ocr_cls/module.py
Normal file
160
deploy/hubserving/ocr_cls/module.py
Normal file
@@ -0,0 +1,160 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from tools.infer.predict_cls import TextClassifier
|
||||
from tools.infer.utility import parse_args
|
||||
from deploy.hubserving.ocr_cls.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="ocr_cls",
|
||||
version="1.0.0",
|
||||
summary="ocr angle cls service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/text_angle_cls",
|
||||
)
|
||||
class OCRCls(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.text_classifier = TextClassifier(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the text angle in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of text detection box and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
img_list = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
continue
|
||||
img_list.append(img)
|
||||
|
||||
rec_res_final = []
|
||||
try:
|
||||
img_list, cls_res, predict_time = self.text_classifier(img_list)
|
||||
for dno in range(len(cls_res)):
|
||||
angle, score = cls_res[dno]
|
||||
rec_res_final.append(
|
||||
{
|
||||
"angle": angle,
|
||||
"confidence": float(score),
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return [[]]
|
||||
|
||||
return [rec_res_final]
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = OCRCls()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs_words/ch/word_1.jpg",
|
||||
"./doc/imgs_words/ch/word_2.jpg",
|
||||
"./doc/imgs_words/ch/word_3.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
37
deploy/hubserving/ocr_cls/params.py
Executable file
37
deploy/hubserving/ocr_cls/params.py
Executable file
@@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = Config()
|
||||
|
||||
# params for text classifier
|
||||
cfg.cls_model_dir = "./inference/ch_ppocr_mobile_v2.0_cls_infer/"
|
||||
cfg.cls_image_shape = "3, 48, 192"
|
||||
cfg.label_list = ["0", "180"]
|
||||
cfg.cls_batch_num = 30
|
||||
cfg.cls_thresh = 0.9
|
||||
|
||||
cfg.use_pdserving = False
|
||||
cfg.use_tensorrt = False
|
||||
|
||||
return cfg
|
||||
13
deploy/hubserving/ocr_det/__init__.py
Normal file
13
deploy/hubserving/ocr_det/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/ocr_det/config.json
Normal file
15
deploy/hubserving/ocr_det/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_det": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8865,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
155
deploy/hubserving/ocr_det/module.py
Normal file
155
deploy/hubserving/ocr_det/module.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
import copy
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from tools.infer.predict_det import TextDetector
|
||||
from tools.infer.utility import parse_args
|
||||
from deploy.hubserving.ocr_system.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="ocr_det",
|
||||
version="1.0.0",
|
||||
summary="ocr detection service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/text_detection",
|
||||
)
|
||||
class OCRDet(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.text_detector = TextDetector(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the text box in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of text detection box and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
dt_boxes, elapse = self.text_detector(img)
|
||||
logger.info("Predict time : {}".format(elapse))
|
||||
|
||||
rec_res_final = []
|
||||
for dno in range(len(dt_boxes)):
|
||||
rec_res_final.append(
|
||||
{"text_region": dt_boxes[dno].astype(np.int32).tolist()}
|
||||
)
|
||||
all_results.append(rec_res_final)
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = OCRDet()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs/11.jpg",
|
||||
"./doc/imgs/12.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
48
deploy/hubserving/ocr_det/params.py
Executable file
48
deploy/hubserving/ocr_det/params.py
Executable file
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = Config()
|
||||
|
||||
# params for text detector
|
||||
cfg.det_algorithm = "DB"
|
||||
cfg.det_model_dir = "./inference/PP-OCRv3_mobile_det_infer/"
|
||||
cfg.det_limit_side_len = 960
|
||||
cfg.det_limit_type = "max"
|
||||
|
||||
# DB params
|
||||
cfg.det_db_thresh = 0.3
|
||||
cfg.det_db_box_thresh = 0.6
|
||||
cfg.det_db_unclip_ratio = 1.5
|
||||
cfg.use_dilation = False
|
||||
cfg.det_db_score_mode = "fast"
|
||||
|
||||
# #EAST params
|
||||
# cfg.det_east_score_thresh = 0.8
|
||||
# cfg.det_east_cover_thresh = 0.1
|
||||
# cfg.det_east_nms_thresh = 0.2
|
||||
|
||||
cfg.use_pdserving = False
|
||||
cfg.use_tensorrt = False
|
||||
|
||||
return cfg
|
||||
13
deploy/hubserving/ocr_rec/__init__.py
Normal file
13
deploy/hubserving/ocr_rec/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/ocr_rec/config.json
Normal file
15
deploy/hubserving/ocr_rec/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_rec": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8867,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
160
deploy/hubserving/ocr_rec/module.py
Normal file
160
deploy/hubserving/ocr_rec/module.py
Normal file
@@ -0,0 +1,160 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from tools.infer.predict_rec import TextRecognizer
|
||||
from tools.infer.utility import parse_args
|
||||
from deploy.hubserving.ocr_rec.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="ocr_rec",
|
||||
version="1.0.0",
|
||||
summary="ocr recognition service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/text_recognition",
|
||||
)
|
||||
class OCRRec(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.text_recognizer = TextRecognizer(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the text box in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of text detection box and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
img_list = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
continue
|
||||
img_list.append(img)
|
||||
|
||||
rec_res_final = []
|
||||
try:
|
||||
rec_res, predict_time = self.text_recognizer(img_list)
|
||||
for dno in range(len(rec_res)):
|
||||
text, score = rec_res[dno]
|
||||
rec_res_final.append(
|
||||
{
|
||||
"text": text,
|
||||
"confidence": float(score),
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return [[]]
|
||||
|
||||
return [rec_res_final]
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = OCRRec()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs_words/ch/word_1.jpg",
|
||||
"./doc/imgs_words/ch/word_2.jpg",
|
||||
"./doc/imgs_words/ch/word_3.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
41
deploy/hubserving/ocr_rec/params.py
Normal file
41
deploy/hubserving/ocr_rec/params.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = Config()
|
||||
|
||||
# params for text recognizer
|
||||
cfg.rec_algorithm = "CRNN"
|
||||
cfg.rec_model_dir = "./inference/ch_PP-OCRv3_rec_infer/"
|
||||
|
||||
cfg.rec_image_shape = "3, 48, 320"
|
||||
cfg.rec_batch_num = 6
|
||||
cfg.max_text_length = 25
|
||||
|
||||
cfg.rec_char_dict_path = "./ppocr/utils/ppocr_keys_v1.txt"
|
||||
cfg.use_space_char = True
|
||||
|
||||
cfg.use_pdserving = False
|
||||
cfg.use_tensorrt = False
|
||||
|
||||
return cfg
|
||||
13
deploy/hubserving/ocr_system/__init__.py
Normal file
13
deploy/hubserving/ocr_system/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/ocr_system/config.json
Normal file
15
deploy/hubserving/ocr_system/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_system": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8868,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
165
deploy/hubserving/ocr_system/module.py
Normal file
165
deploy/hubserving/ocr_system/module.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from tools.infer.predict_system import TextSystem
|
||||
from tools.infer.utility import parse_args
|
||||
from deploy.hubserving.ocr_system.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="ocr_system",
|
||||
version="1.0.0",
|
||||
summary="ocr system service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/PP-OCR_system",
|
||||
)
|
||||
class OCRSystem(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.text_sys = TextSystem(cfg)
|
||||
|
||||
def merge_configs(
|
||||
self,
|
||||
):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of chinese texts and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
starttime = time.time()
|
||||
dt_boxes, rec_res, _ = self.text_sys(img)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
|
||||
dt_num = len(dt_boxes)
|
||||
rec_res_final = []
|
||||
|
||||
for dno in range(dt_num):
|
||||
text, score = rec_res[dno]
|
||||
rec_res_final.append(
|
||||
{
|
||||
"text": text,
|
||||
"confidence": float(score),
|
||||
"text_region": dt_boxes[dno].astype(np.int32).tolist(),
|
||||
}
|
||||
)
|
||||
all_results.append(rec_res_final)
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ocr = OCRSystem()
|
||||
ocr._initialize()
|
||||
image_path = [
|
||||
"./doc/imgs/11.jpg",
|
||||
"./doc/imgs/12.jpg",
|
||||
]
|
||||
res = ocr.predict(paths=image_path)
|
||||
print(res)
|
||||
68
deploy/hubserving/ocr_system/params.py
Executable file
68
deploy/hubserving/ocr_system/params.py
Executable file
@@ -0,0 +1,68 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = Config()
|
||||
|
||||
# params for text detector
|
||||
cfg.det_algorithm = "DB"
|
||||
cfg.det_model_dir = "./inference/PP-OCRv3_mobile_det_infer/"
|
||||
cfg.det_limit_side_len = 960
|
||||
cfg.det_limit_type = "max"
|
||||
|
||||
# DB params
|
||||
cfg.det_db_thresh = 0.3
|
||||
cfg.det_db_box_thresh = 0.5
|
||||
cfg.det_db_unclip_ratio = 1.6
|
||||
cfg.use_dilation = False
|
||||
cfg.det_db_score_mode = "fast"
|
||||
|
||||
# EAST params
|
||||
cfg.det_east_score_thresh = 0.8
|
||||
cfg.det_east_cover_thresh = 0.1
|
||||
cfg.det_east_nms_thresh = 0.2
|
||||
|
||||
# params for text recognizer
|
||||
cfg.rec_algorithm = "CRNN"
|
||||
cfg.rec_model_dir = "./inference/ch_PP-OCRv3_rec_infer/"
|
||||
|
||||
cfg.rec_image_shape = "3, 48, 320"
|
||||
cfg.rec_batch_num = 6
|
||||
cfg.max_text_length = 25
|
||||
|
||||
cfg.rec_char_dict_path = "./ppocr/utils/ppocr_keys_v1.txt"
|
||||
cfg.use_space_char = True
|
||||
|
||||
# params for text classifier
|
||||
cfg.use_angle_cls = True
|
||||
cfg.cls_model_dir = "./inference/ch_ppocr_mobile_v2.0_cls_infer/"
|
||||
cfg.cls_image_shape = "3, 48, 192"
|
||||
cfg.label_list = ["0", "180"]
|
||||
cfg.cls_batch_num = 30
|
||||
cfg.cls_thresh = 0.9
|
||||
|
||||
cfg.use_pdserving = False
|
||||
cfg.use_tensorrt = False
|
||||
cfg.drop_score = 0.5
|
||||
|
||||
return cfg
|
||||
250
deploy/hubserving/readme.md
Executable file
250
deploy/hubserving/readme.md
Executable file
@@ -0,0 +1,250 @@
|
||||
[English](readme_en.md) | 简体中文
|
||||
|
||||
- [基于PaddleHub Serving的服务部署](#基于paddlehub-serving的服务部署)
|
||||
- [1. 近期更新](#1-近期更新)
|
||||
- [2. 快速启动服务](#2-快速启动服务)
|
||||
- [2.1 安装PaddleHub](#21-安装PaddleHub)
|
||||
- [2.2 下载推理模型](#22-下载推理模型)
|
||||
- [2.3 安装服务模块](#23-安装服务模块)
|
||||
- [2.4 启动服务](#24-启动服务)
|
||||
- [2.4.1. 命令行命令启动(仅支持CPU)](#241-命令行命令启动仅支持cpu)
|
||||
- [2.4.2 配置文件启动(支持CPU、GPU)](#242-配置文件启动支持cpugpu)
|
||||
- [3. 发送预测请求](#3-发送预测请求)
|
||||
- [4. 返回结果格式说明](#4-返回结果格式说明)
|
||||
- [5. 自定义修改服务模块](#5-自定义修改服务模块)
|
||||
|
||||
|
||||
PaddleOCR提供2种服务部署方式:
|
||||
- 基于PaddleHub Serving的部署:代码路径为`./deploy/hubserving`,按照本教程使用;
|
||||
- 基于PaddleServing的部署:代码路径为`./deploy/pdserving`,使用方法参考[文档](../../deploy/pdserving/README_CN.md)。
|
||||
|
||||
# 基于PaddleHub Serving的服务部署
|
||||
|
||||
hubserving服务部署目录下包括文本检测、文本方向分类,文本识别、文本检测+文本方向分类+文本识别3阶段串联,版面分析、表格识别和PP-Structure七种服务包,请根据需求选择相应的服务包进行安装和启动。目录结构如下:
|
||||
```
|
||||
deploy/hubserving/
|
||||
└─ ocr_cls 文本方向分类模块服务包
|
||||
└─ ocr_det 文本检测模块服务包
|
||||
└─ ocr_rec 文本识别模块服务包
|
||||
└─ ocr_system 文本检测+文本方向分类+文本识别串联服务包
|
||||
└─ structure_layout 版面分析服务包
|
||||
└─ structure_table 表格识别服务包
|
||||
└─ structure_system PP-Structure服务包
|
||||
└─ kie_ser 关键信息抽取-SER服务包
|
||||
└─ kie_ser_re 关键信息抽取-SER+RE服务包
|
||||
```
|
||||
|
||||
每个服务包下包含3个文件。以2阶段串联服务包为例,目录如下:
|
||||
```
|
||||
deploy/hubserving/ocr_system/
|
||||
└─ __init__.py 空文件,必选
|
||||
└─ config.json 配置文件,可选,使用配置启动服务时作为参数传入
|
||||
└─ module.py 主模块,必选,包含服务的完整逻辑
|
||||
└─ params.py 参数文件,必选,包含模型路径、前后处理参数等参数
|
||||
```
|
||||
## 1. 近期更新
|
||||
|
||||
* 2022.10.09 新增关键信息抽取服务。
|
||||
* 2022.08.23 新增版面分析服务。
|
||||
* 2022.05.05 新增PP-OCRv3检测和识别模型。
|
||||
* 2022.03.30 新增PP-Structure和表格识别两种服务。
|
||||
|
||||
## 2. 快速启动服务
|
||||
以下步骤以检测+识别2阶段串联服务为例,如果只需要检测服务或识别服务,替换相应文件路径即可。
|
||||
### 2.1 安装PaddleHub
|
||||
paddlehub 需要 python>3.6.2
|
||||
```bash
|
||||
pip3 install paddlehub==2.1.0 --upgrade -i https://mirror.baidu.com/pypi/simple
|
||||
```
|
||||
|
||||
### 2.2 下载推理模型
|
||||
安装服务模块前,需要准备推理模型并放到正确路径。默认使用的是PP-OCRv3模型,默认模型路径为:
|
||||
| 模型 | 路径 |
|
||||
| ------- | - |
|
||||
| 检测模型 | `./inference/PP-OCRv3_mobile_det_infer/` |
|
||||
| 识别模型 | `./inference/ch_PP-OCRv3_rec_infer/` |
|
||||
| 方向分类器 | `./inference/ch_ppocr_mobile_v2.0_cls_infer/` |
|
||||
| 版面分析模型 | `./inference/picodet_lcnet_x1_0_fgd_layout_infer/` |
|
||||
| 表格结构识别模型 | `./inference/ch_ppstructure_mobile_v2.0_SLANet_infer/` |
|
||||
| 关键信息抽取SER模型 | `./inference/ser_vi_layoutxlm_xfund_infer/` |
|
||||
| 关键信息抽取RE模型 | `./inference/re_vi_layoutxlm_xfund_infer/` |
|
||||
|
||||
**模型路径可在`params.py`中查看和修改。**
|
||||
|
||||
更多模型可以从PaddleOCR提供的模型库[PP-OCR](../../doc/doc_ch/models_list.md)和[PP-Structure](../../ppstructure/docs/models_list.md)下载,也可以替换成自己训练转换好的模型。
|
||||
|
||||
### 2.3 安装服务模块
|
||||
PaddleOCR提供5种服务模块,根据需要安装所需模块。
|
||||
|
||||
在Linux环境(Windows环境请将`/`替换为`\`)下,安装模块命令如下表:
|
||||
| 服务模块 | 命令 |
|
||||
| ------- | - |
|
||||
| 检测 | `hub install deploy/hubserving/ocr_det` |
|
||||
| 分类 | `hub install deploy/hubserving/ocr_cls` |
|
||||
| 识别 | `hub install deploy/hubserving/ocr_rec` |
|
||||
| 检测+识别串联 | `hub install deploy/hubserving/ocr_system` |
|
||||
| 表格识别 | `hub install deploy/hubserving/structure_table` |
|
||||
| PP-Structure | `hub install deploy/hubserving/structure_system` |
|
||||
| 版面分析 | `hub install deploy/hubserving/structure_layout` |
|
||||
| 关键信息抽取SER | `hub install deploy/hubserving/kie_ser` |
|
||||
| 关键信息抽取SER+RE | `hub install deploy/hubserving/kie_ser_re` |
|
||||
|
||||
### 2.4 启动服务
|
||||
#### 2.4.1. 命令行命令启动(仅支持CPU)
|
||||
**启动命令:**
|
||||
```bash
|
||||
hub serving start --modules Module1==Version1, Module2==Version2, ... \
|
||||
--port 8866 \
|
||||
--use_multiprocess \
|
||||
--workers \
|
||||
```
|
||||
|
||||
**参数:**
|
||||
|参数|用途|
|
||||
|---|---|
|
||||
|`--modules`/`-m`|PaddleHub Serving预安装模型,以多个Module==Version键值对的形式列出<br>**当不指定Version时,默认选择最新版本**|
|
||||
|`--port`/`-p`|服务端口,默认为8866|
|
||||
|`--use_multiprocess`|是否启用并发方式,默认为单进程方式,推荐多核CPU机器使用此方式<br>**Windows操作系统只支持单进程方式**|
|
||||
|`--workers`|在并发方式下指定的并发任务数,默认为`2*cpu_count-1`,其中`cpu_count`为CPU核数|
|
||||
|
||||
如启动串联服务:
|
||||
```bash
|
||||
hub serving start -m ocr_system
|
||||
```
|
||||
|
||||
这样就完成了一个服务化API的部署,使用默认端口号8866。
|
||||
|
||||
#### 2.4.2 配置文件启动(支持CPU、GPU)
|
||||
**启动命令:**
|
||||
```bash
|
||||
hub serving start -c config.json
|
||||
```
|
||||
|
||||
其中,`config.json`格式如下:
|
||||
```json
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_system": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8868,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
```
|
||||
|
||||
- `init_args`中的可配参数与`module.py`中的`_initialize`函数接口一致。
|
||||
|
||||
**当`use_gpu`为`true`时,表示使用GPU启动服务。**
|
||||
- `predict_args`中的可配参数与`module.py`中的`predict`函数接口一致。
|
||||
|
||||
**注意:**
|
||||
- 使用配置文件启动服务时,其他参数会被忽略。
|
||||
- 如果使用GPU预测(即,`use_gpu`置为`true`),则需要在启动服务之前,设置CUDA_VISIBLE_DEVICES环境变量,如:
|
||||
```bash
|
||||
export CUDA_VISIBLE_DEVICES=0
|
||||
```
|
||||
- **`use_gpu`不可与`use_multiprocess`同时为`true`**。
|
||||
|
||||
如,使用GPU 3号卡启动串联服务:
|
||||
```bash
|
||||
export CUDA_VISIBLE_DEVICES=3
|
||||
hub serving start -c deploy/hubserving/ocr_system/config.json
|
||||
```
|
||||
|
||||
## 3. 发送预测请求
|
||||
配置好服务端,可使用以下命令发送预测请求,获取预测结果:
|
||||
```bash
|
||||
python tools/test_hubserving.py --server_url=server_url --image_dir=image_path
|
||||
```
|
||||
|
||||
需要给脚本传递2个参数:
|
||||
- `server_url`:服务地址,格式为`http://[ip_address]:[port]/predict/[module_name]`
|
||||
|
||||
例如,如果使用配置文件启动分类,检测、识别,检测+分类+识别3阶段,表格识别和PP-Structure服务
|
||||
|
||||
并为每个服务修改了port,那么发送请求的url将分别是:
|
||||
```
|
||||
http://127.0.0.1:8865/predict/ocr_det
|
||||
http://127.0.0.1:8866/predict/ocr_cls
|
||||
http://127.0.0.1:8867/predict/ocr_rec
|
||||
http://127.0.0.1:8868/predict/ocr_system
|
||||
http://127.0.0.1:8869/predict/structure_table
|
||||
http://127.0.0.1:8870/predict/structure_system
|
||||
http://127.0.0.1:8870/predict/structure_layout
|
||||
http://127.0.0.1:8871/predict/kie_ser
|
||||
http://127.0.0.1:8872/predict/kie_ser_re
|
||||
```
|
||||
- `image_dir`:测试图像路径,可以是单张图片路径,也可以是图像集合目录路径
|
||||
- `visualize`:是否可视化结果,默认为False
|
||||
- `output`:可视化结果保存路径,默认为`./hubserving_result`
|
||||
|
||||
访问示例:
|
||||
```bash
|
||||
python tools/test_hubserving.py --server_url=http://127.0.0.1:8868/predict/ocr_system --image_dir=./doc/imgs/ --visualize=false
|
||||
```
|
||||
|
||||
## 4. 返回结果格式说明
|
||||
返回结果为列表(list),列表中的每一项为词典(dict),词典一共可能包含3种字段,信息如下:
|
||||
|字段名称|数据类型|意义|
|
||||
|---|---|---|
|
||||
|angle|str|文本角度|
|
||||
|text|str|文本内容|
|
||||
|confidence|float| 文本识别置信度或文本角度分类置信度|
|
||||
|text_region|list|文本位置坐标|
|
||||
|html|str|表格的html字符串|
|
||||
|regions|list|版面分析+表格识别+OCR的结果,每一项为一个list<br>包含表示区域坐标的`bbox`,区域类型的`type`和区域结果的`res`三个字段|
|
||||
|layout|list|版面分析的结果,每一项一个dict,包含版面区域坐标的`bbox`,区域类型的`label`|
|
||||
|
||||
不同模块返回的字段不同,如,文本识别服务模块返回结果不含`text_region`字段,具体信息如下:
|
||||
|字段名/模块名 |ocr_det |ocr_cls |ocr_rec |ocr_system |structure_table |structure_system |structure_layout |kie_ser |kie_re |
|
||||
|--- |--- |--- |--- |--- |--- |--- |--- |--- |--- |
|
||||
|angle | |✔ | |✔ | | | |
|
||||
|text | | |✔ |✔ | |✔ | |✔ |✔ |
|
||||
|confidence | |✔ |✔ |✔ | |✔ | |✔ |✔ |
|
||||
|text_region |✔ | | |✔ | |✔ | |✔ |✔ |
|
||||
|html | | | | |✔ |✔ | | | |
|
||||
|regions | | | | |✔ |✔ | | | |
|
||||
|layout | | | | | | |✔ | | |
|
||||
|ser_res | | | | | | | |✔ | |
|
||||
|re_res | | | | | | | | |✔ |
|
||||
|
||||
**说明:** 如果需要增加、删除、修改返回字段,可在相应模块的`module.py`文件中进行修改,完整流程参考下一节自定义修改服务模块。
|
||||
|
||||
## 5. 自定义修改服务模块
|
||||
如果需要修改服务逻辑,一般需要操作以下步骤(以修改`deploy/hubserving/ocr_system`为例):
|
||||
|
||||
1. 停止服务:
|
||||
```bash
|
||||
hub serving stop --port/-p XXXX
|
||||
```
|
||||
2. 到`deploy/hubserving/ocr_system`下的`module.py`和`params.py`等文件中根据实际需求修改代码。
|
||||
|
||||
例如,如果需要替换部署服务所用模型,则需要到`params.py`中修改模型路径参数`det_model_dir`和`rec_model_dir`,如果需要关闭文本方向分类器,则将参数`use_angle_cls`置为`False`
|
||||
|
||||
当然,同时可能还需要修改其他相关参数,请根据实际情况修改调试。
|
||||
|
||||
**强烈建议修改后先直接运行`module.py`调试,能正确运行预测后再启动服务测试。**
|
||||
|
||||
**注意:** PPOCR-v3识别模型使用的图片输入shape为`3,48,320`,因此需要修改`params.py`中的`cfg.rec_image_shape = "3, 48, 320"`,如果不使用PPOCR-v3识别模型,则无需修改该参数。
|
||||
3. (可选)如果想要重命名模块需要更改`module.py`文件中的以下行:
|
||||
- [`from deploy.hubserving.ocr_system.params import read_params`中的`ocr_system`](https://github.com/PaddlePaddle/PaddleOCR/blob/a923f35de57b5e378f8dd16e54d0a3e4f51267fd/deploy/hubserving/ocr_system/module.py#L35)
|
||||
- [`name="ocr_system",`中的`ocr_system`](https://github.com/PaddlePaddle/PaddleOCR/blob/a923f35de57b5e378f8dd16e54d0a3e4f51267fd/deploy/hubserving/ocr_system/module.py#L39)
|
||||
4. (可选)可能需要删除`__pycache__`目录以强制刷新CPython缓存:
|
||||
```bash
|
||||
find deploy/hubserving/ocr_system -name '__pycache__' -exec rm -r {} \;
|
||||
```
|
||||
5. 安装修改后的新服务包:
|
||||
```bash
|
||||
hub install deploy/hubserving/ocr_system
|
||||
```
|
||||
6. 重新启动服务:
|
||||
```bash
|
||||
hub serving start -m ocr_system
|
||||
```
|
||||
249
deploy/hubserving/readme_en.md
Executable file
249
deploy/hubserving/readme_en.md
Executable file
@@ -0,0 +1,249 @@
|
||||
English | [简体中文](readme.md)
|
||||
|
||||
- [Service deployment based on PaddleHub Serving](#service-deployment-based-on-paddlehub-serving)
|
||||
- [1. Update](#1-update)
|
||||
- [2. Quick start service](#2-quick-start-service)
|
||||
- [2.1 Install PaddleHub](#21-install-paddlehub)
|
||||
- [2.2 Download inference model](#22-download-inference-model)
|
||||
- [2.3 Install Service Module](#23-install-service-module)
|
||||
- [2.4 Start service](#24-start-service)
|
||||
- [2.4.1 Start with command line parameters (CPU only)](#241-start-with-command-line-parameters-cpu-only)
|
||||
- [2.4.2 Start with configuration file(CPU and GPU)](#242-start-with-configuration-filecpugpu)
|
||||
- [3. Send prediction requests](#3-send-prediction-requests)
|
||||
- [4. Returned result format](#4-returned-result-format)
|
||||
- [5. User-defined service module modification](#5-user-defined-service-module-modification)
|
||||
|
||||
PaddleOCR provides 2 service deployment methods:
|
||||
- Based on **PaddleHub Serving**: Code path is `./deploy/hubserving`. Please follow this tutorial.
|
||||
- Based on **PaddleServing**: Code path is `./deploy/pdserving`. Please refer to the [tutorial](../../deploy/pdserving/README.md) for usage.
|
||||
|
||||
# Service deployment based on PaddleHub Serving
|
||||
|
||||
The hubserving service deployment directory includes seven service packages: text detection, text angle class, text recognition, text detection+text angle class+text recognition three-stage series connection, layout analysis, table recognition, and PP-Structure. Please select the corresponding service package to install and start the service according to your needs. The directory is as follows:
|
||||
```
|
||||
deploy/hubserving/
|
||||
└─ ocr_det text detection module service package
|
||||
└─ ocr_cls text angle class module service package
|
||||
└─ ocr_rec text recognition module service package
|
||||
└─ ocr_system text detection+text angle class+text recognition three-stage series connection service package
|
||||
└─ structure_layout layout analysis service package
|
||||
└─ structure_table table recognition service package
|
||||
└─ structure_system PP-Structure service package
|
||||
└─ kie_ser KIE(SER) service package
|
||||
└─ kie_ser_re KIE(SER+RE) service package
|
||||
```
|
||||
|
||||
Each service pack contains 3 files. Take the 2-stage series connection service package as an example, the directory is as follows:
|
||||
```
|
||||
deploy/hubserving/ocr_system/
|
||||
└─ __init__.py Empty file, required
|
||||
└─ config.json Configuration file, optional, passed in as a parameter when using configuration to start the service
|
||||
└─ module.py Main module file, required, contains the complete logic of the service
|
||||
└─ params.py Parameter file, required, including parameters such as model path, pre and post-processing parameters
|
||||
```
|
||||
## 1. Update
|
||||
|
||||
* 2022.10.09 add KIE services.
|
||||
* 2022.08.23 add layout analysis services.
|
||||
* 2022.03.30 add PP-Structure and table recognition services.
|
||||
* 2022.05.05 add PP-OCRv3 text detection and recognition services.
|
||||
|
||||
## 2. Quick start service
|
||||
The following steps take the 2-stage series service as an example. If only the detection service or recognition service is needed, replace the corresponding file path.
|
||||
|
||||
### 2.1 Install PaddleHub
|
||||
```bash
|
||||
pip3 install paddlehub==2.1.0 --upgrade
|
||||
```
|
||||
|
||||
### 2.2 Download inference model
|
||||
Before installing the service module, you need to prepare the inference model and put it in the correct path. By default, the PP-OCRv3 models are used, and the default model path is:
|
||||
| Model | Path |
|
||||
| ------- | - |
|
||||
| text detection model | ./inference/PP-OCRv3_mobile_det_infer/ |
|
||||
| text recognition model | ./inference/ch_PP-OCRv3_rec_infer/ |
|
||||
| text angle classifier | ./inference/ch_ppocr_mobile_v2.0_cls_infer/ |
|
||||
| layout parse model | ./inference/picodet_lcnet_x1_0_fgd_layout_infer/ |
|
||||
| tanle recognition | ./inference/ch_ppstructure_mobile_v2.0_SLANet_infer/ |
|
||||
| KIE(SER) | ./inference/ser_vi_layoutxlm_xfund_infer/ |
|
||||
| KIE(SER+RE) | ./inference/re_vi_layoutxlm_xfund_infer/ |
|
||||
|
||||
**The model path can be found and modified in `params.py`.**
|
||||
More models provided by PaddleOCR can be obtained from the [model library](../../doc/doc_en/models_list_en.md). You can also use models trained by yourself.
|
||||
|
||||
### 2.3 Install Service Module
|
||||
PaddleOCR provides 5 kinds of service modules, install the required modules according to your needs.
|
||||
|
||||
* On the Linux platform(replace `/` with `\` if using Windows), the examples are as the following table:
|
||||
| Service model | Command |
|
||||
| text detection | `hub install deploy/hubserving/ocr_det` |
|
||||
| text angle class: | `hub install deploy/hubserving/ocr_cls` |
|
||||
| text recognition: | `hub install deploy/hubserving/ocr_rec` |
|
||||
| 2-stage series: | `hub install deploy/hubserving/ocr_system` |
|
||||
| table recognition | `hub install deploy/hubserving/structure_table` |
|
||||
| PP-Structure | `hub install deploy/hubserving/structure_system` |
|
||||
| KIE(SER) | `hub install deploy/hubserving/kie_ser` |
|
||||
| KIE(SER+RE) | `hub install deploy/hubserving/kie_ser_re` |
|
||||
|
||||
### 2.4 Start service
|
||||
#### 2.4.1 Start with command line parameters (CPU only)
|
||||
**start command:**
|
||||
```bash
|
||||
hub serving start --modules Module1==Version1, Module2==Version2, ... \
|
||||
--port 8866 \
|
||||
--use_multiprocess \
|
||||
--workers \
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|parameters|usage|
|
||||
|---|---|
|
||||
|`--modules`/`-m`|PaddleHub Serving pre-installed model, listed in the form of multiple Module==Version key-value pairs<br>**When Version is not specified, the latest version is selected by default**|
|
||||
|`--port`/`-p`|Service port, default is 8866|
|
||||
|`--use_multiprocess`|Enable concurrent mode, by default using the single-process mode, this mode is recommended for multi-core CPU machines<br>**Windows operating system only supports single-process mode**|
|
||||
|`--workers`|The number of concurrent tasks specified in concurrent mode, the default is `2*cpu_count-1`, where `cpu_count` is the number of CPU cores|
|
||||
|
||||
For example, start the 2-stage series service:
|
||||
```bash
|
||||
hub serving start -m ocr_system
|
||||
```
|
||||
|
||||
This completes the deployment of a service API, using the default port number 8866.
|
||||
|
||||
#### 2.4.2 Start with configuration file(CPU and GPU)
|
||||
**start command:**
|
||||
```bash
|
||||
hub serving start --config/-c config.json
|
||||
```
|
||||
|
||||
In which the format of `config.json` is as follows:
|
||||
```json
|
||||
{
|
||||
"modules_info": {
|
||||
"ocr_system": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8868,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
```
|
||||
- The configurable parameters in `init_args` are consistent with the `_initialize` function interface in `module.py`.
|
||||
|
||||
**When `use_gpu` is `true`, it means that the GPU is used to start the service**.
|
||||
- The configurable parameters in `predict_args` are consistent with the `predict` function interface in `module.py`.
|
||||
|
||||
**Note:**
|
||||
- When using the configuration file to start the service, other parameters will be ignored.
|
||||
- If you use GPU prediction (that is, `use_gpu` is set to `true`), you need to set the environment variable CUDA_VISIBLE_DEVICES before starting the service, such as:
|
||||
```bash
|
||||
export CUDA_VISIBLE_DEVICES=0
|
||||
```
|
||||
- **`use_gpu` and `use_multiprocess` cannot be `true` at the same time.**
|
||||
|
||||
For example, use GPU card No. 3 to start the 2-stage series service:
|
||||
```bash
|
||||
export CUDA_VISIBLE_DEVICES=3
|
||||
hub serving start -c deploy/hubserving/ocr_system/config.json
|
||||
```
|
||||
|
||||
## 3. Send prediction requests
|
||||
After the service starts, you can use the following command to send a prediction request to obtain the prediction result:
|
||||
```bash
|
||||
python tools/test_hubserving.py --server_url=server_url --image_dir=image_path
|
||||
```
|
||||
|
||||
Two parameters need to be passed to the script:
|
||||
- **server_url**:service address, the format of which is
|
||||
`http://[ip_address]:[port]/predict/[module_name]`
|
||||
|
||||
For example, if using the configuration file to start the text angle classification, text detection, text recognition, detection+classification+recognition 3 stages, table recognition and PP-Structure service,
|
||||
|
||||
also modified the port for each service, then the `server_url` to send the request will be:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8865/predict/ocr_det
|
||||
http://127.0.0.1:8866/predict/ocr_cls
|
||||
http://127.0.0.1:8867/predict/ocr_rec
|
||||
http://127.0.0.1:8868/predict/ocr_system
|
||||
http://127.0.0.1:8869/predict/structure_table
|
||||
http://127.0.0.1:8870/predict/structure_system
|
||||
http://127.0.0.1:8870/predict/structure_layout
|
||||
http://127.0.0.1:8871/predict/kie_ser
|
||||
http://127.0.0.1:8872/predict/kie_ser_re
|
||||
```
|
||||
- **image_dir**:Test image path, which can be a single image path or an image directory path
|
||||
- **visualize**:Whether to visualize the results, the default value is False
|
||||
- **output**:The folder to save the Visualization result, the default value is `./hubserving_result`
|
||||
|
||||
Example:
|
||||
```bash
|
||||
python tools/test_hubserving.py --server_url=http://127.0.0.1:8868/predict/ocr_system --image_dir=./doc/imgs/ --visualize=false`
|
||||
```
|
||||
|
||||
## 4. Returned result format
|
||||
The returned result is a list. Each item in the list is a dictionary which may contain three fields. The information is as follows:
|
||||
|
||||
|field name|data type|description|
|
||||
|----|----|----|
|
||||
|angle|str|angle|
|
||||
|text|str|text content|
|
||||
|confidence|float|text recognition confidence|
|
||||
|text_region|list|text location coordinates|
|
||||
|html|str|table HTML string|
|
||||
|regions|list|The result of layout analysis + table recognition + OCR, each item is a list<br>including `bbox` indicating area coordinates, `type` of area type and `res` of area results|
|
||||
|layout|list|The result of layout analysis, each item is a dict, including `bbox` indicating area coordinates, `label` of area type|
|
||||
|
||||
The fields returned by different modules are different. For example, the results returned by the text recognition service module do not contain `text_region`, detailed table is as follows:
|
||||
|
||||
|field name/module name |ocr_det |ocr_cls |ocr_rec |ocr_system |structure_table |structure_system |structure_layout |kie_ser |kie_re |
|
||||
|--- |--- |--- |--- |--- |--- |--- |--- |--- |--- |
|
||||
|angle | |✔ | |✔ | | | |
|
||||
|text | | |✔ |✔ | |✔ | |✔ |✔ |
|
||||
|confidence | |✔ |✔ |✔ | |✔ | |✔ |✔ |
|
||||
|text_region |✔ | | |✔ | |✔ | |✔ |✔ |
|
||||
|html | | | | |✔ |✔ | | | |
|
||||
|regions | | | | |✔ |✔ | | | |
|
||||
|layout | | | | | | |✔ | | |
|
||||
|ser_res | | | | | | | |✔ | |
|
||||
|re_res | | | | | | | | |✔ |
|
||||
|
||||
**Note:** If you need to add, delete or modify the returned fields, you can modify the file `module.py` of the corresponding module. For the complete process, refer to the user-defined modification service module in the next section.
|
||||
|
||||
## 5. User-defined service module modification
|
||||
If you need to modify the service logic, the following steps are generally required (take the modification of `deploy/hubserving/ocr_system` for example):
|
||||
|
||||
1. Stop service:
|
||||
```bash
|
||||
hub serving stop --port/-p XXXX
|
||||
```
|
||||
2. Modify the code in the corresponding files under `deploy/hubserving/ocr_system`, such as `module.py` and `params.py`, to your actual needs.
|
||||
|
||||
For example, if you need to replace the model used by the deployed service, you need to modify model path parameters `det_model_dir` and `rec_model_dir` in `params.py`. If you want to turn off the text direction classifier, set the parameter `use_angle_cls` to `False`.
|
||||
|
||||
Of course, other related parameters may need to be modified at the same time. Please modify and debug according to the actual situation.
|
||||
|
||||
**It is suggested to run `module.py` directly for debugging after modification before starting the service test.**
|
||||
|
||||
**Note** The image input shape used by the PPOCR-v3 recognition model is `3, 48, 320`, so you need to modify `cfg.rec_image_shape = "3, 48, 320"` in `params.py`, if you do not use the PPOCR-v3 recognition model, then there is no need to modify this parameter.
|
||||
3. (Optional) If you want to rename the module, the following lines should be modified:
|
||||
- [`ocr_system` within `from deploy.hubserving.ocr_system.params import read_params`](https://github.com/PaddlePaddle/PaddleOCR/blob/a923f35de57b5e378f8dd16e54d0a3e4f51267fd/deploy/hubserving/ocr_system/module.py#L35)
|
||||
- [`ocr_system` within `name="ocr_system",`](https://github.com/PaddlePaddle/PaddleOCR/blob/a923f35de57b5e378f8dd16e54d0a3e4f51267fd/deploy/hubserving/ocr_system/module.py#L39)
|
||||
4. (Optional) It may require you to delete the directory `__pycache__` to force flush build cache of CPython:
|
||||
```bash
|
||||
find deploy/hubserving/ocr_system -name '__pycache__' -exec rm -r {} \;
|
||||
```
|
||||
5. Install modified service module:
|
||||
```bash
|
||||
hub install deploy/hubserving/ocr_system/
|
||||
```
|
||||
6. Restart service:
|
||||
```bash
|
||||
hub serving start -m ocr_system
|
||||
```
|
||||
13
deploy/hubserving/structure_layout/__init__.py
Normal file
13
deploy/hubserving/structure_layout/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/structure_layout/config.json
Normal file
15
deploy/hubserving/structure_layout/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"structure_layout": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8871,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
148
deploy/hubserving/structure_layout/module.py
Normal file
148
deploy/hubserving/structure_layout/module.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from ppstructure.layout.predict_layout import LayoutPredictor as _LayoutPredictor
|
||||
from ppstructure.utility import parse_args
|
||||
from deploy.hubserving.structure_layout.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="structure_layout",
|
||||
version="1.0.0",
|
||||
summary="PP-Structure layout service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/structure_layout",
|
||||
)
|
||||
class LayoutPredictor(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.layout_predictor = _LayoutPredictor(cfg)
|
||||
|
||||
def merge_configs(self):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The layout results of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
starttime = time.time()
|
||||
res, _ = self.layout_predictor(img)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
|
||||
for item in res:
|
||||
item["bbox"] = item["bbox"].tolist()
|
||||
all_results.append({"layout": res})
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
layout = LayoutPredictor()
|
||||
layout._initialize()
|
||||
image_path = ["./ppstructure/docs/table/1.png"]
|
||||
res = layout.predict(paths=image_path)
|
||||
print(res)
|
||||
32
deploy/hubserving/structure_layout/params.py
Executable file
32
deploy/hubserving/structure_layout/params.py
Executable file
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Config(object):
|
||||
pass
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = Config()
|
||||
|
||||
# params for layout analysis
|
||||
cfg.layout_model_dir = "./inference/picodet_lcnet_x1_0_fgd_layout_infer/"
|
||||
cfg.layout_dict_path = "./ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt"
|
||||
cfg.layout_score_threshold = 0.5
|
||||
cfg.layout_nms_threshold = 0.5
|
||||
return cfg
|
||||
13
deploy/hubserving/structure_system/__init__.py
Normal file
13
deploy/hubserving/structure_system/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/structure_system/config.json
Normal file
15
deploy/hubserving/structure_system/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"structure_system": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8870,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
154
deploy/hubserving/structure_system/module.py
Normal file
154
deploy/hubserving/structure_system/module.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from ppstructure.predict_system import StructureSystem as PPStructureSystem
|
||||
from ppstructure.predict_system import save_structure_res
|
||||
from ppstructure.utility import parse_args
|
||||
from deploy.hubserving.structure_system.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="structure_system",
|
||||
version="1.0.0",
|
||||
summary="PP-Structure system service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/structure_system",
|
||||
)
|
||||
class StructureSystem(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.table_sys = PPStructureSystem(cfg)
|
||||
|
||||
def merge_configs(self):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of chinese texts and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
starttime = time.time()
|
||||
res, _ = self.table_sys(img)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
|
||||
# parse result
|
||||
res_final = []
|
||||
for region in res:
|
||||
region.pop("img")
|
||||
res_final.append(region)
|
||||
all_results.append({"regions": res_final})
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
structure_system = StructureSystem()
|
||||
structure_system._initialize()
|
||||
image_path = ["./ppstructure/docs/table/1.png"]
|
||||
res = structure_system.predict(paths=image_path)
|
||||
print(res)
|
||||
33
deploy/hubserving/structure_system/params.py
Executable file
33
deploy/hubserving/structure_system/params.py
Executable file
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from deploy.hubserving.structure_table.params import read_params as table_read_params
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = table_read_params()
|
||||
|
||||
# params for layout parser model
|
||||
cfg.layout_model_dir = ""
|
||||
cfg.layout_dict_path = "./ppocr/utils/dict/layout_publaynet_dict.txt"
|
||||
cfg.layout_score_threshold = 0.5
|
||||
cfg.layout_nms_threshold = 0.5
|
||||
|
||||
cfg.mode = "structure"
|
||||
cfg.output = "./output"
|
||||
return cfg
|
||||
13
deploy/hubserving/structure_table/__init__.py
Normal file
13
deploy/hubserving/structure_table/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
15
deploy/hubserving/structure_table/config.json
Normal file
15
deploy/hubserving/structure_table/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"modules_info": {
|
||||
"structure_table": {
|
||||
"init_args": {
|
||||
"version": "1.0.0",
|
||||
"use_gpu": true
|
||||
},
|
||||
"predict_args": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": 8869,
|
||||
"use_multiprocess": false,
|
||||
"workers": 2
|
||||
}
|
||||
148
deploy/hubserving/structure_table/module.py
Normal file
148
deploy/hubserving/structure_table/module.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
import copy
|
||||
|
||||
import time
|
||||
import paddlehub
|
||||
from paddlehub.common.logger import logger
|
||||
from paddlehub.module.module import moduleinfo, runnable, serving
|
||||
import cv2
|
||||
import numpy as np
|
||||
import paddlehub as hub
|
||||
|
||||
from tools.infer.utility import base64_to_cv2
|
||||
from ppstructure.table.predict_table import TableSystem as _TableSystem
|
||||
from ppstructure.predict_system import save_structure_res
|
||||
from ppstructure.utility import parse_args
|
||||
from deploy.hubserving.structure_table.params import read_params
|
||||
|
||||
|
||||
@moduleinfo(
|
||||
name="structure_table",
|
||||
version="1.0.0",
|
||||
summary="PP-Structure table service",
|
||||
author="paddle-dev",
|
||||
author_email="paddle-dev@baidu.com",
|
||||
type="cv/structure_table",
|
||||
)
|
||||
class TableSystem(hub.Module):
|
||||
def _initialize(self, use_gpu=False, enable_mkldnn=False):
|
||||
"""
|
||||
initialize with the necessary elements
|
||||
"""
|
||||
cfg = self.merge_configs()
|
||||
cfg.use_gpu = use_gpu
|
||||
if use_gpu:
|
||||
try:
|
||||
_places = os.environ["CUDA_VISIBLE_DEVICES"]
|
||||
int(_places[0])
|
||||
print("use gpu: ", use_gpu)
|
||||
print("CUDA_VISIBLE_DEVICES: ", _places)
|
||||
cfg.gpu_mem = 8000
|
||||
except:
|
||||
raise RuntimeError(
|
||||
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES via export CUDA_VISIBLE_DEVICES=cuda_device_id."
|
||||
)
|
||||
cfg.ir_optim = True
|
||||
cfg.enable_mkldnn = enable_mkldnn
|
||||
|
||||
self.table_sys = _TableSystem(cfg)
|
||||
|
||||
def merge_configs(self):
|
||||
# default cfg
|
||||
backup_argv = copy.deepcopy(sys.argv)
|
||||
sys.argv = sys.argv[:1]
|
||||
cfg = parse_args()
|
||||
|
||||
update_cfg_map = vars(read_params())
|
||||
|
||||
for key in update_cfg_map:
|
||||
cfg.__setattr__(key, update_cfg_map[key])
|
||||
|
||||
sys.argv = copy.deepcopy(backup_argv)
|
||||
return cfg
|
||||
|
||||
def read_images(self, paths=[]):
|
||||
images = []
|
||||
for img_path in paths:
|
||||
assert os.path.isfile(img_path), "The {} isn't a valid file.".format(
|
||||
img_path
|
||||
)
|
||||
img = cv2.imread(img_path)
|
||||
if img is None:
|
||||
logger.info("error in loading image:{}".format(img_path))
|
||||
continue
|
||||
images.append(img)
|
||||
return images
|
||||
|
||||
def predict(self, images=[], paths=[]):
|
||||
"""
|
||||
Get the chinese texts in the predicted images.
|
||||
Args:
|
||||
images (list(numpy.ndarray)): images data, shape of each is [H, W, C]. If images not paths
|
||||
paths (list[str]): The paths of images. If paths not images
|
||||
Returns:
|
||||
res (list): The result of chinese texts and save path of images.
|
||||
"""
|
||||
|
||||
if images != [] and isinstance(images, list) and paths == []:
|
||||
predicted_data = images
|
||||
elif images == [] and isinstance(paths, list) and paths != []:
|
||||
predicted_data = self.read_images(paths)
|
||||
else:
|
||||
raise TypeError("The input data is inconsistent with expectations.")
|
||||
|
||||
assert (
|
||||
predicted_data != []
|
||||
), "There is not any image to be predicted. Please check the input data."
|
||||
|
||||
all_results = []
|
||||
for img in predicted_data:
|
||||
if img is None:
|
||||
logger.info("error in loading image")
|
||||
all_results.append([])
|
||||
continue
|
||||
starttime = time.time()
|
||||
res, _ = self.table_sys(img)
|
||||
elapse = time.time() - starttime
|
||||
logger.info("Predict time: {}".format(elapse))
|
||||
|
||||
all_results.append({"html": res["html"]})
|
||||
return all_results
|
||||
|
||||
@serving
|
||||
def serving_method(self, images, **kwargs):
|
||||
"""
|
||||
Run as a service.
|
||||
"""
|
||||
images_decode = [base64_to_cv2(image) for image in images]
|
||||
results = self.predict(images_decode, **kwargs)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
table_system = TableSystem()
|
||||
table_system._initialize()
|
||||
image_path = ["./ppstructure/docs/table/table.jpg"]
|
||||
res = table_system.predict(paths=image_path)
|
||||
print(res)
|
||||
30
deploy/hubserving/structure_table/params.py
Executable file
30
deploy/hubserving/structure_table/params.py
Executable file
@@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from deploy.hubserving.ocr_system.params import read_params as pp_ocr_read_params
|
||||
|
||||
|
||||
def read_params():
|
||||
cfg = pp_ocr_read_params()
|
||||
|
||||
# params for table structure model
|
||||
cfg.table_max_len = 488
|
||||
cfg.table_model_dir = "./inference/en_ppocr_mobile_v2.0_table_structure_infer/"
|
||||
cfg.table_char_dict_path = "./ppocr/utils/dict/table_structure_dict.txt"
|
||||
cfg.show_log = False
|
||||
return cfg
|
||||
Reference in New Issue
Block a user