PaddleOCR学习笔记2-初步识别服务
今天初步实现了网页,上传图片,识别显示结果到页面的服务。后续再完善。
采用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="http://localhost:5000/uploader">通用文本识别</a></li></ul><div class="content"><!--上传图片文件--><div id="upload_file"><form action="http://localhost:5000/uploader" method="POST" enctype="multipart/form-data"><div class="form-group"><input type="file" class="form-control" id="upload_file" name="upload_file" placeholder="upload_file"></div><div class="form-group"><button type="submit" class="form-control btn-primary">上传图片文件</button></div></form></div></div>
</body>
</html>
result.html :
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head><title>结果</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;}</style>
</head>
<body><div class="header"><div class="title">PandaCodeOCR</div></div><ul class="menu"><li><a href="http://localhost:5000/uploader">通用文本识别</a></li></ul><div class="row"><!--显示上传的图片--><div class="col-md-6" style="border: 2px solid #ddd;"><span class="label label-info">上传图片</span><!--静态加载 图片--><img src="{{ url_for('static', filename = result_dict['filename'])}}" alt="show_img" class="img-responsive"></div><div class="col-md-6" style="border: 2px solid #ddd;"><!--显示识别结果JSON报文列表--><span class="label label-info">识别结果:</span>{% for line_str in result_dict['result'] %}<p class="text-left">{{ line_str['text'] }}</p>{% endfor %}</div></div>
</body>
</html>
<!--静态加载 script-->
<script src={{ url_for('static',filename='jquery1.3.3/jquery.min.js')}}></script>
主要视图代码文件如下:
views.py :
import json
import os
import timefrom . import blue_task
from flask import Flask, render_template, requestfrom paddleocr import PaddleOCR
from PIL import Image,ImageDraw
import numpy as np'''
自定义模型测试ocr方法
'''def test_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'] = pointstmp_dict['text'] = texttmp_dict['score'] = scoreresult_dict['result'].append(tmp_dict)return result_dict# 转换图片
def convert_image(image, threshold=None):# 阈值 控制二值化程度,不能超过256,[200, 256]# 适当调大阈值,可以提高文本识别率,经过测试有效。if threshold is None:threshold = 200print('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] = 255else:pixels[x, y] = 0return image@blue_task.route('/upload')
def upload_file():return render_template('upload.html')@blue_task.route('/uploader', methods=['GET', 'POST'])
def uploader():if request.method == 'POST':#每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。filedata = request.files['upload_file']upload_filename = filedata.filenameprint(upload_filename)#保存文件到指定路径#目标文件的名称可以是硬编码的,也可以从 request.files[file] 对象的 filename 属性中获取。#但是,建议使用 secure_filename() 函数获取它的安全版本img_path = os.path.join('upload/', 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 = test_model_ocr(img_2)# 识别时间end = time.time()recognize_time = int((end - start) * 1000)result_dict["filename"] = img_pathresult_dict["recognize_time"] = str(recognize_time)result_dict["error_code"] = "000000"result_dict["error_msg"] = "识别成功"# return json.dumps(result_dict, ensure_ascii=False), {'Content-Type': 'application/json'}# render_template方法:渲染模板# 参数1: 模板名称 参数n: 传到模板里的数据return render_template('result.html', result_dict=result_dict)else:return render_template('upload.html')
启动flask应用,测试结果如下:



相关文章:
PaddleOCR学习笔记2-初步识别服务
今天初步实现了网页,上传图片,识别显示结果到页面的服务。后续再完善。 采用flask paddleocr bootstrap快速搭建OCR识别服务。 代码结构如下: 模板页面代码文件如下: upload.html : <!DOCTYPE html> <html> <…...
【Opencv】Pyhton 播放上一帧,下一帧,存video,逐帧分析
文章目录 读取具体哪一帧等待按钮写入解码方式与文件格式对应全部代码 读取具体哪一帧 这个方法可以获取某一帧: while True:cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)ret, frame cap.read()if not ret:break等待按钮 这个方法可以显示当前帧,…...
【关于Java:认识异常】
文章目录 一、1. 异常概念与体系结构1.1 异常的概念1.2 常见的异常1.算数异常2.数组越界异常3.空指针异常 1.3 异常的体系结构1.4 异常的分类1. 编译时异常2. 运行时异常(RuntimeException) 二、 异常的处理方式2.1 防御式编程2.2 EAFP:(异常…...
【C++ • STL • 力扣】详解string相关OJ
文章目录 1、仅仅翻转字母2、字符串中的第一个唯一字符3、字符串里最后一个单词的长度4、验证一个字符串是否是回文5、字符串相加总结 ヾ(๑╹◡╹)ノ" 人总要为过去的懒惰而付出代价 ヾ(๑╹◡╹)ノ" 1、仅仅翻转字母 力扣链接 代码1展示&…...
【Tomcat服务部署及优化】
Tomcat 一、什么是Tomcat?二、Tomcat 核心组件2.1 Tomcat 组件2.3 Container组件的结构2.4 Tomcat 请求过程 三、Tomcat 部署3.1 安装JDK3.2 设置JDK环境变量3.3 安装Tomcat并用supervisor启动解压添加到supervisord服务测试能否通过supervisorctl启动 四、Tomcat的端口和主要…...
C++之红黑树
红黑树 红黑树的概念红黑树的性质红黑树结点的定义红黑树的插入红黑树的验证红黑树与AVL树的比较 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上…...
Go语言网络编程(socket编程)TCP
1、TCP编程 1.1.1 Go语言实现TCP通信 TCP协议 TCP/IP(Transmission Control Protocol/Internet Protocol) 即传输控制协议/网间协议,是一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transport layer)通信协…...
C语言——局部和全局变量
局部变量 定义在函数内部的变量称为局部变量(Local Variable) 局部变量的作用域(作用范围)仅限于函数内部, 离开该函数后是无效的 离开该函数后,局部变量自动释放 示例代码: #include <stdio.h>// 函数定义 …...
【Java基础篇 | 类和对象】--- 聊聊什么是内部类
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习Java的一点学习心得,欢迎大家在评论区讨论💌 前言 当一个事物的内部&…...
合宙Air724UG LuatOS-Air LVGL API控件-页面 (Page)
页面 (Page) 当控件内容过多,无法在屏幕内完整显示时,可让其在 页面 内显示。 示例代码 page lvgl.page_create(lvgl.scr_act(), nil) lvgl.obj_set_size(page, 150, 200) lvgl.obj_align(page, nil, lvgl.ALIGN_CENTER, 0, 0)label lvgl.label_crea…...
mongodb数据库操作
1、启动mongodb /usr/local/mongodb/bin/mongod --dbpath /var/mongodb/data/--logpath /var/mongodb/logs/log.log &在mongodb启动命令中 --dbpath 指定mongodb的数据存储路径 --logpath 指定mongodb的日志存储路径 2、停止mongodb 第一步先进入mongo命令行模式 第二…...
第 2 章 线性表 ( 双链循环线性表(链式存储结构)实现)
1. 背景说明 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H#define CHECK_NULL(pointer) if (!(pointer)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR…...
redis在日常开发工作中的常见用法
redis是一款内存型数据库,在开发工作中经常用到,功能强大; 特别开一篇文章用来记录一下它的常见用法,算是一种总结; 它最主要的特点就是高可用的,速度快,分布式;有人说速度快&…...
小程序实现下拉刷新
小程序实现下拉刷新可以通过使用组件scroll-view和事件onPullDownRefresh来实现。 scroll-view组件的使用 在需要下拉刷新的页面的wxml文件中,通过scroll-view组件包裹需要滚动的内容,设置scroll-y属性为true,表示允许竖向滚动。示例代码如…...
Day 36 贪心算法 part05 : 435. 无重叠区间 763.划分字母区间 56. 合并区间
56. 合并区间 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 1: 输入:inte…...
使用Python将网页数据保存到NoSQL数据库的方法和示例
随着大数据和人工智能技术的快速发展,对于大规模数据的处理需求日益增多。NoSQL数据库作为一种新兴的数据存储解决方案,具有高可扩展性、高性能和灵活性数据模型等优势,已经在许多行业得到广泛应用。传统的关系型数据库在处理海量数据时可能会…...
两个路由器如何连接设置的方法攻略
一、前言 随着智能家居时代来临,家里的网络部署需求开始复杂起来。往往一个路由器已经不能满足需求或者不利于拓展。两个路由器连接最常见的情况是家中已有一个路由器,并且已经通过这个路由器来正常上网。现在是因某些原因想在不改变已经在用的路由器的设…...
分类任务评价指标
分类任务评价指标 分类任务中,有以下几个常用指标: 混淆矩阵准确率(Accuracy)精确率(查准率,Precision)召回率(查全率,Recall)F-scorePR曲线ROC曲线 1. 混…...
c++静态成员
目录 静态成员 静态成员变量 静态成员函数 const 静态成员属性 静态成员实现单例模式 静态成员 在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字 static 声明为静态的,称为静态成员。 不管这…...
go-zero直连与etcd服务注册中心
go-zero中直连方式 在使用grpc是最重要的就是pb文件了,生成的pb文件,通过pb文件可以生成grpc的客户端和服务端,那么客户端和服务端就可以直连了,再次基础上可以引入etcd实现服务注册。 所有的代码都需要开发者编写,包…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
