1.欢迎点赞、关注、批评、指正,互三走起来,小手动起来!
2.了解、学习OCR相关技术知识领域,结合日常的场景进行测试、总结。如本文总结的flask+paddleocr+bootstrap搭建OCR文本推理WEB服务应用示例场景。
文章目录
- 1.代码结构
- 2.效果演示
- 3.接口返回
- 4.代码详情
- 4.1 `HTML`代码详情
- 4.2`Python`代码详情
- 5.PaddleOCR模型推理参数解释
- 6.后续展望
1.代码结构
- 如下图所示:
2.效果演示
- 详情如下:
3.接口返回
- 接口测试效果图
- 返回结果详情部分示例
{
"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.后续展望
- 持续改进优化该部分代码,并完善文档。欢迎交流。。。
- PaddleOCR模型推理参数解释