• PaddleOCR学习笔记3-通用识别服务


    今天优化了下之前的初步识别服务的python代码和html代码。

    采用flask + paddleocr+ bootstrap快速搭建OCR识别服务。

    代码结构如下:

    模板页面代码文件如下:

    upload.html :

    1. <!DOCTYPE html>
    2. <html>
    3. <meta charset="utf-8">
    4. <head>
    5. <title>PandaCodeOCR</title>
    6. <!--静态加载 样式-->
    7. <link rel="stylesheet" href={{ url_for('static',filename='bootstrap3/css/bootstrap.min.css') }}></link>
    8. <style>
    9. body {
    10. font-family: Arial, sans-serif;
    11. margin: 0;
    12. padding: 0;
    13. }
    14. .header {
    15. background-color: #f0f0f0;
    16. text-align: center;
    17. padding: 20px;
    18. }
    19. .title {
    20. font-size: 32px;
    21. margin-bottom: 10px;
    22. }
    23. .menu {
    24. list-style-type: none;
    25. margin: 0;
    26. padding: 0;
    27. overflow: hidden;
    28. background-color: #FFDEAD;
    29. border: 2px solid #DCDCDC;
    30. }
    31. .menu li {
    32. float: left;
    33. font-size: 24px;
    34. }
    35. .menu li a {
    36. display: block;
    37. color: #333;
    38. text-align: center;
    39. padding: 14px 16px;
    40. text-decoration: none;
    41. }
    42. .menu li a:hover {
    43. background-color: #ddd;
    44. }
    45. .content {
    46. padding: 20px;
    47. border: 2px solid blue;
    48. }
    49. </style>
    50. </head>
    51. <body>
    52. <div class="header">
    53. <div class="title">PandaCodeOCR</div>
    54. </div>
    55. <ul class="menu">
    56. <li><a href="/upload/">通用文本识别</a></li>
    57. </ul>
    58. <div class="content">
    59. <!--上传图片文件-->
    60. <div id="upload_file">
    61. <form id="fileForm" action="/upload/" method="POST" enctype="multipart/form-data">
    62. <div class="form-group">
    63. <input type="file" class="form-control" id="upload_file" name="upload_file">
    64. <label class="sr-only" for="upload_file">上传图片</label>
    65. </div>
    66. </form>
    67. </div>
    68. </div>
    69. </div>
    70. <div id="show" style="display: none;">
    71. <!--显示上传的图片-->
    72. <div class="col-md-6" style="border: 2px solid #ddd;">
    73. <span class="label label-info">上传图片</span>
    74. <!--静态加载 图片, url_for() 动态生成路径 -->
    75. <img src="" alt="Image preview area..." title="preview-img" class="img-responsive">
    76. </div>
    77. <div class="col-md-6" style="border: 2px solid #ddd;">
    78. <!--显示识别结果JSON报文列表-->
    79. <span class="label label-info">识别结果:</span>
    80. <!-- 结果显示区 -->
    81. <div id="result_show">加载中......</div>
    82. </div>
    83. </div>
    84. </body>
    85. </html>
    86. <!--静态加载 script-->
    87. <script src={{ url_for('static',filename='jquery1.3.3/jquery.min.js') }}></script>
    88. <script src={{ url_for('static',filename='js/jquery-form.js') }}></script>
    89. <script type="text/javascript">
    90. var fileInput = document.querySelector('input[type=file]');
    91. var previewImg = document.querySelector('img');
    92. {#上传图片事件#}
    93. fileInput.addEventListener('change', function () {
    94. var file = this.files[0];
    95. var reader = new FileReader();
    96. //显示预览界面
    97. $("#show").css("display", "block");
    98. // 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片
    99. reader.addEventListener("load", function () {
    100. previewImg.src = reader.result;
    101. }, false);
    102. // 调用reader.readAsDataURL()方法,把图片转成base64
    103. reader.readAsDataURL(file);
    104. //初始化输出结果信息
    105. $("#result_show").html("加载中......");
    106. {#上传图片识别表单事件,并显示识别结果信息#}
    107. {# ajaxSubmit 请求异步响应#}
    108. $("#fileForm").ajaxSubmit(function (data) {
    109. var inner = "";
    110. //alert(data['recognize_time'])
    111. //循环输出返回结果,响应识别结果为每行列表
    112. for (var i in data['result']) {
    113. var value = data['result'][i]['text'];
    114. inner += "

      " + value + "

      "
      ;
    115. }
    116. //清空输出结果信息
    117. $("#result_show").html("");
    118. //添加识别结果信息
    119. $("#result_show").append(inner);
    120. });
    121. }, false);
    122. </script>

    主要python代码文件如下:

    myapp.py:

    1. import json
    2. import os
    3. import time
    4. from flask import Flask, render_template, request, jsonify
    5. from paddleocr import PaddleOCR
    6. from PIL import Image, ImageDraw
    7. import numpy as np
    8. # 应用名称,当前py名称,视图函数
    9. app = Flask(__name__)
    10. # 项目文件夹的绝对路径
    11. # BASE_DIR = os.path.dirname(os.path.abspath(__name__))
    12. # 相对路径
    13. BASE_DIR = os.path.dirname(os.path.basename(__name__))
    14. # 上传文件路径
    15. UPLOAD_DIR = os.path.join(os.path.join(BASE_DIR, 'static'), 'upload')
    16. '''
    17. PaddleOCR模型通用识别方法
    18. '''
    19. def rec_model_ocr(img):
    20. # 返回字典结果对象
    21. result_dict = {'result': []}
    22. # paddleocr 目前支持的多语言语种可以通过修改lang参数进行切换
    23. # 例如`ch`, `en`, `fr`, `german`, `korean`, `japan`
    24. # 使用CPU预加载,不用GPU
    25. # 模型路径下必须包含model和params文件,目前开源的v3版本模型 已经是识别率很高的了
    26. # 还要更好的就要自己训练模型了。
    27. ocr = PaddleOCR(det_model_dir='./inference/ch_PP-OCRv3_det_infer/',
    28. rec_model_dir='./inference/ch_PP-OCRv3_rec_infer/',
    29. cls_model_dir='./inference/ch_ppocr_mobile_v2.0_cls_infer/',
    30. use_angle_cls=True, lang="ch", use_gpu=False)
    31. # 识别图片文件
    32. result0 = ocr.ocr(img, cls=True)
    33. result = result0[0]
    34. for index in range(len(result)):
    35. line = result[index]
    36. tmp_dict = {}
    37. points = line[0]
    38. text = line[1][0]
    39. score = line[1][1]
    40. tmp_dict['points'] = points
    41. tmp_dict['text'] = text
    42. tmp_dict['score'] = score
    43. result_dict['result'].append(tmp_dict)
    44. return result_dict
    45. # 转换图片
    46. def convert_image(image, threshold=None):
    47. # 阈值 控制二值化程度,不能超过256,[200, 256]
    48. # 适当调大阈值,可以提高文本识别率,经过测试有效。
    49. if threshold is None:
    50. threshold = 200
    51. print('threshold : ', threshold)
    52. # 首先进行图片灰度处理
    53. image = image.convert("L")
    54. pixels = image.load()
    55. # 在进行二值化
    56. for x in range(image.width):
    57. for y in range(image.height):
    58. if pixels[x, y] > threshold:
    59. pixels[x, y] = 255
    60. else:
    61. pixels[x, y] = 0
    62. return image
    63. @app.route('/')
    64. def upload_file():
    65. return render_template('upload.html')
    66. @app.route('/upload/', methods=['GET', 'POST'])
    67. def upload():
    68. if request.method == 'POST':
    69. # 每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。
    70. filedata = request.files['upload_file']
    71. upload_filename = filedata.filename
    72. print(upload_filename)
    73. # 保存文件到指定路径
    74. # 目标文件的名称可以是硬编码的,也可以从 ​request.files[file] ​对象的​ filename ​属性中获取。
    75. # 但是,建议使用 ​secure_filename()​ 函数获取它的安全版本
    76. if not os.path.exists(UPLOAD_DIR):
    77. os.makedirs(UPLOAD_DIR)
    78. img_path = os.path.join(UPLOAD_DIR, upload_filename)
    79. filedata.save(img_path)
    80. print('file uploaded successfully')
    81. start = time.time()
    82. print('=======开始OCR识别======')
    83. # 打开图片
    84. img1 = Image.open(img_path)
    85. # 转换图片, 识别图片文本
    86. # print('转换图片,阈值=220时,再转换为ndarray数组, 识别图片文本')
    87. # 转换图片
    88. img2 = convert_image(img1, 220)
    89. # Image图像转换为ndarray数组
    90. img_2 = np.array(img2)
    91. # 识别图片
    92. result_dict = rec_model_ocr(img_2)
    93. # 识别时间
    94. end = time.time()
    95. recognize_time = int((end - start) * 1000)
    96. result_dict["filename"] = upload_filename
    97. result_dict["recognize_time"] = str(recognize_time)
    98. result_dict["error_code"] = "000000"
    99. result_dict["error_msg"] = "识别成功"
    100. # render_template方法:渲染模板
    101. # 参数1: 模板名称 参数n: 传到模板里的数据
    102. # return render_template('result.html', result_dict=result_dict)
    103. # 将数据转换成JSON格式,一般用于ajax异步响应页面,不跳转页面用,等价下面方法
    104. # return json.dumps(result_dict, ensure_ascii=False), {'Content-Type': 'application/json'}
    105. # 将数据转换成JSON格式,一般用于ajax异步响应页面,不跳转页面用
    106. return jsonify(result_dict)
    107. else:
    108. return render_template('upload.html')
    109. if __name__ == '__main__':
    110. # 启动app
    111.    app.run(port=8000)

    启动flask应用,测试结果如下:

  • 相关阅读:
    数据库 -neo4j的基本操作
    华为面试题
    浏览器提示“此网站的安全证书有问题“,你还敢继续访问吗?
    【数据结构】手撕二叉树oj练习与经典问题
    无锡室内设计培训——室内的十种设计手法
    计算机毕业设计之java+javaweb的理发店管理系统
    1015 德才论【PAT (Basic Level) Practice (中文)】
    LeetCode练习4——删除有序数组中的重复项
    SHELL内涵段子
    说说未来趋势 「元宇宙」是什么?
  • 原文地址:https://blog.csdn.net/xionghui2007/article/details/132754240