【paddleOCR】从零开始搭建一个发票识别的restfulAPI服务

1,782 阅读8分钟

背景

  • 选择docker进行构建。因为资金有限, 使用cpu版的paddleOCR.
  • 包含2个模型: 检测模型--(定位文字位置), 识别模型(识别汉字)

坑一. ubuntu20.4换源

ARG DEBIAN_FRONTEND=noninteractive
USER root
RUN mv /etc/apt/sources.list /etc/apt/sources_backup.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal main restricted " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal universe " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-updates universe " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal multiverse " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-updates multiverse " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-security universe " >> /etc/apt/sources.list && \
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ focal-security multiverse " >> /etc/apt/sources.list && \
echo "deb http://archive.canonical.com/ubuntu focal partner " >> /etc/apt/sources.list
RUN apt-get update -y 
RUN apt-get install -y iputils-ping net-tools

坑二 libgl1-mesa-glx

apt install libgl1-mesa-glx

坑三 apt-get install libglib2.0-dev

在这里插入图片描述

完成Dockerfile构建

在这里插入图片描述

docker运行

docker run -itd -p8866:8866 --name bdocr bdocr

查看日志

docker logs -f bdocr 很好已经运行着flask后端服务了. 在这里插入图片描述

调试 -- 好吧,1核的服务器直接卡崩了.

results.data 就是 一个json数组, 包含识别文本, 置信度(0-1), 文本的位置, 接口换别的语言也行,支持多图片识别, 只要你机子性能好. POST http://127.0.0.1:8866/predict/ch_pp-ocrv3
DATA传json字符串----{"images":[ 图片的base64, 图片二的base64, ... ]}

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("Snap101.jpg")) ]}
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))
results = r.json()["results"]
print(results)

# 过滤打印预测结果
results = r.json()["results"]
keywords = ['开票日期','发票代码','发票号码','纳税人识别号','保单号','业务号码']
for ls in results:
    print('------')
    for i in ls['data']:
        for j in keywords:
            if j in i['text']:
                print(i['text'])

换机子 11800h (8核16线程) 限制单核最高3.5GHZ

很好, 识别一张增值税发票10秒钟左右(300k以下的jpg或者png), qps可能就个位数. 在这里插入图片描述

识别出的文本

  • 有的不在一行(比如金额和对应数字), 不好处理, 鬼知道怎么拼接. 字符串过短就去除换行?
  • 在一行的好办, 比如 ['开票日期','发票代码','发票号码','纳税人识别号','保单号','业务号码']. 直接正则提取就行.
[{'data': [{'confidence': 0.945626437664032, 'text': '发票代码:031001800111', 'text_box_position': [[922, 20], [1135, 24], [1135, 46], [921, 41]]}, {'confidence': 0.9517925381660461, 'text': '上海增值税电子普通发票', 'text_box_position': [[407, 50], [883, 50], [883, 95], [407, 95]]}, {'confidence': 0.9518486261367798, 'text': '发票号码:66284871', 'text_box_position': [[922, 59], [1097, 62], [1096, 83], [921, 80]]}, {'confidence': 0.9012559652328491, 'text': '开票日期:20191029日', 'text_box_position': [[921, 98], [1178, 98], [1178, 121], [921, 121]]}, {'confidence': 0.9574885964393616, 'text': '国家税务总局', 'text_box_position': [[609, 111], [697, 111], [697, 126], [609, 126]]}, {'confidence': 0.9672134518623352, 'text': '上海市税务局', 'text_box_position': [[613, 140], [687, 137], [688, 155], [613, 159]]}, {'confidence': 0.9172490239143372, 'text': '校验码:00210941513014933847', 'text_box_position': [[919, 135], [1215, 141], [1215, 164], [919, 158]]}, {'confidence': 
0.8558400273323059, 'text': '499099472580', 'text_box_position': [[16, 148], [135, 148], [135, 165], [16, 165]]}, {'confidence': 0.9874964952468872, 'text': '名', 'text_box_position': [[64, 179], [80, 179], [80, 205], [64, 205]]}, {'confidence': 0.9312224984169006, 'text': '大学', 'text_box_position': [[235, 183], [282, 183], [282, 207], [235, 207]]}, {'confidence': 0.9144629240036011, 'text': '称:', 'text_box_position': [[163, 184], [204, 184], [204, 205], [163, 205]]}, {'confidence': 0.7343701720237732, 'text': '8?>8*8*897<09+7/*<7*9<8*7-80', 'text_box_position': [[801, 179], [1241, 179], [1241, 197], [801, 197]]}, {'confidence': 0.9714970588684082, 'text': '密', 'text_box_position': [[738, 189], [757, 189], [757, 211], [738, 211]]}, {'confidence': 0.9480007290840149, 'text': '购', 'text_box_position': [[24, 200], [43, 200], [43, 220], [24, 220]]}, {'confidence': 0.9787009954452515, 'text': '12100000', 'text_box_position': [[226, 216], [354, 216], [354, 239], [226, 239]]}, {'confidence': 0.9669632315635681, 'text': '纳税人识别号:', 'text_box_position': [[64, 220], [194, 220], [194, 239], [64, 239]]}, {'confidence': 0.9084798693656921, 'text': '1299256>1>65605/0238<>95+42*', 'text_box_position': [[800, 211], [1243, 209], [1243, 232], [800, 234]]}, {'confidence': 0.9930230379104614, 'text': '买', 
'text_box_position': [[23, 231], [45, 231], [45, 256], [23, 256]]}, {'confidence': 0.9083058834075928, 'text': '码', 'text_box_position': [[738, 232], [759, 232], [759, 252], [738, 252]]}, {'confidence': 0.9212196469306946, 'text': '地址、电话:上海市四平路1239号18817812130', 'text_box_position': [[62, 251], [501, 256], [501, 278], [61, 272]]}, {'confidence': 0.8564757108688354, 'text': '553>516/-41>8+07<6<-/>355/+1', 'text_box_position': [[801, 247], [1239, 247], [1239, 266], [801, 266]]}, {'confidence': 0.9994157552719116, 'text': '方', 'text_box_position': [[22, 270], [41, 268], [43, 287], [25, 289]]}, {'confidence': 0.9353272318840027, 'text': '开 
户行及账号:中国农业银行股份有限公司上海翔股支行03326700812000848', 'text_box_position': [[64, 287], [730, 287], [730, 306], [64, 306]]}, {'confidence': 0.8597356677055359, 'text': '566*3133-401/492197*885<->36', 'text_box_position': [[801, 282], [1242, 282], [1242, 301], [801, 301]]}, {'confidence': 0.9962540864944458, 'text': 
'单位', 'text_box_position': [[467, 318], [507, 318], [507, 338], [467, 338]]}, {'confidence': 0.9997873306274414, 'text': '数量', 'text_box_position': [[565, 318], 
[628, 318], [628, 342], [565, 342]]}, {'confidence': 0.9592089653015137, 'text': '规格型号', 'text_box_position': [[357, 319], [435, 319], [435, 338], [357, 338]]}, 
{'confidence': 0.99732506275177, 'text': '单', 'text_box_position': [[721, 318], [749, 318], [749, 340], [721, 340]]}, {'confidence': 0.9983073472976685, 'text': '价
', 'text_box_position': [[759, 319], [781, 319], [781, 338], [759, 338]]}, {'confidence': 0.9987186789512634, 'text': '金额', 'text_box_position': [[896, 319], [959, 319], [959, 340], [896, 340]]}, {'confidence': 0.9876129627227783, 'text': '货物或应税劳务、服务名称', 'text_box_position': [[63, 321], [295, 321], [295, 338], [63, 338]]}, {'confidence': 0.9152608513832092, 'text': '税率', 'text_box_position': [[1028, 319], [1071, 319], [1071, 338], [1028, 338]]}, {'confidence': 0.9998440742492676, 'text': '税额', 'text_box_position': [[1138, 321], [1201, 321], [1201, 340], [1138, 340]]}, {'confidence': 0.9471420049667358, 'text': '*保险服务*短期团体意外 
伤害保险', 'text_box_position': [[15, 338], [310, 338], [310, 357], [15, 357]]}, {'confidence': 0.9992747902870178, 'text': '份', 'text_box_position': [[473, 337], [499, 337], [499, 361], [473, 361]]}, {'confidence': 0.9987457394599915, 'text': '91.42', 'text_box_position': [[776, 338], [829, 338], [829, 358], [776, 358]]}, {'confidence': 0.9015056490898132, 'text': '91.42', 'text_box_position': [[972, 338], [1028, 338], [1028, 358], [972, 358]]}, {'confidence': 0.9983651041984558, 'text': 
'6%', 'text_box_position': [[1031, 338], [1064, 338], [1064, 358], [1031, 358]]}, {'confidence': 0.9950968027114868, 'text': '**', 'text_box_position': [[354, 340], 
[377, 340], [377, 356], [354, 356]]}, {'confidence': 0.6403006315231323, 'text': '5. 48', 'text_box_position': [[1235, 338], [1278, 338], [1278, 358], [1235, 358]]}, {'confidence': 0.9979796409606934, 'text': '91.42', 'text_box_position': [[952, 558], [1023, 558], [1023, 581], [952, 581]]}, {'confidence': 0.9991210103034973, 'text': '计', 'text_box_position': [[204, 562], [228, 562], [228, 585], [204, 585]]}, {'confidence': 0.9806618690490723, 'text': '合', 'text_box_position': [[97, 564], 
[118, 564], [118, 584], [97, 584]]}, {'confidence': 0.7473207712173462, 'text': '¥5.48', 'text_box_position': [[1218, 560], [1278, 560], [1278, 580], [1218, 580]]}, {'confidence': 0.9677237272262573, 'text': '价税合计(大写)', 'text_box_position': [[97, 605], [247, 605], [247, 628], [97, 628]]}, {'confidence': 0.9092860817909241, 'text': '?玖拾陆元玖角', 'text_box_position': [[357, 603], [507, 603], [507, 625], [357, 625]]}, {'confidence': 0.9263322949409485, 'text': '(小写)¥96.90', 'text_box_position': [[952, 605], [1091, 605], [1091, 624], [952, 624]]}, {'confidence': 0.9995607733726501, 'text': '名', 'text_box_position': [[63, 640], [80, 640], 
[80, 664], [63, 664]]}, {'confidence': 0.9539690613746643, 'text': '称:中国平安财产保险股份有限公司上海分公司', 'text_box_position': [[159, 639], [582, 643], [582, 
670], [159, 666]]}, {'confidence': 0.9423936605453491, 'text': '保单号10220031900540705549', 'text_box_position': [[772, 643], [1030, 643], [1030, 662], [772, 662]]}, {'confidence': 0.9579678177833557, 'text': '销', 'text_box_position': [[28, 663], [47, 663], [47, 683], [28, 683]]}, {'confidence': 0.9853338599205017, 'text': '纳
税人识别号:', 'text_box_position': [[65, 675], [195, 675], [195, 694], [65, 694]]}, {'confidence': 0.8110359907150269, 'text': '913100001322279017', 'text_box_position': [[228, 676], [513, 676], [513, 695], [228, 695]]}, {'confidence': 0.7695711255073547, 'text': '备', 'text_box_position': [[742, 667], [753, 667], [753, 680], [742, 680]]}, {'confidence': 0.9996627569198608, 'text': '售', 'text_box_position': [[28, 693], [44, 693], [44, 717], [28, 717]]}, {'confidence': 0.9779407382011414, 
'text': '地址、电话:上海市常熟路8号4008866338', 'text_box_position': [[62, 706], [463, 709], [463, 732], [61, 729]]}, {'confidence': 0.9990666508674622, 'text': '方
', 'text_box_position': [[27, 726], [45, 726], [45, 748], [27, 748]]}, {'confidence': 0.999420166015625, 'text': '注', 'text_box_position': [[738, 731], [757, 731], 
[757, 749], [738, 749]]}, {'confidence': 0.935571014881134, 'text': '开户行及账号:平安银行股份有限公司上海北京西路支行11014491518001', 'text_box_position': [[64, 742], [700, 742], [700, 761], [64, 761]]}, {'confidence': 0.8658991456031799, 'text': '913100001322279017', 'text_box_position': [[948, 758], [1171, 761], [1171, 789], [948, 786]]}, {'confidence': 0.9470199942588806, 'text': '收款人:', 'text_box_position': [[33, 782], [105, 782], [105, 805], [33, 805]]}, {'confidence': 0.9908418655395508, 'text': '复核:', 'text_box_position': [[389, 784], [435, 784], [435, 804], [389, 804]]}, {'confidence': 0.9768704175949097, 'text': '开票人:平安产险', 'text_box_position': [[655, 782], [815, 787], [814, 810], [654, 805]]}, {'confidence': 0.9629880785942078, 'text': '(1)', 'text_box_position': [[1040, 821], [1086, 821], [1086, 842], [1040, 842]]}], 'save_path': ''}]