当前位置: 首页 > news >正文

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初始化里完成,虽然使用了额外线程去做,但还是会影响到主线程,主界面,有大佬知道怎么处理,还请指点!!!】

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

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

相关文章:

OCR实践-问卷表格统计

前言 书接上文 OCR实践—PaddleOCROCR实践-Table-Transformer 本项目代码已开源 放在 Github上&#xff0c;欢迎参考使用&#xff0c;Star https://github.com/caibucai22/TableAnalysisTool 主要功能说明&#xff1a;对手动拍照的问卷图片进行统计分数&#xff08;对应分数…...

uniapp中的条件编译

在script中 // #ifdef APP-PLUS console.log("11"); // #endif// #ifdef MP-WEIXIN console.log("22"); // #endif 在template中 <!-- #ifdef APP-PLUS --><view>哈哈哈</view> <!-- #endif --><!-- #ifdef MP-WEIXIN -->…...

Segment Routing Overview

大家觉得有意义和帮助记得及时关注和点赞!!! Segment Routing (SR) 是近年来网络领域的一项新技术&#xff0c;“segment” 在这里 指代网络隔离技术&#xff0c;例如 MPLS。如果快速回顾网络设计在过去几十年的 发展&#xff0c;我们会发现 SR 也许是正在形成的第三代网络设计…...

【K8s】专题十五(6):Kubernetes 网络之 Pod 网络调试

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…...

CMake 构建项目并整理头文件和库文件

本文将介绍如何使用 CMake 构建项目、编译生成库文件&#xff0c;并将头文件和库文件整理到统一的目录中以便在其他项目中使用。 1. 项目结构 假设我们正在构建一个名为 rttr 的开源库&#xff0c;初始的项目结构如下&#xff1a; D:\WorkCode\Demo\rttr-master\|- src\ …...

Boost之log日志使用

不讲理论&#xff0c;直接上在程序中可用代码&#xff1a; 一、引入Boost模块 开发环境&#xff1a;Visual Studio 2017 Boost库版本&#xff1a;1.68.0 安装方式&#xff1a;Nuget 安装命令&#xff1a; #只安装下面几个即可 Install-package boost -version 1.68.0 Install…...

多功能jquery图片预览放大镜插件

xZoom是一款多功能的jquery图片预览放大镜插件。它支持多种图片放大模式&#xff0c;可以和Fancy Box或Magnific Pop-up等插件结合使用&#xff0c;功能非常强大。 在线预览 下载 使用方法 在页面中引入jquery和xzoom.css以及xzoom.js文件。 <link rel"stylesheet&…...

CSS系列(39)-- Shapes详解

前端技术探索系列&#xff1a;CSS Shapes详解 ✨ 致读者&#xff1a;探索形状布局的艺术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS Shapes&#xff0c;这个强大的形状布局特性。 基础形状 &#x1f680; 圆形与椭圆 /* 基础圆形 */ .circle {widt…...

AI 神经网络在智能家居场景中的应用

在科技持续进步的当下&#xff0c;智能家居领域正经历着深刻变革&#xff0c;AI 神经网络技术的融入成为推动这一变革的关键力量&#xff0c;为家居生活带来了诸多显著变化与提升&#xff0c;本文将几种常见的AI算法应用做了一下总结&#xff0c;希望对物联网从业者有所帮助。 …...

Rocky DEM tutorial7_Conical Dryer_锥形干燥器

tutorial 7_Conical Dryer_锥形干燥器 文章目录 tutorial 7_Conical Dryer_锥形干燥器0. 目的1. 模型介绍2. 模型设置2.1设置physics2.2 导入几何2.3 设置motion2.4 Boundary边界设置2.5 设置材料2.6设置材料间相互作用2.7 创建粒子2.8 设置颗粒进口2.9 求解器设置3. 后处理Enj…...

CSS(二):美化网页元素

目录 字体样式 文本样式 列表样式 背景图片 字体样式 字体相关的 CSS 属性&#xff1a; font-family&#xff1a;设置字体font-size&#xff1a;设置字体大小font-weight&#xff1a;设置字体的粗细&#xff08;如 normal, bold, lighter 等&#xff09;color&#xff1a;…...

平方根无迹卡尔曼滤波(SR-UKF)算法,用于处理三维非线性状态估计问题

本MATLAB 代码实现了平方根无迹卡尔曼滤波&#xff08;SR-UKF&#xff09;算法&#xff0c;用于处理三维非线性状态估计问题 文章目录 运行结果代码概述代码 运行结果 三轴状态曲线对比&#xff1a; 三轴误差曲线对比&#xff1a; 误差统计特性输出&#xff08;命令行截图&…...

【论文笔记】Visual Alignment Pre-training for Sign Language Translation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Visual Alignment Pre-tra…...

NLP基础知识 - 向量化

NLP基础知识 - 向量化 目录 NLP基础知识 - 向量化 NLP基础知识 - 向量化目录什么是向量化&#xff1f;为什么需要向量化&#xff1f;常见的向量化方法1. 词袋模型&#xff08;Bag of Words, BoW&#xff09;2. TF-IDF&#xff08;词频-逆文档频率&#xff09;3. 词嵌入&#x…...

JAVA学习笔记_MySQL进阶

文章目录 存储引擎InnoDB引擎MyISAM引擎Memory存储引擎的选择 索引索引数据结构Btree(多路平衡查找树)BTreeHash索引为什么InnoDQB存储引擎采用Btree索引结构 索引分类思考题 索引语法索引性能分析慢查询日志show profiesexplain 索引的使用规则最左前缀法则索引失效SQL提示覆盖…...

ffmpeg: stream_loop报错 Error while filtering: Operation not permitted

问题描述 执行ffmpeg命令的时候&#xff0c;报错&#xff1a;Error while filtering: Operation not permitted 我得命令如下 ffmpeg -framerate 25 -y -i /data/workerspace/mtk/work_home/mtk_202406111543-l9CSU91H1f1b3/tmp/%08d.png -stream_loop -1 -i /data/workerspa…...

Vue.use()和Vue.component()

当很多页面用到同一个组件&#xff0c;又不想每次都在局部注册时&#xff0c;可以在main.js 中全局注册 Vue.component()一次只能注册一个组件 import CcInput from /components/cc-input.vue Vue.component(CcInput);Vue.use()一次可以注册多个组件 对于自定义的组件&#…...

javaweb 04 springmvc

0.1 在上一次的课程中&#xff0c;我们开发了springbootweb的入门程序。 基于SpringBoot的方式开发一个web应用&#xff0c;浏览器发起请求 /hello 后 &#xff0c;给浏览器返回字符串 “Hello World ~”。 其实呢&#xff0c;是我们在浏览器发起请求&#xff0c;请求了我们…...

[Visual studio] 性能探测器

最近发现VS的profile还是很好用的&#xff0c; 可以找到项目代码的瓶颈&#xff0c;比如发现CPU的每一个函数的时间占比&#xff0c;分析代码耗时分布&#xff0c;和火焰图一样的效果 如何使用 1. 打开你的项目&#xff0c;调整成release状态 2. 点击调试->性能探测器 3…...

【漫话机器学习系列】017.大O算法(Big-O Notation)

大 O 表示法&#xff08;Big-O Notation&#xff09; 大 O 表示法是一种用于描述算法复杂性的数学符号&#xff0c;主要用于衡量算法的效率&#xff0c;特别是随着输入规模增大时算法的运行时间或占用空间的增长趋势。 基本概念 时间复杂度 描述算法所需的运行时间如何随输入数…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态&#xff0c;这是一个可以多选的控件。 二、属性 其实功能大差不差&#xff0c;除了特殊的几个外&#xff0c;与button基本相同&#xff0c;所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...