• PaddleOCR 安装与实践(CPU版)


    0、glibc升级至2.23以及python升级至3.7

    https://blog.csdn.net/qq_20989105/article/details/90712139   # glibc 2.23升级
    https://www.cnblogs.com/goldsunshine/p/12938654.html # python3.7 升级

    1、安装(请按照官网的安装,本人使用docker方式,也是推荐方式,至于克隆源码,我用的是gitee中的,汗......github太慢了.....)

    https://hub.fastgit.org/PaddlePaddle/PaddleOCR/blob/release/2.1/doc/doc_ch/installation.md

    2、测试是否安装成功,标红说明安装成功啦!

    λ ywj-computer /home/PaddleOCR/tools {release/2.0} python3
    Python 3.7.0 (default, Apr 13 2021, 06:08:34) 
    [GCC 8.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import paddle
    grep: warning: GREP_OPTIONS is deprecated; please use an alias or script
    >>> 

    3、测试官网例子玩玩,(标红的地方可以自己上传自己的图片,更换文件名即可)

    python3 tools/infer/predict_system.py --image_dir="./doc/imgs/11.jpg" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/"  --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True
    
    
    python3 tools/infer/predict_system.py --image_dir="./doc/imgs/" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/"  --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True
    
    
    python3 tools/infer/predict_system.py --image_dir="./doc/imgs/3.jpg" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/"  --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True --use_gpu=False
    [2021/04/13 07:12:57] root INFO: dt_boxes num : 17, elapse : 0.9136314392089844
    [2021/04/13 07:12:57] root INFO: cls num  : 17, elapse : 0.08672833442687988
    [2021/04/13 07:12:58] root INFO: rec_res num  : 17, elapse : 0.17425131797790527
    [2021/04/13 07:12:58] root INFO: Predict time of ./doc/imgs/4.jpg: 1.227s
    [2021/04/13 07:12:58] root INFO: 性出住, 0.932
    [2021/04/13 07:12:58] root INFO: 公民身份号码, 0.999
    [2021/04/13 07:12:58] root INFO: 名, 1.000
    [2021/04/13 07:12:58] root INFO: 男, 0.812
    [2021/04/13 07:12:58] root INFO: 1991年7月7日, 0.998
    [2021/04/13 07:12:58] root INFO: 杨深度, 0.990
    [2021/04/13 07:12:58] root INFO: 村XXX, 0.999
    [2021/04/13 07:12:58] root INFO: 湖南省XXXXXX, 0.991
    [2021/04/13 07:12:58] root INFO: 民族汉, 0.924
    [2021/04/13 07:12:58] root INFO: 43052XXXXXXXXXXX, 0.995
    [2021/04/13 07:12:58] root INFO: The visualized image saved in ./inference_results/4.jpg

    识别十分准确,只是要获取自己想要的格式以及信息提取还要优化很多

    ======================安装完成,部署测试==============================

    1、部署有两种方式,我这边使用的是hub方式

    部署安装文档说明:https://hub.fastgit.org/PaddlePaddle/PaddleOCR/tree/release/2.1/deploy/hubserving

    2、返回需要的text字段

    1、cd /home/PaddleOCR/deploy/hubserving/ocr_system
    
    2、修改module.py文件:
        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.int).tolist()
                    })
                all_results.append(rec_res_final)
    3、可以看上面的注释部分是我们不需要的,我们只需要text部分

    3、参数调节params.py(这里我没有做调整)

    4、使用flask部署web框架

    1、安装flask 
        pip3 install flask 
        pip3 install flask-cors
    2、mv test_hubserving.py test_myocr.py,整体代码如下:
    # Copyright (c) 2020 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.
    import os
    import sys
    __dir__ = os.path.dirname(os.path.abspath(__file__))
    sys.path.append(__dir__)
    sys.path.append(os.path.abspath(os.path.join(__dir__, '..')))
    
    from ppocr.utils.logging import get_logger
    logger = get_logger()
    
    import cv2
    import numpy as np
    import time
    from PIL import Image
    from ppocr.utils.utility import get_image_file_list
    from tools.infer.utility import draw_ocr, draw_boxes
    
    import requests
    import json
    import base64
    
    from flask import Flask,request
    from flask_cors import CORS
    
    
    import requests
    app = Flask(__name__)
    CORS(app)  # 解决跨域问题
    
    def cv2_to_base64(image):
        return base64.b64encode(image).decode('utf8')
    
    
    def draw_server_result(image_file, res):
        img = cv2.imread(image_file)
        image = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        if len(res) == 0:
            return np.array(image)
        keys = res[0].keys()
        if 'text_region' not in keys:  # for ocr_rec, draw function is invalid 
            logger.info("draw function is invalid for ocr_rec!")
            return None
        elif 'text' not in keys:  # for ocr_det
            logger.info("draw text boxes only!")
            boxes = []
            for dno in range(len(res)):
                boxes.append(res[dno]['text_region'])
            boxes = np.array(boxes)
            draw_img = draw_boxes(image, boxes)
            return draw_img
        else:  # for ocr_system
            logger.info("draw boxes and texts!")
            boxes = []
            texts = []
            scores = []
            for dno in range(len(res)):
                boxes.append(res[dno]['text_region'])
                texts.append(res[dno]['text'])
                scores.append(res[dno]['confidence'])
            boxes = np.array(boxes)
            scores = np.array(scores)
            draw_img = draw_ocr(
                image, boxes, texts, scores, draw_txt=True, drop_score=0.5)
            return draw_img
    
    @app.route("/test")
    def test():
        return 'Hello World!'
    
    @app.route("/myocr", methods=["POST"] )
    def myocr():
        # 输入参数
        image_file = request.files['file']
        basepath = os.path.dirname(__file__)
    
        logger.info("{} basepath".format(basepath))
    
        savepath = os.path.join(basepath, image_file.filename)
        image_file.save(savepath)
        img = open(savepath, 'rb').read()
        if img is None:
            logger.info("error in loading image:{}".format(image_file))
    
        # 转为 base64
        data = {'images': [cv2_to_base64(img)]}
        # 发送请求
        url = "http://127.0.0.1:8866/predict/ocr_system"
        headers = {"Content-type": "application/json"}
        r = requests.post(url=url, headers=headers, data=json.dumps(data))
    
        # 返回结果
        res = r.json()["results"][0]
        logger.info(res)
        return  json.dumps(res)
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000)

      ####只提取身份证号以及包含带X的####

    # Copyright (c) 2020 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.
    import os
    import sys
    
    __dir__ = os.path.dirname(os.path.abspath(__file__))
    sys.path.append(__dir__)
    sys.path.append(os.path.abspath(os.path.join(__dir__, '..')))
    
    from ppocr.utils.logging import get_logger
    
    logger = get_logger()
    
    import cv2
    import numpy as np
    import time
    from PIL import Image
    from ppocr.utils.utility import get_image_file_list
    from tools.infer.utility import draw_ocr, draw_boxes
    
    import requests
    import json
    import base64
    
    from flask import Flask, request
    from flask_cors import CORS
    import re
    
    import requests
    
    app = Flask(__name__)
    CORS(app)  # 解决跨域问题
    sys.setrecursionlimit(10000)  # 解决循环调用限制
    
    
    def cv2_to_base64(image):
        return base64.b64encode(image).decode('utf8')
    
    
    def draw_server_result(image_file, res):
        img = cv2.imread(image_file)
        image = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        if len(res) == 0:
            return np.array(image)
        keys = res[0].keys()
        if 'text_region' not in keys:  # for ocr_rec, draw function is invalid
            logger.info("draw function is invalid for ocr_rec!")
            return None
        elif 'text' not in keys:  # for ocr_det
            logger.info("draw text boxes only!")
            boxes = []
            for dno in range(len(res)):
                boxes.append(res[dno]['text_region'])
            boxes = np.array(boxes)
            draw_img = draw_boxes(image, boxes)
            return draw_img
        else:  # for ocr_system
            logger.info("draw boxes and texts!")
            boxes = []
            texts = []
            scores = []
            for dno in range(len(res)):
                boxes.append(res[dno]['text_region'])
                texts.append(res[dno]['text'])
                scores.append(res[dno]['confidence'])
            boxes = np.array(boxes)
            scores = np.array(scores)
            draw_img = draw_ocr(
                image, boxes, texts, scores, draw_txt=True, drop_score=0.5)
            return draw_img
    
    
    @app.route("/ocr", methods=['POST'])
    def ocr_test():
        file = request.files['file']
        image_path = file
        url = "http://127.0.0.1:8866/predict/ocr_system"
        image_file_list = get_image_file_list(image_path)
        is_visualize = False
        headers = {"Content-type": "application/json"}
        cnt = 0
        total_time = 0
        for image_file in image_file_list:
            img = open(image_file, 'rb').read()
            if img is None:
                logger.info("error in loading image:{}".format(image_file))
                continue
    
            # 发送HTTP请求
            starttime = time.time()
            data = {'images': [cv2_to_base64(img)]}
            r = requests.post(url=url, headers=headers, data=json.dumps(data))
            elapse = time.time() - starttime
            total_time += elapse
            logger.info("Predict time of %s: %.3fs" % (image_file, elapse))
            res = r.json()["results"][0]
            logger.info(res)
    
            if is_visualize:
                draw_img = draw_server_result(image_file, res)
                if draw_img is not None:
                    draw_img_save = "./server_results/"
                    if not os.path.exists(draw_img_save):
                        os.makedirs(draw_img_save)
                    cv2.imwrite(
                        os.path.join(draw_img_save, os.path.basename(image_file)),
                        draw_img[:, :, ::-1])
                    logger.info("The visualized image saved in {}".format(
                        os.path.join(draw_img_save, os.path.basename(image_file))))
            cnt += 1
            if cnt % 100 == 0:
                logger.info("{} processed".format(cnt))
        logger.info("avg time cost: {}".format(float(total_time) / cnt))
    
    
    @app.route("/test")
    def test():
        return 'Hello World!'
    
    
    @app.route("/recImg", methods=["POST"])
    def recImg():
        # 输入参数
        image_file = request.files['file']
        basepath = os.path.dirname(__file__)
    
        logger.info("{} basepath".format(basepath))
    
        savepath = os.path.join(basepath, image_file.filename)
        image_file.save(savepath)
        img = open(savepath, 'rb').read()
        if img is None:
            logger.info("error in loading image:{}".format(image_file))
    
        # 转为 base64
        data = {'images': [cv2_to_base64(img)]}
        # 发送请求
        url = "http://127.0.0.1:8866/predict/ocr_system"
        headers = {"Content-type": "application/json"}
        r = requests.post(url=url, headers=headers, data=json.dumps(data))
    
        # 返回结果
        res = r.json()["results"][0]
        logger.info(res)
        # 删除保存的img
        os.remove(savepath)
        # 提取身份证号码
        idCardJson = json.dumps(res, ensure_ascii=False)
        return idCardJson
    
    
    @app.route("/", methods=["POST"])
    def myocr():
        # 输入参数
        image_file = request.files['file']
        basepath = os.path.dirname(__file__)
    
        logger.info("{} basepath".format(basepath))
    
        savepath = os.path.join(basepath, image_file.filename)
        image_file.save(savepath)
        img = open(savepath, 'rb').read()
        if img is None:
            logger.info("error in loading image:{}".format(image_file))
    
        # 转为 base64
        data = {'images': [cv2_to_base64(img)]}
        # 发送请求
        url = "http://127.0.0.1:8866/predict/ocr_system"
        headers = {"Content-type": "application/json"}
        r = requests.post(url=url, headers=headers, data=json.dumps(data))
    
        # 返回结果
        res = r.json()["results"][0]
        logger.info(res)
    
        # 删除保存的img
        os.remove(savepath)
        # 提取身份证号码
        idCardJson = getIDCard(json.dumps(res, ensure_ascii=False))
        return idCardJson
    
    
    def getIDCard(text):
        #    logger.info("getIDCard接受的结果 is %s" % (text))
        #    IDs = re.findall(r"d{18}|d{17}[X|x|×]", text)
        #    logger.info("IDs is %s: %s" % (type(IDs), IDs))
        #    if (len(IDs) != 1):
        #        return "Extract IdCard Error"
        #    idDict = {}
        #    idDict['idCard'] = handleIdCard(IDs[0])
        #    idCardJson = json.dumps(idDict, ensure_ascii=False)
        #    return idCardJson
    
        # 对带X的用户进行处理
        logger.info("getIDCard接受的结果 is %s" % (text))
        # 国内用户
        chIds = re.findall(r"d{18}|d{17}[X|x|×]", text)
        # 港澳用户
        hkIDs = re.findall(r"[H|M]d{8}", text)
        logger.info("chIds is %s: %s" % (type(chIds), chIds))
        logger.info("hkIDs is %s: %s" % (type(hkIDs), hkIDs))
        # len(chIds) != 1 表示只有一个数组
        idDict = {}
        if len(chIds) == 1:
            if len(chIds[0]) == 18:
                idDict['data'] = handleIdCard(chIds[0])
                idDict['code'] = "200"
                return json.dumps(idDict, ensure_ascii=False)
    
        if len(hkIDs) == 1:
            if len(hkIDs[0]) == 9 and (hkIDs[0].startswith('H') or hkIDs[0].startswith('M')):
                idDict['data'] = hkIDs[0]
                idDict['code'] = "200"
                return json.dumps(idDict, ensure_ascii=False)
    
        idDict['code'] = "500"
        idDict['data'] = "Extract IdCard Error"
        return json.dumps(idDict, ensure_ascii=False)
    
    
    def handleIdCard(text):
        if len(text) == 18:
            logger.info("这是啥====== %s" % (text[len(text) - 1]))
    
            if is_number(text[len(text) - 1]):
                return text
            else:
                return text[0:-1] + "X"
    
    
    def is_number(s):
        try:
            float(s)
            return True
        except ValueError:
            pass
    
        try:
            import unicodedata
            unicodedata.numeric(s)
            return True
        except (TypeError, ValueError):
            pass
        return False
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000)
    View Code

    5、运行与测试

    1、启动ocr_system:hub serving start -m ocr_system &
    2、启动web服务: python3 test_myocr.py &
       grep: warning: GREP_OPTIONS is deprecated; please use an alias or script

        * Serving Flask app "yangwj" (lazy loading)
        * Environment: production
        WARNING: This is a development server. Do not use it in a production deployment.
        Use a production WSGI server instead.
        * Debug mode: off
        * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

    3、postman 测试与结果

    这样一个ocr算法程序就部署好了.............

    6、转为uwsgi部署

    a) 安装 uwsgi

    1、卸载pip uninstall uwsgi
    
    2、安装pip install uwsgi --no-cache-dir

    参考博客:https://blog.csdn.net/qq_43590972/article/details/88622750

    b) 在tools目录下增加myocr.ini

    [uwsgi]
    #socket配和nginx使用
    #socket = 0.0.0.0:8080
    #Http请求
    http = 0.0.0.0:8080
    #项目地址
    chdir = /home/PaddleOCR/tools
    #flask 请使用app
    callable = app
    wsgi-file = yangwj.py
    processes = 2
    threads = 4
    #最大支持5M
    buffer-size = 5242880
    master = true
    #支持post请求
    post-buffering = 1  
    pidfile = uwsgi.pid
    #日志文件
    daemonize = ./logs/uwsgi.log

    c) 清除uwsgi进程和启动uwsgi进程

    pkill -9 uwsgi
    
    uwsgi --ini   xxx/uwsgi.ini  #请尽量使用绝对路径

    d) 访问地址 http://localhost:8080

    ==============机器重启后,进入容器步骤==================

    1、开启python3的虚拟环境

    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
    source ~/.bashrc

    2、workon paddleocr

    3、docker restart containerId

    4、进入容器

    sudo docker container exec -it ppocr /bin/bash
  • 相关阅读:
    Redhat Lighttpd安装配置
    PHP正则表达式学习参考的文章
    50点提高PHP编程效率 引入缓存提升性能
    位运算符C语言
    Redhat Mongodb学习笔记
    Redhat Cacti安装配置
    HTTP 状态代码表示什么意思?
    map容器对象插入数据的4种方式
    socket网络间通信初识
    仿美团项目-第一部分
  • 原文地址:https://www.cnblogs.com/ywjfx/p/14656792.html
Copyright © 2020-2023  润新知