Python 调用 Umi-OCR API 批量识别图片/PDF文档数据

目录

一、需求分析

二、方案设计(概要/详细)

三、技术选型

四、OCR 测试 Demo

五、批量文件识别完整代码实现 

六、总结


一、需求分析

        市场部同事进行采购或给客户报价时,往往基于过往采购合同数据,给出现在采购或报价的金额区间,现需要整合过往已有合同数据进行录入,以Excel 表格形式,方便市场部同事查找和计算。

二、方案设计(概要/详细)

        由于合同文件数据类型多样,格式复杂(样式不固定,且不是单纯的文本文字)于是在数据录入过程中需要进行如下几步操作:

  • 数据分类

如果一个PDF包含图像,通常是由扫描仪或者拍照设备生成的PDF。遍历所有的文件判断每一页是否含有图像。把所有文件分成两类,有图(扫描或拍照生成的PDF)或无图(Word转PDF)

  • 数据清洗刷选,校准

a.对于格式相对固定的Word转PDF文件,将数据可以全部获取,使用模板匹配提取关键字段(如采购名称、数量、价格、日期等)。在按照关键词(金额,时间等)匹配,并写道Excel A中,并对得到的数据内容进行验证校准。

b.扫描或拍照生成的PDF,使用OCR光学识别,将PDF页面转化成图片,然后再识别图片内容,进行关键词匹配并写道Excel B中,并对得到的数据内容进行验证校准。

  • 数据整合

设计好最终需要的Excel要有哪些字段,然后将Excel A 和 Excel B 按照时间排序归并到最终的Excel中 (所有的数据按照时间都存到一个sheet中,方便后期直接查询)

三、技术选型

        由于要用到一些数据处理上的方法,使用 Python 会简单一点 ,同时这只是一个简单的需求,不算是一个正规的项目,应该越快越简单越好 Python 作为脚本语言是很好的选择 ,于是采用的技术栈就是 Python + OCR 

四、OCR 测试 Demo

import pytesseract
import codecs
from PIL import Imageif __name__ == '__main__':# 指定 Tesseract 安装路径pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'im = Image.open('./test.png')result = pytesseract.image_to_string(im, lang='chi_sim')print(result)# 首先导入codecs库,用codecs.open()方法创建并打开一个名为output.txt的文件,以utf-8编码模式写入resultwith codecs.open('output.txt', 'w', encoding='utf-8') as f:f.write(result)

        这种方式只能识别简单的图片文本内容,但是对于拍照,扫描版,以及图片中含有表格的形式,都无法识别。 

 

识别结果

        于是更换思路,自己实现OCR难度较大且识别效果不好,经过调研之后,发现GitHub 上有一个开源的OCR 识别工具,可以直接调用里面的API接口,不用自己写OCR 识别方法了。

        Umi-OCR总结有几大特点:免费、方便、高效、灵活 支持繁中、英语、日语等语言,使用不同的识别引擎就能识别不同种类的文字,并且给开发者提供Http服务,使用api的方式,让不同的编程语言都调用接口。

Release Umi-OCR v2.1.4 · hiroi-sora/Umi-OCR

下面给出安装包的下载地址 

Release Umi-OCR v2.1.4 · hiroi-sora/Umi-OCR

测试结果:

说明:在测试的时候,OCR工具记得打开,否则连接不上

五、批量文件识别完整代码实现 

import requests
import json
import openpyxl
import os
import base64
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from PIL import Image
from io import BytesIO
from openpyxl import Workbook
from openpyxl.drawing.image import Image as ExcelImage
import fitz  # PyMuPDF# compress_image 功能:压缩图片,确保其文件大小不超过指定的最大值。 参数:image_path (str): 图片文件的路径。 max_size_kb (int, 默认值 1024): 图片的最大文件大小(单位:KB)。
# 逻辑:
#   打开图片并获取其 EXIF 信息。
#   获取原始图片的尺寸。
#   使用循环尝试不同的质量参数,直到文件大小小于或等于 max_size_kb 或质量参数降到 10 以下。
#   保存压缩后的图片,确保其尺寸与原始图片一致。
#   返回压缩后的图片对象。def compress_image(image_path, max_size_kb=1024):print("进入压缩方法")# 打开图片img = Image.open(image_path)# 保留图片的 EXIF 信息exif_data = img.info.get('exif', None)# 获取原始图片的尺寸original_size = img.size# 尝试不同的质量参数,直到文件大小小于或等于 max_size_kbquality = 95while True:# 保存压缩后的图片,保留 EXIF 信息img.save(image_path, format=img.format, optimize=True, quality=quality, exif=exif_data)# 检查文件大小file_size_kb = os.path.getsize(image_path) / 1024if file_size_kb <= max_size_kb or quality <= 10:break# 降低质量参数quality -= 5# 确保压缩后的图片尺寸与原始图片一致img = Image.open(image_path)if img.size != original_size:img = img.resize(original_size)img.save(image_path, format=img.format, optimize=True, quality=quality, exif=exif_data)print(f"图片压缩完成,文件大小: {file_size_kb:.2f} KB")return img  # 返回压缩后的图片对象# post_url 功能:发送 POST 请求到 OCR API,并将结果写入 Excel 文件。 参数: base64_strings (list): 图片的 Base64 编码字符串列表。excel_file_path (str): Excel 文件的路径。file_name (str): 文件名。imgs (list): 图片对象列表。
# 逻辑:
#   构建请求数据,包括 Base64 编码的图片字符串和选项。
#   设置请求头和重试策略。
#   发送 POST 请求到指定 URL。
#   解析响应数据并将其写入 Excel 文件的相应单元格。
#   调用 insert_images_into_excel 方法将图片插入到 Excel 文件中。
#   保存 Excel 文件。
#   处理请求异常并打印错误信息。def post_url(base64_strings, excel_file_path, file_name, imgs):url = "http://127.0.0.1:1224/api/ocr"data = {"base64": base64_strings[0],"options": {"data.format": "text",}}headers = {"Content-Type": "application/json"}data_str = json.dumps(data)session = requests.Session()retries = Retry(total=4, backoff_factor=2, status_forcelist=[502, 503, 504])session.mount('http://', HTTPAdapter(max_retries=retries))try:response = session.post(url, data=data_str, headers=headers, timeout=100)response.raise_for_status()res_dict = json.loads(response.text)# 写入 Excelworkbook = openpyxl.load_workbook(excel_file_path)sheet = workbook['Sheet']row = sheet.max_row + 1base_name = os.path.splitext(file_name)[0]  # 去掉文件后缀sheet[f'A{row}'] = base_name  # 文件名放在第一列sheet[f'B{row}'] = res_dict.get('data', '')  # 文件内容放在第二列# 插入图片insert_images_into_excel(sheet, row, imgs)# 保存工作簿workbook.save(excel_file_path)except requests.exceptions.RequestException as e:print(f"请求失败: {e}")print(f'post_url 方法调用完成!文件: {file_name}')# insert_images_into_excel 功能:将图片插入到 Excel 工作表中。 参数: sheet (openpyxl.worksheet.worksheet.Worksheet): Excel 工作表对象。 row (int): 插入图片的行号。 imgs (list): 图片对象列表。
# 逻辑:
#    初始化列索引为 3(即 C 列)。
#    遍历图片对象列表,生成正确的列名。
#    将图片对象插入到指定的单元格。
#    更新列索引以插入下一张图片。def insert_images_into_excel(sheet, row, imgs):col = 3  # 从 C 列开始for img in imgs:# 生成正确的列名col_letter = openpyxl.utils.get_column_letter(col)img_path = f"{col_letter}{row}"img_obj = ExcelImage(img)sheet.add_image(img_obj, img_path)col += 1# fix_pic_file 功能:处理图片文件,包括压缩和 Base64 编码。 参数:image_path (str): 图片文件的路径。
# 逻辑:
#    判断文件大小,如果超过 1MB,则调用 compress_image 方法进行压缩。
#    打开图片文件并读取其内容,进行 Base64 编码。
#    去掉 Base64 编码头部(如果存在)。
#    返回 Base64 编码字符串和图片对象。def fix_pic_file(image_path):# 判断文件大小file_size_kb = os.path.getsize(image_path) / 1024if file_size_kb > 1024:  # 1MB# 压缩图片img = compress_image(image_path)else:img = Image.open(image_path)with open(image_path, "rb") as image_file:encoded_string = base64.b64encode(image_file.read()).decode('utf-8')# 去掉 base64 编码头部if encoded_string.startswith('data:image/png;base64,'):encoded_string = encoded_string.replace('data:image/png;base64,', '')elif encoded_string.startswith('data:image/jpg;base64,'):encoded_string = encoded_string.replace('data:image/jpg;base64,', '')print(f'fix_pic_file 方法调用完成!文件: {os.path.basename(image_path)}')return encoded_string, img# 功能:将 PDF 文件转换为图片文件。 参数:pdf_path (str): PDF 文件的路径   ;  output_folder (str): 输出图片文件的目录。
# 逻辑:
#     打开 PDF 文件。
#     遍历每一页,将其转换为图片并保存到指定目录。
#     返回图片文件路径列表和 PDF 文件的基本名称。def convert_pdf_to_image(pdf_path, output_folder):# 打开 PDF 文件pdf_document = fitz.open(pdf_path)base_name = os.path.splitext(os.path.basename(pdf_path))[0]images = []for page_num in range(len(pdf_document)):page = pdf_document.load_page(page_num)pix = page.get_pixmap()img_path = os.path.join(output_folder, f"{base_name}_page_{page_num + 1}.png")pix.save(img_path)images.append(img_path)return images, base_name# 功能:批量处理指定文件夹中的图片和 PDF 文件。 参数:folder_path (str): 包含图片和 PDF 文件的文件夹路径  ;  excel_file_path (str): Excel 文件的路径。# 逻辑:获取文件夹中所有符合条件的文件(PNG、JPG、JPEG、PDF)。
# 遍历每个文件:
# 如果是 PDF 文件,调用 convert_pdf_to_image 方法将其转换为图片。
#    对每张图片调用 fix_pic_file 方法进行处理,获取 Base64 编码字符串和图片对象。
#    调用 post_url 方法将处理结果写入 Excel 文件。
# 如果是图片文件,直接调用 fix_pic_file 和 post_url 方法进行处理。def batch_process(folder_path, excel_file_path):files = [f for f in os.listdir(folder_path) if f.endswith(('.png', '.jpg', '.jpeg', '.pdf'))]for file in files:file_path = os.path.join(folder_path, file)if file.endswith('.pdf'):# 转换 PDF 为图片images, base_name = convert_pdf_to_image(file_path, folder_path)base64_strings = []compressed_imgs = []for img_path in images:base64_string, img = fix_pic_file(img_path)base64_strings.append(base64_string)compressed_imgs.append(img)post_url(base64_strings, excel_file_path, base_name, compressed_imgs)else:base64_string, img = fix_pic_file(file_path)post_url([base64_string], excel_file_path, file, [img])# 批量处理指定文件夹中的 图片和 PDF 文件,通过 OCR API 获取文本内容,并将结果写入 Excel 文件中(同时,处理过程中会对图片进行压缩和 Base64 编码)# 1、指定文件夹路径和 Excel 文件路径。
# 2、如果 Excel 文件不存在,创建一个新的 Excel 文件。
# 3、调用 batch_process 方法批量处理文件夹中的图片和 PDF 文件。
# 4、打印处理结束信息。if __name__ == '__main__':# 指定文件夹路径和 Excel 文件路径folder_path = 'D:\\ssproject\\ssprice'excel_file_path = 'D:\\ssproject\\ssprice\\excel.xlsx'# 创建 Excel 文件(如果不存在)if not os.path.exists(excel_file_path):workbook = Workbook()workbook.save(excel_file_path)# 批量处理图片batch_process(folder_path, excel_file_path)print('处理结束!')

六、总结

        当然,以上只是根据实际情况简单实现了一下后端数据录入的工作,要实现数据闭环还需要匹配对应的文件上传功能以及前端页面展示,在此不给予展示实现过程。

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

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

相关文章

MySQL用法---MySQL Workbench创建数据库和表

1. 连接数据库 打开软件&#xff0c;点击左下角卡片&#xff0c;输入设置的数据库密码&#xff0c;勾选单选框 2. 了解主页面的组成部分 3. 创建数据库 先点击工具栏的创建按钮 再输入数据库名称 点击 Apply 创建 4. 创建数据表 展开数据库&#xff0c;在Tables上右键&…

Leecode刷题C语言之可以被进一步捕获的棋子数

执行结果:通过 执行用时和内存消耗如下&#xff1a; 代码如下&#xff1a; int numRookCaptures(char** board, int boardSize, int* boardColSize) {int cnt 0, st 0, ed 0;int dx[4] {0, 1, 0, -1};int dy[4] {1, 0, -1, 0};for (int i 0; i < 8; i) {for (int j…

Python、R循环神经网络RNN、指数平滑ETS、ARIMA模型预测网络流量、ATM机取款、旅游需求时间序列数据...

全文链接&#xff1a;https://tecdat.cn/?p38496 分析师&#xff1a;Pengyuan Wen 在当今经济研究与商业决策领域&#xff0c;精准的时间序列预测具有极为关键的意义。社会消费品零售总额作为反映人民消费水平以及国民经济状况的核心指标&#xff0c;其发展趋势的精准把握对中…

第二篇:k8s工作流程

我们来看通过deployment部署pod的常规流程&#xff1a; kubectl向apiserver发送部署请求&#xff08;例如使用 kubectl create -f deployment.yml&#xff09;apiserver将 Deployment 持久化到etcd&#xff1b;etcd与apiserver进行一次http通信。controller manager通过watch a…

DevOps系统设计和技术选型

命名是一件痛苦的事情&#xff0c;除非你不想要一个好名字。 我正在做的这个管理系统叫什么合适&#xff0c;或者是什么类型的系统&#xff0c;想去想来不知所措&#xff0c;后来想想这么小的东西纠结什么&#xff0c;先从小的细节一点点来&#xff0c;能用就行&#xff0c;就用…

大模型基础环境部署之二:安装CUDA(详细实操版)

在完成 Nvidia 驱动的安装之后&#xff0c;接下来进行 CUDA 的安装以及版本确认。 一、安装 CUDA 1、运行 CUDA 安装程序 /mnt/data/Nvidia/CUDA# ./cuda_12.1.0_530.30.02_linux.run在安装过程中&#xff0c;确保不要选择安装驱动&#xff0c;以免覆盖已经安装好的 Nvidia …

在 Ansys Mechanical 中使用命名选择

介绍 在设置模型时&#xff0c;我通常会使用几何选择选项来确定边界条件、载荷、材料属性和模型的其他重要方面的范围。 这对于没有很多面或身体的小模型来说已经足够好了。随着我的模型变得越来越大和越来越复杂&#xff0c;单击确定边界条件和材料属性的范围变得很乏味&…

【Elasticsearch】实现气象数据存储与查询系统

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

精密制造中智能扭矩系统的关键作用

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。】 电子、半导体、医疗器械等精密制造行业对于产品质量和性能的要求达到了前所未有的高度。在这一背景下&#xff0c;智能扭矩系统成为了确保零部件装配高精度和一致性的关键要素&#xff0c;对提升…

使用mtools搭建MongoDB复制集和分片集群

mtools介绍 mtools是一套基于Python实现的MongoDB工具集&#xff0c;其包括MongoDB日志分析、报表生成及简易的数据库安装等功能。它由MongoDB原生的工程师单独发起并做开源维护&#xff0c;目前已经有大量的使用者。 mtools所包含的一些常用组件如下&#xff1a; mlaunch支…

软件测试最新项目合集【商城、外卖、银行、金融等等.......】

项目一&#xff1a;ShopNC商城 项目概况&#xff1a; ShopNC商城是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城&#xff0c;系统PC后台是基于ThinkPHP MVC构架开发的跨…

Artec Leo 3D扫描仪 革新家具行业的数字化展示【沪敖3D】

随着科技的飞速进步&#xff0c;三维扫描技术已被广泛应用于包括家居行业在内的多个行业。面对现代消费者对家居产品日益增长的个性化和多样化需求&#xff0c;传统的家居设计和展示方法已难以满足市场需求。三维扫描技术的出现&#xff0c;为家居行业带来了新的发展机遇&#…

爬虫项目基础知识详解

文章目录 Python爬虫项目基础知识一、爬虫与数据分析1.1 Python中的requests库Requests 库的安装Requests 库的 get() 方法爬取网页的通用代码框架HTTP 协议及 Requests 库方法Requests 库主要方法解析 1.2 python中的json库1.3 xpath学习之python中lxml库html了解html结构html…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

棋牌项目Go的日志打印问题

棋牌项目Go的日志打印问题 项目使用 go work 管理模块 github.com/spf13/viper 通过 application.yml 加载配置 $ tree . ├── README.md ├── common │ ├── application.yml │ ├── config │ │ └── config.go │ ├── go.mod │ ├── go.su…

【Linux操作系统】多线程控制(创建,等待,终止、分离)

目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数&#xff08;pthread&#xff09;查看和理解线程id主线程与其他线程之间的关系 三、线程等待&#xff08;回收&#xff09;四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…

小程序 —— Day1

组件 — view和scroll-view view 类似于HTML中的div&#xff0c;是一个块级元素 案例&#xff1a;通过view组件实现页面的基础布局 scroll-view 可滚动的视图区域&#xff0c;用来实现滚动列表效果 案例&#xff1a;实现纵向滚动效果 scroll-x属性&#xff1a;允许横向滚动…

快速构建NLP理论知识体系

NLP理论知识体系 一句话解释NLPNLP模型及原理简述1、Rag 一句话解释NLP 如果我们要实现机器翻译、情感分析、问答系统、文本摘要、聊天机器人、构造智能化的辅助文件填写模板&#xff0c;NLP可以通过现成的模型对输入的语音、文字、图片进行处理&#xff08;分词、标词性、去停…

Kafka的消费消息是如何传递的?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka的消费消息是如何传递的&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka的消费消息是如何传递的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka 的消息传递是通过 消费者&#xff08…

shell脚本实战案例

文章目录 实战第一坑功能说明脚本实现 实战第一坑 实战第一坑&#xff1a;在Windows系统写了一个脚本&#xff0c;比如上面&#xff0c;随后上传到服务&#xff0c;执行会报错 原因&#xff1a; 解决方案&#xff1a;在linux系统touch文件&#xff0c;并通过vim添加内容&…