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应用,测试结果如下: