1.欢迎点赞、关注、批评、指正,互三走起来,小手动起来!
2.了解、学习OCR相关技术知识领域,结合日常的场景进行测试、总结。如本文总结的flask+paddleocr+bootstrap搭建OCR文本推理WEB服务应用示例场景。


文章目录
  • 1.代码结构
  • 2.效果演示
  • 3.接口返回
  • 4.代码详情
  • 4.1 `HTML`代码详情
  • 4.2`Python`代码详情
  • 5.PaddleOCR模型推理参数解释
  • 6.后续展望


1.代码结构

  • 如下图所示:

2.效果演示

  • 详情如下:

3.接口返回

  • 接口测试效果图
  • 【ocr识别003】flask+paddleocr+bootstrap搭建OCR文本推理WEB服务_ocr

  • 返回结果详情部分示例
{
    "error_code": "000000",
    "error_msg": "识别成功",
    "filename": "cstp2.png",
    "recognize_time": "5890",
    "result": [
        {
            "points": [
                [
                    14.0,
                    11.0
                ],
                [
                    108.0,
                    11.0
                ],
                [
                    108.0,
                    40.0
                ],
                [
                    14.0,
                    40.0
                ]
            ],
            "score": 0.979973316192627,
            "text": "性别:男"
        },
        {
            "points": [
                [
                    289.0,
                    11.0
                ],
                [
                    400.0,
                    9.0
                ],
                [
                    401.0,
                    37.0
                ],
                [
                    290.0,
                    39.0
                ]
            ],
            "score": 0.8993546962738037,
            "text": "住院号:"
        },
        {
            "points": [
                [
                    677.0,
                    2.0
                ],
                [
                    713.0,
                    12.0
                ],
                [
                    707.0,
                    31.0
                ],
                [
                    672.0,
                    21.0
                ]
            ],
            "score": 0.6370271444320679,
            "text": "贝别:"
        }
    ]
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.

4.代码详情

4.1 HTML代码详情
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
    <title>OCR文字检测识别试运行系统</title>
    <!--静态加载 样式-->
    <link rel="stylesheet" href={{ url_for('static',filename='bootstrap-3.4.1/css/bootstrap.min.css') }}></link>
    <link rel="stylesheet" href={{ url_for('static',filename='css/upload.css') }}></link>
    <link rel="stylesheet" href={{ url_for('static',filename='css/36buttons.css') }}></link>
</head>
<body>
<div class="header">
    <div class="title">【OCR】PP-OCRv3 文字检测识别试运行系统v0.3.0</div>
</div>

<ul class="menu">
    <li><a href="/upload/">通用文本检测识别处理</a></li>
</ul>

<div class="content">
    <!--上传图片文件-->
    <div id="upload_file">
        <form id="fileForm" action="/upload/" method="POST" enctype="multipart/form-data">
            <div class="form-group">
                <input type="file" class="form-control" id="_upload_file" name="upload_file">
<!--                <label class="sr-only" for="upload_file">上传图片</label>-->
                </br>
                <button id="resetButton" name="resetButton" type="reset" class="button green">重置推理结果</button>
            </div>
        </form>
    </div>
</div>
</div>

<div id="show" style="display: none;">
    <!--显示上传的图片-->
    <div class="col-md-6" style="border: 2px solid #ddd;">
        </br>
        <span class="label label-info" style="font-size: 24px;"><<<<<< 原始图片展示 >>>>>> </br></span>
        <!--静态加载 图片, url_for() 动态生成路径 -->
        </br>
        <img id="src_pic_show" src="" alt="Image preview area..." title="preview-img" class="img-responsive">
    </div>
    <div class="col-md-6" style="border: 2px solid #ddd;">
        <!--显示识别结果JSON报文列表-->
        </br>
        <span class="label label-info" style="font-size: 24px;"><<<<<< 推理结果详情 >>>>>> </br></span>
        </br>
        <!-- 结果显示区 -->
        <div id="result_show" style="font-size: 28px;">客官,您提交的任务加急推理中......</div>
    </div>
</div>
</body>
</html>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="http://malsup.github.io/jquery.form.js"></script>

<script type="text/javascript">
    var fileInput = document.querySelector('input[type=file]');
    var previewImg = document.querySelector('img');

    {#上传图片事件#}
    fileInput.addEventListener('change', function () {
        var file = this.files;
        var reader = new FileReader();

        //显示预览界面
        $("#show").css("display", "block");

        // 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片
        reader.addEventListener("load", function () {
            previewImg.src = reader.result;
        }, false);

        // 调用reader.readAsDataURL()方法,把图片转成base64
        reader.readAsDataURL(file);

        //初始化输出结果信息
        $("#result_show").html("</br>客官,您提交的任务加急推理中......");

        {#上传图片识别表单事件,并显示识别结果信息#}
        {# ajaxSubmit 请求异步响应#}

        $("#fileForm").ajaxSubmit(function (data) {
            var inner = '<table border="1"> <thead> <tr> <th>序号</th> <th>文本目标</th> <th>置信度分数</th> </tr> </thead> <tbody>';
            //循环输出返回结果,响应识别结果为每行列表
            var inc = 1;
            for (var i in data['result']) {
                var text = data['result'][i]['text'];
                var score = data['result'][i]['score'];
                inner += "<tr><td>" + inc + "</td>" + "<td>" + text + "</td>" + "<td>" + score + "</td></tr>";
                inc += 1;
            }
            inner += '</tbody></table>'
            //清空输出结果信息
            $("#result_show").html("");

            //添加识别结果信息
            $("#show").append( inner );
        });
    }, false);

    document.getElementById('resetButton').addEventListener('click', function() {
        document.getElementById('src_pic_show').src = '';
        $('#result_show').empty();
    });
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
4.2Python代码详情
  • 源代码
import json
import os
import time
import numpy as np
import pandas as pd
from pyautogui import *
from paddleocr import PaddleOCR
from PIL import Image, ImageDraw
from flask import Flask, render_template, request, jsonify
# 应用名称,当前py名称,视图函数
app = Flask(__name__)
# 相对路径
BASE_DIR = os.path.dirname(os.path.basename(__name__))

# 上传文件路径
UPLOAD_DIR = os.path.join(os.path.join(BASE_DIR, 'static'), 'upload')

def ocr_img2text( image ):
    result_dict = {'result': []}
    paddleocr = PaddleOCR(det_model_dir='./inference/ch_PP-OCRv3_det_infer/',
                    rec_model_dir='./inference/ch_PP-OCRv3_rec_infer/',
                    cls_model_dir='./inference/ch_ppocr_mobile_v2.0_cls_infer/',
                    use_angle_cls=True, lang="ch", use_gpu=True)
    if image == "":
        image = screenshot()  # 使用pyautogui进行截图操作
        image = np.array(image)
    else:
        # 不为空就打开
        image = Image.open(image).convert('RGB')
        image = np.array(image)  # 经提醒,需要添加array

    print( image, type(image) )
    # 识别图片文件
    result0 = paddleocr.ocr( image, cls=True )
    result = result0[0]

    # for line in result0:
    #     for word in line:
    #         print( word )

    for index in range(len(result)):
        line = result[index]
        p_dict = {}
        points = line[1]
        text = line[1][0]
        score = line[1][1]
        p_dict['points'] = points
        p_dict['text'] = text
        p_dict['score'] = score
        result_dict['result'].append( p_dict )
    return result_dict

@app.route('/')
def upload_file():
    return render_template('upload.html')

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        # 每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。
        filedata = request.files['upload_file']
        upload_filename = filedata.filename
        print(upload_filename)
        # 保存文件到指定路径
        # 目标文件的名称可以是硬编码的,也可以从 request.files[file] 对象的 filename 属性中获取。
        # 但是,建议使用 secure_filename() 函数获取它的安全版本
        if not os.path.exists(UPLOAD_DIR):
            os.makedirs(UPLOAD_DIR)
        img_path = os.path.join(UPLOAD_DIR, upload_filename)
        filedata.save(img_path)
        start = time.time()
        # 打开图片
        img1 = Image.open(img_path)
        # 识别图片
        result_dict = ocr_img2text(img_path)

        # 识别时间
        end = time.time()
        recognize_time = int((end - start) * 1000)

        result_dict["filename"] = upload_filename
        result_dict["recognize_time"] = str(recognize_time)
        result_dict["error_code"] = "000000"
        result_dict["error_msg"] = "识别成功"
        return jsonify(result_dict)
    else:
        return render_template('upload.html')
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.

5.PaddleOCR模型推理参数解释

  • 参数详情

6.后续展望