OCR实践-问卷表格统计

前言

书接上文

  1. OCR实践—PaddleOCR
  2. OCR实践-Table-Transformer

本项目代码已开源 放在 Github上,欢迎参考使用,Star

https://github.com/caibucai22/TableAnalysisTool

在这里插入图片描述

主要功能说明:对手动拍照的问卷图片进行统计分数(对应分数打对号),单张问卷各项得分写入excel文件,并汇总所有图片得分到 excel

模型

基于前面的模型知识,完成了这一需求

首先涉及到的模型(在技术测试过程中,也发现了一些效果更好的模型,放在后续迭代过程中加入)

表格定位模型,使用ppstructure

表格特征编码模型和表格结构识别模型 分别是 Detr,和 微软的table-transformer-structure-recognition

字符识别模型,使用 PaddleOCR

对号处理模型,使用 微调的Yolov8n-cls(Yolov8n-det 也可以)

模型的加载统一放在 ModelManager.py 中实现

UI

在这里插入图片描述

UI,是用pyqt5简单实现的界面,主要包括

简单的进度展示

简单的图像状态展示

处理图像展示

打开单张图片、打开文件夹、以及 开始处理的三个按钮

其中模型加载,以及表格图像处理都是耗时操作,为了避免主进程阻塞,导致界面卡住,使用了 Worker 封装然后用线程执行,多提升点用户体验,在Workers.py 中定义

UI层逻辑

模型加载

self.model: TableProcessModel = None
self.thread = None
self.worker = None# load model by thread
self.load_model()

load_model函数

def load_model(self):self.thread = QThread()self.worker = ModelLoadWorker()self.worker.moveToThread(self.thread)# connectself.worker.model_loaded.connect(self.on_model_loaded)self.thread.started.connect(self.worker.run)self.thread.finished.connect(self.thread.deleteLater)#self.thread.start()

表格处理

def process_images_v2(self):if self.model is None:QMessageBox.information(self, 'info', "Model has not been loaded successfully! Please wait")returnif len(self.images_need_process) == 0:QMessageBox.information(self, 'info', "No Image loaded! Please load images")returnself.process_button.setEnabled(False)self.thread = QThread()self.worker = ImageProcessWorker(self.images_need_process, self.model, log=True)self.worker.moveToThread(self.thread)self.worker.image_processed.connect(self.update_ui)self.worker.finished.connect(self.on_processing_finished)self.worker.show_signal.connect(self.load_image_on_screen)self.thread.started.connect(self.worker.run)self.thread.start()

模型加载Worker

class ModelLoadWorker(QObject):model_loaded = pyqtSignal(object)def __init__(self):super().__init__()self.model = Nonedef run(self):try:self.model = TableProcessModel()except Exception as e:print('error loading model', e)else:self.model_loaded.emit(self.model)

如有问题,欢迎留言、私信或加群交流【群号:392784757】

Workers

图像(表格)处理 Worker

class ImageProcessWorker(QObject):image_processed = pyqtSignal(str)finished = pyqtSignal()show_signal = pyqtSignal(int)def __init__(self, images, model:TableProcessModel,log=False):super().__init__()self.images = imagesself.processor = modelself.log = log@pyqtSlot()def run(self):for i, image_path in enumerate(self.images):try:self.show_signal.emit(i)# 处理图片if self.log:print('processing ', image_path, '--->', end='')self.processor.run(image_path)if self.log:print('done')time.sleep(0.5)self.image_processed.emit(f"Processed: {image_path}")except Exception as e:self.image_processed.emit(f"Error processing {image_path}: {str(e)}")self.finished.emit()  # 处理完成

在具体执行时,交由线程处理,避免了主线程的阻塞

表格处理模块 TableProcess.py

涉及到的模型,表格定位模型、表格特征编码和表格结构识别模型

其中表格处理模块 在完成结构识别后,会调用统计分数模块,二者存在一定的低耦合性,但主要逻辑还是互相分离,比较清晰,也方便适配其他业务逻辑,只需要修改或添加 后面的业务模块,如统计分数

统一调用接口

def run(self, next_image_path):try:self.reset_results()self.image_path = next_image_pathself.load_image()self.initialize_cache_dir()self.run_parse_table()self.score_eval.eval_score()self.score_eval.to_xlsx()except Exception as e:print('run error ', e)

核心函数 run_parse_table()

def run_parse_table(self):table_image = self.infer_locate_table() # bgrif len(self.locate_table_bbox) == 0:raise Exception("定位表格失败")table_image = Image.fromarray(cv2.cvtColor(table_image,cv2.COLOR_BGR2RGB))target_sizes = [table_image.size[::-1]]self.encoding_for_table_split(table_image)if self.table_split_result['encoding'] is None:raise Exception("表格特征编码失败")self.infer_split(self.table_split_result['encoding'], target_sizes)if len(self.table_split_result.keys()) <= 1:raise Exception("表格切分失败")self.parse_table_split_result()# visualize first for debugif CACHE:self.draw_boxs(table_image.copy(), cut_cell=False)self.setup_score_eval(table_image)

整体流程:表格定位 -> 表格图像编码 -> 表格结构识别 -> 表格分数评估

中间图,settings.py 中提供了 CACHE = True 开启,默认False 关闭

在这里插入图片描述

其中

self.infer_locate_table()

self.encoding_for_table_split(table_image)

self.infer_split(self.table_split_result[‘encoding’], target_sizes)

分别涉及了模型的推理

完整代码,请前往 Github 下载查看

统计分数模块 ScoreEvaluation.py

涉及到的模块,字符识别模型、对号处理模型

主要函数 eval_score()

def eval_score(self):for row_i in range(self.n_row):if row_i == 0:continuescore_boxs = self.cells[row_i*self.n_col +self.score_col_start_idx:row_i*self.n_col+self.score_col_end_idx+1]line_score = self.eval_line_score(score_boxs)self.row_scores.append(line_score)self.score_history.append((f'{self.cur_image_name}_score.xlsx', sum(self.row_scores)))

eval_line_score() 评估每一行得分,涉及到模型推理,以及顺序的判断

完整代码,请前往 Github 下载查看

性能测试

4060 8G 16G RAM i9-13900HX

100张图片 GPU 3.5s/张,CPU4.6s/张

注意事项

欢迎一起探讨,留言、私信或加群 交流【群号:392784757】
编程过程注意

  • 使用一定的方法,防止模型重复加载(一次加载,多次推理)

  • paddle的模型 GPU的使用应该是自动管理的,use_gpu = True;其他模型的GPU推理,需要自行管理,同时需要设置 输入 和 模型 所在设备位置一致 CPU/GPU

  • 模型的推理与解析,需要先了解模型输入输出,根据官方demo/sample学习;然后结合自己的需求修改;多Debug;

  • 不同模型默认使用的图像读取,有的是 PIL.Image,或者是 cv2.imread() ,读取后送入模型处理,发现模型结果有一定区别,甚至完全不对,当发现你的模型结果很奇怪,不妨查看一下 输入

  • 耗时操作不要在主线程做【我的模型加载在ui初始化里完成,虽然使用了额外线程去做,但还是会影响到主线程,主界面,有大佬知道怎么处理,还请指点!!!】

  • 对于某些操作,如处理单张图片和文件夹多张图片 应该要统一;加载图片接口统一 不要分别实现

  • 注意资源的清理,临时变量的清理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yarn list --pattern vuex-module-decorators

dgqdgqdeMac-mini spid-admin % yarn list --pattern vuex-module-decorators yarn list v1.22.22 └─ vuex-module-decorators0.16.1 ✨ Done in 0.24s.好的&#xff0c;这段代码是一个典型的 Vuex 模块定义&#xff0c;使用了 vuex-module-decorators 库。这个库为 Vuex 提…

用Python写炸金花游戏

文章目录 **代码分解与讲解**1. **扑克牌的生成与洗牌**2. **给玩家发牌**3. **打印玩家的手牌**4. **定义牌的优先级**5. **判断牌型**6. **确定牌型优先级**7. **比较两手牌的大小**8. **打印结果** 完整代码 以下游戏规则&#xff1a; 那么我们要实现的功能&#xff0c;就是…

day19-Linux软件包

科普&#xff0c;什么是代码文件。 电脑程序Program&#xff0c;就是某一个编程语言编写的一个代码文件&#xff0c;里面包含了该语言特有的指令&#xff0c;以及各种字符、符号。 linux自带的network管理脚本&#xff0c;shell脚本 什么是软件程序。 软件程序&#xff0c;就…

图像处理-Ch4-频率域处理

Ch4 频率域处理(Image Enhancement in Frequency Domain) FT &#xff1a;将信号表示成各种频率的正弦信号的线性组合。 频谱&#xff1a; ∣ F ( u , v ) ∣ [ R 2 ( u , v ) I 2 ( u , v ) ] 1 2 |F(u, v)| \left[ R^2(u, v) I^2(u, v) \right]^{\frac{1}{2}} ∣F(u,v)…

Vue BPMN Modeler流程图

1、参考地址 git clone https://github.com/evanyangg/vue-bpmn-modeler.git 2、安装bpmn.js npm install bpmn-js --save 3、使用bpmn.js <template><div class"containers"><div class"canvas" ref"canvas"></div&g…

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码 大家都知道使用CubMAX可以很快的将&#xff0c;FATFS文件管理系统移植到单片机上&#xff0c;但是别的芯片没有这么好用的工具&#xff0c;就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题&#xff0c;然后再移植FATFS文件管理系统。 二、SD…

5、栈应用-表达式求值

本章内容使用上述栈结构函数&#xff0c;来完成表达式求值操作。 表达式例如&#xff1a;3*(7-2) 或者 (0-12)*((5-3)*32)/(22) 。 1、实现思路 a、建立OPTR&#xff08;运算符&#xff09;和OPND&#xff08;数字&#xff09;两个栈&#xff0c;后输入字符串以结束 b、自左向…

【递归与回溯深度解析:经典题解精讲(下篇)】—— Leetcode

文章目录 有效的数独解数独单词搜索黄金矿工不同的路径||| 有效的数独 递归解法思路 将每个数独的格子视为一个任务&#xff0c;依次检查每个格子是否合法。 如果当前格子中的数字违反了数独规则&#xff08;在行、列或 33 小方块中重复&#xff09;&#xff0c;直接返回 Fals…

Llama 3 预训练(二)

目录 3. 预训练 3.1 预训练数据 3.1.1 网络数据筛选 PII 和安全过滤 文本提取与清理 去重&#xff08;De-duplication&#xff09; 启发式过滤&#xff08;Heuristic Filtering&#xff09; 基于模型的质量过滤 代码和数学推理数据处理 多语言数据处理 3.1.2 确定数…

双指针——查找总价格为目标值的两个商品

一.题目描述 LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 二.题目解析 这个题目非常简单&#xff0c;其实就是判断有没有两个数加起来等于target。 三.算法解析 1.暴力解法 暴力解法的话我们可以枚举出所有的情况&#xff0c;然后判…

sqlserver镜像设置

本案例是双机热备&#xff0c;只设置主体服务器&#xff08;主&#xff09;和镜像服务器&#xff08;从&#xff09;&#xff0c;不设置见证服务器 设置镜像前先检查是否启用了 主从服务器数据库的 TCP/IP协议 和 RemoteDAC &#xff08;1&#xff09;打开SQL Server配置管理器…

Elasticsearch:analyzer(分析器)

一、概述 可用于将字符串字段转换为单独的术语&#xff1a; 添加到倒排索引中&#xff0c;以便文档可搜索。级查询&#xff08;如 生成搜索词的 match查询&#xff09;使用。 分析器分为内置分析器和自定义的分析器&#xff0c;它们都是由若干个字符过滤器&#xff08;chara…

ElementPlus 自定义封装 el-date-picker 的快捷功能

文章目录 需求分析 需求 分析 我们看到官网上给出的案例如下&#xff0c;但是不太满足我们用户想要的快捷功能&#xff0c;因为不太多&#xff0c;因此需要我们自己封装一些&#xff0c;方法如下 外部自定义该组件的快捷内容 export const getPickerOptions () > {cons…

低代码开发平台排名2024

低代码开发平台在过去几年中迅速崛起&#xff0c;成为企业数字化转型的重要工具。这些平台通过可视化界面和拖放组件&#xff0c;使业务人员和技术人员都能快速构建应用程序&#xff0c;大大缩短了开发周期。以下是一些在2024年值得关注和使用的低代码开发平台。 一、Zoho Cre…

计算机网络——期末复习(4)协议或技术汇总、思维导图

思维导图 协议与技术 物理层通信协议&#xff1a;曼彻斯特编码链路层通信协议&#xff1a;CSMA/CD &#xff08;1&#xff09;停止-等待协议&#xff08;属于自动请求重传ARQ协议&#xff09;&#xff1a;确认、否认、重传、超时重传、 &#xff08;2&#xff09;回退N帧协…

【MySQL学习笔记】关于索引

文章目录 【MySQL学习笔记】关于索引1.索引数据结构2.索引存储3.联合索引3.1 联合索引的b树结构3.2 索引覆盖&#xff1f;回表&#xff1f;3.3 联合索引最左匹配原则3.5 索引下推 4.索引失效 【MySQL学习笔记】关于索引 1.索引数据结构 索引是一种能提高查询速度的数据结构。…

D104【python 接口自动化学习】- pytest进阶参数化用法

day104 pytest参数化parametrize单参数 学习日期&#xff1a;20241223 学习目标&#xff1a;pytest基础用法 -- pytest参数化parametrize单参数 学习笔记&#xff1a; 参数化 parametrize 参数化可以组装测试数据&#xff0c;在测试前定义好测试数据&#xff0c;并在测试用…

第T4周:TensorFlow实现猴痘识别(Tensorboard的使用)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标&#xff1a; 1、学习tensorboard的使用 具体实现&#xff1a; &#xff08;一&#xff09;环境&#xff1a; 语言环境&#xff1a;Python 3.10 编 译 器…

Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde

介绍 安装自己的linux-server,可以作为学习使用&#xff0c;web方式访问&#xff0c;基于ubuntu构建开源项目 https://github.com/linuxserver/docker-webtop安装 docker run -d -p 1336:3000 -e PASSWORD123456 --name webtop lscr.io/linuxserver/webtop:ubuntu-kde登录 …

小米路由器开启SSH,配置阿里云ddns,开启外网访问SSH和WEB管理界面

文章目录 前言一、开启SSH二、配置阿里云ddns1.准备工作2.创建ddns脚本3.添加定时任务 三、开启外网访问SSH和WEB管理界面1、解除WEB管理页面访问限制2.手动添加防火墙端口转发规则&#xff0c;开启外网访问WEB管理和SSH 前言 例如&#xff1a;随着人工智能的不断发展&#xf…