El servidor GPU HUAWEI CLOUD implementa el servicio de reconocimiento chino-inglés PaddleOCR

prefacio

Recientemente, usé el servicio de OCR en un proyecto de la empresa. Al principio, usé la interfaz de reconocimiento de texto universal en Baidu Cloud. Más tarde, accidentalmente me enteré de que el módulo PaddleOCR de la plataforma fly-pulse de código abierto de Baidu tiene un modelo listo que se puede usar directamente, así que configuré una versión de CPU del servicio de reconocimiento de OCR en el servidor de la empresa. Debido al rendimiento del servidor de la empresa y al problema de la versión de la CPU, el rendimiento no cumplió con los requisitos, así que compré el servidor GPU de Huawei Cloud. para implementar la versión GPU del servicio OCR.

Cómo construir la versión GPU del entorno PaddlePaddle en el servidor en la nube de Huawei, consulte el siguiente artículo: https://blog.csdn.net/loutengyuan/article/details/126527326

Instalar Paddle OCR

PaddleOCR es el servicio de reconocimiento de texto OCR de código abierto de Baidu basado en PaddlePaddle. Dirección de Github: https://github.com/PaddlePaddle/PaddleOCR/Install
, ingrese el siguiente comando, después de la instalación, puede experimentar el servicio de reconocimiento OCR en la línea de comando

pip install "paddleocr>=2.0." -i https://mirror.baidu.com/pypi/simple

Descargue un paquete de experiencia de imagen de prueba:

wget https://paddleocr.bj.bcebos.com/dygraph_v2.1/ppocr_img.zip #下载
unzip ppocr_img.zip #解压

Ingrese al directorio recién descomprimido y comience a experimentar el reconocimiento OCR

cd ppocr_img #进入刚才下载解压的图片目录

Realizar reconocimiento OCR

paddleocr --image_dir ./imgs/11.jpg --use_angle_cls true --use_gpu true

La ejecución puede reportar un error, aquí necesita instalar dos libs libX11 y libXext

yum install -y libX11 
yum install -y libXext

Este es el reconocimiento, use el servidor GPU para identificar el ultrarrápido
inserte la descripción de la imagen aquí

Implementar el servicio de API de reconocimiento OCR

Para la implementación, Paddle proporciona dos métodos, PaddleHub y Paddle Serving. Usar PaddleHub es el más conveniente y puede ejecutarlo directamente desde la línea de comando. Paddle Serving es más estable cuando se implementa y admite la compilación e implementación de C ++.
Hablemos del despliegue de python de PaddleHub y Paddle Serving (despliegue recomendado o Paddle Serving)

PaddleHub implementa API de reconocimiento OCR

Instalar PaddleHub

pip install --upgrade paddlehub -i https://mirror.baidu.com/pypi/simple

Inicie el servicio API

# 前台启动
hub serving start -m ch_pp-ocrv3 --use_gpu   #会自动下载OCR模型
# 后台启动
nohup hub serving start -m ch_pp-ocrv3 --use_gpu > log.log 2>&1 &

Esto inicia un servicio de reconocimiento OCR
inserte la descripción de la imagen aquí

El tamaño de memoria de GPU máximo predeterminado es 8000 M. Si necesita modificar el método que puede encontrar /root/.paddlehub/modules/ch_pp_ocrv3/module.py, _set_configcambie 8000 al valor que desee.

    def _set_config(self, pretrained_model_path):
        """
        predictor config path
        """
        model_file_path = pretrained_model_path + '.pdmodel'
        params_file_path = pretrained_model_path + '.pdiparams'

        config = paddle_infer.Config(model_file_path, params_file_path)
        try:
            _places = os.environ["CUDA_VISIBLE_DEVICES"]
            int(_places[0])
            use_gpu = True
        except:
            use_gpu = False

        if use_gpu:
        	# 原本最大显存是8000M,这里改成2000M。
            config.enable_use_gpu(2000, 0)
            # config.enable_use_gpu(8000, 0)
        else:
            config.disable_gpu()
            if self.enable_mkldnn:
                # cache 10 different shapes for mkldnn to avoid memory leak
                config.set_mkldnn_cache_capacity(10)
                config.enable_mkldnn()

        config.disable_glog_info()
        config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass")
        config.switch_use_feed_fetch_ops(False)

        predictor = paddle_infer.create_predictor(config)

        input_names = predictor.get_input_names()
        input_handle = predictor.get_input_handle(input_names[0])
        output_names = predictor.get_output_names()
        output_handles = []
        for output_name in output_names:
            output_handle = predictor.get_output_handle(output_name)
            output_handles.append(output_handle)

        return predictor, input_handle, output_handles

ver proceso

ps -ef|grep python

cerrar proceso

kill -9 19913

ver registro

tail -f 1000 log.log

Cómo verificar la ocupación del puerto

$: netstat -anp | grep 8888
tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      13404/python3       
tcp        0      1 172.17.0.10:34036       115.42.35.84:8888       SYN_SENT    14586/python3 

Matar a la fuerza el proceso: por pid

$: kill -9 13404
$: kill -9 14586
$: netstat -anp | grep 8888
$:
  • Solicitud de prueba de cartero

Al identificar, debe convertir la imagen a base64 y luego enviar los parámetros en la solicitud json

Dirección de solicitud: http://127.0.0.1:8866/predict/ch_pp-ocrv3
Método de solicitud: json
Parámetros de solicitud: {"imágenes": ["El contenido base64 de la imagen, no es necesario el logotipo base64 anterior"]}

inserte la descripción de la imagen aquí

  • Guión de prueba de Python
import requests
import json
import cv2
import base64

def cv2_to_base64(image):
    data = cv2.imencode('.jpg', image)[1]
    return base64.b64encode(data.tostring()).decode('utf8')

# 发送HTTP请求
data = {
    
    'images':[cv2_to_base64(cv2.imread("你的图片地址"))]}
headers = {
    
    "Content-type": "application/json"}
url = "http://127.0.0.1:8866/predict/ch_pp-ocrv3"
r = requests.post(url=url, headers=headers, data=json.dumps(data))

# 打印预测结果
print(r.json())

inserte la descripción de la imagen aquí

  • solicitud de prueba de rizo
curl --location --request POST 'http://127.0.0.1:8866/predict/ch_pp-ocrv3' \
--header 'Content-Type: application/json' \
--data-raw '{"images":["图片的base64内容,不需前面的base64标识"]}'

El resultado devuelve:

{
    
    "msg":[{
    
    "data":[{
    
    "confidence":0.9314630627632141,"text":"(paddle env][root@M-1-2-centos","text_box_position":[[6,10],[231,10],[231,23],[6,23]]},{
    
    "confidence":0.9092367887496948,"text":"ppocr imgl# hub serving start -m chpp-ocrv3 --use_gpu","text_box_position":[[227,10],[612,12],[612,25],[227,23]]},{
    
    "confidence":0.939938485622406,"text":"[2022-05-30 19:49:34 +0800]","text_box_position":[[5,25],[191,25],[191,38],[5,38]]},{
    
    "confidence":0.8236835598945618,"text":"[28320]","text_box_position":[[200,26],[246,26],[246,37],[200,37]]},{
    
    "confidence":0.6653339862823486,"text":"LINFO]","text_box_position":[[256,26],[295,26],[295,37],[256,37]]},{
    
    "confidence":0.842379093170166,"text":"starting gunicorn 2o.1.0","text_box_position":[[301,26],[474,26],[474,38],[301,38]]},{
    
    "confidence":0.939938485622406,"text":"[2022-05-30 19:49:34 +0800]","text_box_position":[[5,40],[191,40],[191,53],[5,53]]},{
    
    "confidence":0.8367705345153809,"text":"[28320]","text_box_position":[[200,41],[247,41],[247,52],[200,52]]},{
    
    "confidence":0.86468505859375,"text":"[INFO]","text_box_position":[[257,41],[297,41],[297,52],[257,52]]},{
    
    "confidence":0.9211856722831726,"text":"Listening at: http://0.0.0.0:8866 (28320)","text_box_position":[[302,40],[589,40],[589,53],[302,53]]},{
    
    "confidence":0.9346868395805359,"text":"[2022-05-3019:49:34+0800]","text_box_position":[[4,55],[191,54],[191,67],[4,68]]},{
    
    "confidence":0.9421297311782837,"text":"[28320]","text_box_position":[[199,55],[247,55],[247,68],[199,68]]},{
    
    "confidence":0.9394086003303528,"text":"[INFO]","text_box_position":[[256,55],[298,55],[298,68],[256,68]]},{
    
    "confidence":0.9321832656860352,"text":"Using worker: sync","text_box_position":[[302,56],[430,56],[430,68],[302,68]]},{
    
    "confidence":0.9334865808486938,"text":"[2022-05-30 19:49:34 +0800]","text_box_position":[[4,70],[191,70],[191,83],[4,83]]},{
    
    "confidence":0.8994974493980408,"text":"[INFO] ","text_box_position":[[256,70],[305,70],[305,84],[256,84]]},{
    
    "confidence":0.8855429887771606,"text":"[28324]","text_box_position":[[200,71],[246,71],[246,82],[200,82]]},{
    
    "confidence":0.9438435435295105,"text":"Booting worker with pid: 28324","text_box_position":[[300,70],[515,69],[515,83],[300,84]]}],"save_path":""}],"results":"","status":"000"}

De esta manera, se puede utilizar con normalidad.La velocidad de reconocimiento es de unos 100-300ms, que es muy rápida.
Tutorial de implementación oficial: https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/deploy/hubserving/readme.md

Despliegue el servicio de reconocimiento OCR a través de Paddle Serving

En comparación con la implementación de hubserving, PaddleServing tiene las siguientes ventajas:

  • Admite alta concurrencia y comunicación eficiente entre el cliente y el servidor
  • Admite capacidades de servicio de grado industrial, como gestión de modelos, carga en línea, pruebas A/B en línea, etc.
  • Admite múltiples lenguajes de programación para desarrollar clientes, como C ++, Python y Java

Primero prepare el entorno PaddleOCR, será muy lento extraer el código github aquí, puede descargarlo científicamente primero y luego cargarlo en el servidor

git clone https://github.com/PaddlePaddle/PaddleOCR --depth=1

en el directorio de trabajo

cd PaddleOCR/deploy/pdserving/

Instalar el entorno operativo de PaddleServing, los pasos son los siguientes

# 安装serving,用于启动服务
wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_server_gpu-0.8.3.post102-py3-none-any.whl
pip3 install paddle_serving_server_gpu-0.8.3.post102-py3-none-any.whl

# 安装client,用于向服务发送请求
wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_client-0.8.3-cp38-none-any.whl
pip3 install paddle_serving_client-0.8.3-cp38-none-any.whl

# 安装serving-app
wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_app-0.8.3-py3-none-any.whl
pip3 install paddle_serving_app-0.8.3-py3-none-any.whl
  • conversión de modelo

Al usar PaddleServing para la implementación del servicio, es necesario convertir el modelo de inferencia guardado en un modelo que sea fácil de implementar para el servicio.

Primero, descargue el modelo de inferencia de PP-OCR

# 下载并解压 OCR 文本检测模型
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar -O ch_PP-OCRv3_det_infer.tar && tar -xf ch_PP-OCRv3_det_infer.tar
# 下载并解压 OCR 文本识别模型
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar -O ch_PP-OCRv3_rec_infer.tar &&  tar -xf ch_PP-OCRv3_rec_infer.tar

A continuación, utilice paddle_serving_client instalado para convertir el modelo de inferencia descargado en un formato de modelo que sea fácil de implementar en el servidor.

# 转换检测模型
python3 -m paddle_serving_client.convert --dirname ./ch_PP-OCRv3_det_infer/ \
                                         --model_filename inference.pdmodel          \
                                         --params_filename inference.pdiparams       \
                                         --serving_server ./ppocr_det_v3_serving/ \
                                         --serving_client ./ppocr_det_v3_client/

# 转换识别模型
python3 -m paddle_serving_client.convert --dirname ./ch_PP-OCRv3_rec_infer/ \
                                         --model_filename inference.pdmodel          \
                                         --params_filename inference.pdiparams       \
                                         --serving_server ./ppocr_rec_v3_serving/  \
                                         --serving_client ./ppocr_rec_v3_client/

Una vez completada la conversión del modelo de detección, habrá carpetas adicionales de ppocr_det_v3_serving y ppocr_det_v3_client en la carpeta actual, con el siguiente formato:

|- ppocr_det_v3_serving/
  |- __model__  
  |- __params__
  |- serving_server_conf.prototxt  
  |- serving_server_conf.stream.prototxt

|- ppocr_det_v3_client
  |- serving_client_conf.prototxt  
  |- serving_client_conf.stream.prototxt
  • Despliegue de canalización de servicio de paletas
# 启动服务,运行日志保存在log.txt
nohup python3 -u web_service.py > log.log 2>&1 &

inserte la descripción de la imagen aquí
Si no hay ningún error en el registro de ejecución, el inicio es exitoso.
inserte la descripción de la imagen aquí
Luego, puede usar el código de cliente proporcionado por él para solicitar una prueba para
inserte la descripción de la imagen aquí
ver el progreso.

ps -ef|grep python

cerrar proceso

kill -9 19913

ver registro

tail -f 1000 log.log

Cómo verificar la ocupación del puerto

$: netstat -anp | grep 8888
tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      13404/python3       
tcp        0      1 172.17.0.10:34036       115.42.35.84:8888       SYN_SENT    14586/python3 

Matar a la fuerza el proceso: por pid

$: kill -9 13404
$: kill -9 14586
$: netstat -anp | grep 8888
$:
  • Prueba de solicitud HTTP

Dirección de solicitud: http://127.0.0.1:9998/ocr/prediction
Método de solicitud: json
Parámetros de solicitud: {“clave”: “imagen”, “valor”: “base64 de la imagen”}

  • prueba de solicitud de rizo
curl --location --request POST 'http://127.0.0.1:9998/ocr/prediction' \

--header 'Content-Type: application/json' \

--data-raw '{"key":"image","value":"图片的base64"}'

Formato de datos devueltos:

{
    
    
"err_no": 0,
"err_msg": "",
"key": [
    "result"
],
"value": [
    "[[('(padde env)[root@M-1-2-centoppocrimghub servingstart -m chpp-ocrv3--usegpu', 0.84638405), [[5.0, 10.0], [611.0, 12.0], [611.0, 24.0], [5.0, 22.0]]], [('[2022-05-3019:49:34+0800][28320】[INF0]Startingqunicorm20.1.', 0.81580645), [[5.0, 25.0], [472.0, 25.0], [472.0, 38.0], [5.0, 37.0]]], [('[2022-05-3019:49:34+0800][28320][INF0]Listeningat:http://0.0.0.0:8866(28320)', 0.84695405), [[5.0, 40.0], [589.0, 40.0], [589.0, 54.0], [5.0, 54.0]]], [('[2022-05-319:49:34+0800][28320】[INF0]Usingworker:sync', 0.7949861), [[5.0, 54.0], [430.0, 56.0], [430.0, 68.0], [5.0, 66.0]]], [('[2022-05-319:49:34+080】[28324】[INFO】Bootingworkerwith pid:28324', 0.85473406), [[4.0, 70.0], [515.0, 70.0], [515.0, 84.0], [4.0, 84.0]]]]"
],
"tensors": []
}

Esto está completo y se puede usar normalmente. Si proporciona llamadas en otros idiomas, puede consultar sus documentos oficiales.
Tutorial de implementación oficial: https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/deploy/pdserving/README_CN.md

epílogo

Implementar esto es relativamente simple, y la documentación oficial de Paddle es bastante completa, pero aún debe personalizar y entrenar algunos reconocimientos de texto especiales.

Supongo que te gusta

Origin blog.csdn.net/loutengyuan/article/details/126530740
Recomendado
Clasificación