PaddleOCR学习笔记3-通用识别服务
今天优化了下之前的初步识别服务的python代码和html代码。
采用flask + paddleocr+ bootstrap快速搭建OCR识别服务。
代码结构如下:

模板页面代码文件如下:
upload.html :
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>PandaCodeOCR</title>
<!--静态加载 样式-->
<link rel="stylesheet" href={{ url_for('static',filename='bootstrap3/css/bootstrap.min.css') }}></link>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
} .header {
background-color: #f0f0f0;
text-align: center;
padding: 20px;
} .title {
font-size: 32px;
margin-bottom: 10px;
} .menu {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #FFDEAD;
border: 2px solid #DCDCDC;
} .menu li {
float: left;
font-size: 24px;
} .menu li a {
display: block;
color: #333;
text-align: center;
padding: 14px 16px;
text-decoration: none;
} .menu li a:hover {
background-color: #ddd;
} .content {
padding: 20px;
border: 2px solid blue;
}
</style>
</head>
<body>
<div class="header">
<div class="title">PandaCodeOCR</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>
</div>
</form>
</div>
</div>
</div> <div id="show" style="display: none;">
<!--显示上传的图片-->
<div class="col-md-6" style="border: 2px solid #ddd;">
<span class="label label-info">上传图片</span>
<!--静态加载 图片, url_for() 动态生成路径 -->
<img src="" alt="Image preview area..." title="preview-img" class="img-responsive">
</div> <div class="col-md-6" style="border: 2px solid #ddd;">
<!--显示识别结果JSON报文列表-->
<span class="label label-info">识别结果:</span>
<!-- 结果显示区 -->
<div id="result_show">加载中......</div>
</div>
</div>
</body>
</html>
<!--静态加载 script-->
<script src={{ url_for('static',filename='jquery1.3.3/jquery.min.js') }}></script>
<script src={{ url_for('static',filename='js/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[0];
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("加载中......"); {#上传图片识别表单事件,并显示识别结果信息#}
{# ajaxSubmit 请求异步响应#}
$("#fileForm").ajaxSubmit(function (data) {
var inner = "";
//alert(data['recognize_time'])
//循环输出返回结果,响应识别结果为每行列表
for (var i in data['result']) {
var value = data['result'][i]['text'];
inner += "<p class='text-left'>" + value + "</p>";
}
//清空输出结果信息
$("#result_show").html("");
//添加识别结果信息
$("#result_show").append(inner);
});
}, false);
</script>
主要python代码文件如下:
myapp.py:
import json
import os
import time from flask import Flask, render_template, request, jsonify from paddleocr import PaddleOCR
from PIL import Image, ImageDraw
import numpy as np # 应用名称,当前py名称,视图函数
app = Flask(__name__) # 项目文件夹的绝对路径
# BASE_DIR = os.path.dirname(os.path.abspath(__name__))
# 相对路径
BASE_DIR = os.path.dirname(os.path.basename(__name__)) # 上传文件路径
UPLOAD_DIR = os.path.join(os.path.join(BASE_DIR, 'static'), 'upload') '''
PaddleOCR模型通用识别方法
'''
def rec_model_ocr(img):
# 返回字典结果对象
result_dict = {'result': []}
# paddleocr 目前支持的多语言语种可以通过修改lang参数进行切换
# 例如`ch`, `en`, `fr`, `german`, `korean`, `japan`
# 使用CPU预加载,不用GPU
# 模型路径下必须包含model和params文件,目前开源的v3版本模型 已经是识别率很高的了
# 还要更好的就要自己训练模型了。
ocr = 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=False)
# 识别图片文件
result0 = ocr.ocr(img, cls=True)
result = result0[0]
for index in range(len(result)):
line = result[index] tmp_dict = {}
points = line[0]
text = line[1][0]
score = line[1][1]
tmp_dict['points'] = points
tmp_dict['text'] = text
tmp_dict['score'] = score result_dict['result'].append(tmp_dict)
return result_dict # 转换图片
def convert_image(image, threshold=None):
# 阈值 控制二值化程度,不能超过256,[200, 256]
# 适当调大阈值,可以提高文本识别率,经过测试有效。
if threshold is None:
threshold = 200
print('threshold : ', threshold)
# 首先进行图片灰度处理
image = image.convert("L")
pixels = image.load()
# 在进行二值化
for x in range(image.width):
for y in range(image.height):
if pixels[x, y] > threshold:
pixels[x, y] = 255
else:
pixels[x, y] = 0
return image @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)
print('file uploaded successfully') start = time.time() print('=======开始OCR识别======')
# 打开图片
img1 = Image.open(img_path)
# 转换图片, 识别图片文本
# print('转换图片,阈值=220时,再转换为ndarray数组, 识别图片文本')
# 转换图片
img2 = convert_image(img1, 220)
# Image图像转换为ndarray数组
img_2 = np.array(img2)
# 识别图片
result_dict = rec_model_ocr(img_2) # 识别时间
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"] = "识别成功" # render_template方法:渲染模板
# 参数1: 模板名称 参数n: 传到模板里的数据
# return render_template('result.html', result_dict=result_dict) # 将数据转换成JSON格式,一般用于ajax异步响应页面,不跳转页面用,等价下面方法
# return json.dumps(result_dict, ensure_ascii=False), {'Content-Type': 'application/json'} # 将数据转换成JSON格式,一般用于ajax异步响应页面,不跳转页面用
return jsonify(result_dict) else:
return render_template('upload.html') if __name__ == '__main__':
# 启动app
app.run(port=8000)
启动flask应用,测试结果如下:


PaddleOCR学习笔记3-通用识别服务的更多相关文章
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- 学习笔记TF058:人脸识别
人脸识别,基于人脸部特征信息识别身份的生物识别技术.摄像机.摄像头采集人脸图像或视频流,自动检测.跟踪图像中人脸,做脸部相关技术处理,人脸检测.人脸关键点检测.人脸验证等.<麻省理工科技评论&g ...
- Binder学习笔记(九)—— 服务端如何响应Test()请求 ?
从服务端代码出发,TestServer.cpp int main() { sp < ProcessState > proc(ProcessState::self()); sp < I ...
- matlab学习笔记10_5 通用字符串操作和比较函数
一起来学matlab-matlab学习笔记10 10_5 通用字符串操作和比较函数 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张 ...
- 10月9日Android学习笔记:活动与服务之间的通信
最近在照着<第一行代码>这本书来学安卓,顺便记下笔记.主要的内容是Android中服务的第二种启动方式,通过活动绑定服务来启动服务,实现活动与服务之间的通信. 一. 首先创建一个服务类 p ...
- Netty4 学习笔记之一:客户端与服务端通信 demo
前言 因为以前在项目中使用过Mina框架,感受到了该框架的强大之处.于是在业余时间也学习了一下Netty.因为Netty的主要版本是Netty3和Netty4(Netty5已经被取消了),所以我就直接 ...
- Netty4 学习笔记之四: Netty HTTP服务的实现
前言 目前主流的JAVA web 的HTTP服务主要是 springMVC和Struts2,更早的有JSP/servlet. 在学习Netty的时候,发现Netty 也可以作HTTP服务,于是便将此整 ...
- Docker学习笔记 - Docker客户端和服务端
学习内容: Docker客户端和服务端的通讯方式:client和自定义程序 Docker客户端和服务端的连接方式:socket 演示Docker客户端和服务端之间用remote-api通讯:nc ...
- Webpack4 学习笔记七 跨域服务代理
webpack 小插件使用 webpack 监听文件变化配置 webpack 处理跨域问题 Webpack 小插件使用 clean-webpack-plugin: 用于在生成之前删除生成文件夹的Web ...
- iOS学习笔记06-手势识别
一.UIGestureRecognizer简单介绍 我们已经学习了触摸事件处理,但触摸事件处理起来很麻烦,每个触摸事件处理都需要实现3个touches方法,比较繁琐,实际上我们可以使用更加简单的触摸事 ...
随机推荐
- Qt开源作品15-视频监控画面
一.前言 视频监控系统在整个安防领域,已经做到了烂大街的程序,全国起码几百家公司做过类似的系统,当然这一方面的需求量也是非常旺盛的,各种定制化的需求越来越多,尤其是这几年借着人脸识别的东风,发展更加迅 ...
- 开源即时通讯IM框架MobileIMSDK的鸿蒙NEXT端开发快速入门
相关链接: ① MobileIMSDK-鸿蒙端的详细介绍 ② MobileIMSDK-鸿蒙端的开发手册new(* 精编PDF版) 一.理论知识准备 您需要对鸿蒙Next和ArkTS开发有所了解: 1 ...
- 认识Token和Cookie
认识Token和Cookie 1.token和cookie有什么区别? 1.1 存储位置及方式:Cookie是浏览器用来存储本地信息的文件,有一定的存储限制,而Token是由服务器按一定算法生成的 ...
- Python 安装package 问题汇总
1. pip 命令使用国内源安装 pip install torch==1.8.1 -i https://mirrors.aliyun.com/pypi/simple/腾讯云: https://mir ...
- Harbor 共享后端高可用
1. 主机配置 主机地址 主机配置 主机角色 软件版本 192.168.1.60 CPU:4C MEM:4GB Disk: 100GB Harbor+Keepalived Harbor 2.1.3 K ...
- 题解:AT_abc386_d [ABC386D] Diagonal Separation
分析题面,发现题目求的是是否存在一个白点被 \((1, 1)\) 和任意一个黑点围成的矩形内. 先将所有黑点按 \(x\) 坐标排序. 枚举所有的白点. 找到所有横坐标不比该白点横坐标小的所有黑点的纵 ...
- c# 设置WebBrowser的UserAgent
void SuppressScriptErrors(WebBrowser webBrowser, bool hide) { webBrowser.Navigating += (s, e) => ...
- kafka的server.properties文件描述
版本:基于 kafka 2.4.0 http://archive.apache.org/dist/kafka/2.4.0/kafka_2.11-2.4.0.tgz # Licensed to the ...
- C++代码改造为UTF-8编码问题的总结
1. 引言 无论是哪个平台哪种编程语言,字符串乱码真是一个让人无语的问题:你说这个问题比较小吧,但是关键时刻来一下真是受不了.解决方式也有很多种,但是与其将编码转换来转换去,不如统一使用同一种编码方式 ...
- java list集合去重的两种方式