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

access 网站后台汕头自助建站

access 网站后台,汕头自助建站,阿里云虚拟主机与网站吗,丹阳官方网站建站一、问题的由来 最近,有网友说,他一天要处理很多100多份订单截图,提取其中的发货单号、车号、净重、品种、出厂日期等,并存入到Excel文件当中。普通的人工录入太慢,电脑OCR识图又不太准确,还要来回复制粘贴…

一、问题的由来

最近,有网友说,他一天要处理很多100多份订单截图,提取其中的发货单号、车号、净重、品种、出厂日期等,并存入到Excel文件当中。普通的人工录入太慢,电脑OCR识图又不太准确,还要来回复制粘贴,非常的麻烦,而且耗时耗力。因此,他想编写一个批量处理工具,实现批量化操作订单截图,自动提取指定信息,然后可以转到Excel里。

问题的由来

二、问题的分析

这个问题与提取发票信息有点儿像,不过发票一般都是pdf格式,而且很清晰,这是图片,一般都是手机拍摄的,不仅不规则,有时还不太清晰,所以要准确提取难度有点儿大。我想了一下,提供了两套解决的思路。

1. 用智能体的方法

我们进入豆包,在左侧菜单栏中,点击【更多】,找到【AI智能体】,再点击右上角的【创建智能体】,

创建智能体

然后,在设定描述中输入相关指令,并为这个智能体设计一个名称,可以通过AI一键生成。

录入指令

完成智能体编写后,提交豆包审核,审核通过后,我们就可以通过提交图片来实现相关信息的提交了。不过这种方法,一次只能提交一张图片,效果如下所示:

智能体识别相关信息

但这种方法的好处是可以在手机上提交识别,速度还挺快的,准确率也很好,而且操作免费。

2. Python编程法

另一种方法有点儿复杂,但可以实现批量操作,无人职守就可以完成提取图片信息的任务,但是就得消耗豆包API的额度,不过貌似价格不是很高。在编程前,可以去申请一个豆包api,申请地址是:

火山引擎-你的AI云​www.volcengine.com/

申请完之后,在控制台找到多模态处理的AI样例代码如下:

import os
from openai import OpenAI# 初始化客户端
client = OpenAI(base_url="https://ark.cn-beijing.volces.com/api/v3",api_key="<API_KEY>"  # 这里修改了一下,直接为变量赋值,输入你的API_KEY即可
)response = client.chat.completions.create(model="doubao-seed-1-6-250615",  #豆包的多模态处理模型。messages=[{"role": "user","content": [{"type": "image_url","image_url": {"url": "https://wx3.sinaimg.cn/orj480/7ffa58d5ly1i44lggggjxj20k00zkjse.jpg"},},{"type": "text", "text": "提取图片中的文字信息,其它不要显示。"},],}],
)# 提取content内容
content = response.choices[0].message.content
print("提取的内容:")
print(content)

根据上面的样例代码,我们借助Python中的Tkinter框架,编写了一款图片信息提取工具,实现包括图片的导入、预览、信息提取、复制等功能,基本的样式如下:

图片识别工具

软件编写过程中处理了底部按钮放大后变形,图片预览框忽大忽小等问题,为信息提取和图片预览区还设置了LabelFrame,便于操作。

软件可以自动检测本地是否加载API Key,如果没有加载,就会弹窗提醒输入。如果已经加载API,就会提供已经加载API。

软件提取信息,一方面会显示在界面中部右侧,中间用制表位隔开,生成完,点击复制信息就可以粘贴到Excel当中。通过打开目录,还可以查看已经写入本地的信息。

3. 代码展示

import os
import json
from tkinter import Tk, Label, Entry, filedialog, messagebox, StringVar, END, Button, LEFT,LabelFrame,Frame, Toplevel
from tkinter.scrolledtext import ScrolledText
from tkinter import PhotoImage, font
import threading
import base64
import pyperclip
from pathlib import Path
from openai import OpenAI
from PIL import Image, ImageTkclass ImageEssayEvaluator:def __init__(self, root):self.root = rootself.root.title("图片信息提取工具 | By Gordon")self.setup_ui()self.api = Noneself.output_dir = os.path.join(os.getcwd(), "识别结果")os.makedirs(self.output_dir, exist_ok=True)self.current_scale = 1.0  # Track current zoom scaleself.image_files = []  # List to store multiple image pathsself.current_image_index = 0  # Track current image indexjson_filename = "config.json"if not os.path.exists(json_filename):with open(json_filename, "w") as json_file:json.dump({"api_key": self.api}, json_file)print("JSON 文件已创建。")else:with open(json_filename, "r") as json_file:data = json.load(json_file)self.api = data.get("api")if self.api is None:self.show_settings()self.update_api_button_text()def update_api_button_text(self):"""根据API状态更新按钮文本"""if self.api:self.api_button.config(text="已加载API")else:self.api_button.config(text="设置API")def setup_ui(self):self.info_var = StringVar()self.info_var.set("Tip: 请导入图片,识别结果将显示在下方文本框")Label(self.root, textvariable=self.info_var, font=("微软雅黑", 12)).pack(pady=5)frame = Frame(self.root)frame.pack(padx=6)Label(frame, text="图片路径:", font=("微软雅黑", 12)).pack(side='left')self.image_path_entry = Entry(frame, width=60, font=("微软雅黑", 12))self.image_path_entry.pack(side=LEFT, padx=5, pady=5)self.api_button = Button(frame, text="设置API", font=("微软雅黑", 12), command=self.show_settings)self.api_button.pack()# Create a frame for the image and text displaymain_frame = Frame(self.root)main_frame.pack(padx=5, pady=5)# Left Frame for Image Preview (no fixed height)#self.preview_frame = Frame(main_frame, width=500)self.preview_frame = LabelFrame(main_frame, text="  预览图片文件",font=("微软雅黑", 12), width=400, height=460, padx=1, pady=1)self.preview_frame.grid(row=0, column=0, padx=10, pady=10)self.preview_frame.pack_propagate(False)# Image preview labelself.image_label = Label(self.preview_frame)self.image_label.pack(padx=10, pady=10)# Frame for zoom and navigation buttonsbutton_frame = Frame(self.preview_frame)button_frame.pack(side='bottom',pady=5)# Zoom buttons (Up and Down) and Navigation buttons (Previous and Next)self.zoom_in_button = Button(button_frame, text="放大", font=("微软雅黑", 12), command=self.zoom_in)self.zoom_in_button.pack(side=LEFT, padx=5)self.zoom_out_button = Button(button_frame, text="缩小", font=("微软雅黑", 12), command=self.zoom_out)self.zoom_out_button.pack(side=LEFT, padx=5)self.prev_button = Button(button_frame, text="上一张", font=("微软雅黑", 12), command=self.previous_image)self.prev_button.pack(side=LEFT, padx=5)self.next_button = Button(button_frame, text="下一张", font=("微软雅黑", 12), command=self.next_image)self.next_button.pack(side=LEFT, padx=5)# Right Frame for Text Display#self.text_frame = Frame(main_frame, width=400, height=300)self.text_frame = LabelFrame(main_frame, text="  提取信息显示 ", font=("微软雅黑", 12), width=400, height=300, padx=1, pady=1)self.text_frame.grid(row=0, column=1, padx=10, pady=10)# Text display areaself.text_display = ScrolledText(self.text_frame, width=50, height=20, font=("微软雅黑", 12))self.text_display.pack(padx=5, pady=5)button_frame = Frame(self.root)button_frame.pack(expand=True)# Other buttonsButton(button_frame, text="导入图片", font=("微软雅黑", 12), command=self.load_image).pack(side="left", padx=90, pady=10)Button(button_frame, text="提取信息", font=("微软雅黑", 12), command=self.start_evaluation).pack(side="left", padx=60, pady=10)Button(button_frame, text="打开目录", font=("微软雅黑", 12), command=self.open_output_dir).pack(side="left", padx=60, pady=10)Button(button_frame, text="复制信息", font=("微软雅黑", 12), command=self.copy_info).pack(side="left", padx=60, pady=10)def show_settings(self):self.settings_window = Toplevel(self.root)self.settings_window.attributes('-topmost', True)self.settings_window.title("豆包 API设置")Label(self.settings_window, text="请把kimi的API放在这里,使用ctrl+V:").pack(pady=5)self.api_var = StringVar()self.entry = Entry(self.settings_window, textvariable=self.api_var, width=30, font=("微软雅黑", 12))self.entry.pack()confirm_button = Button(self.settings_window, text="确认", command=lambda: self.apply_settings())confirm_button.pack(pady=10)screen_width = self.settings_window.winfo_screenwidth()screen_height = self.settings_window.winfo_screenheight()self.settings_window.update_idletasks()window_width = self.settings_window.winfo_width()window_height = self.settings_window.winfo_height()x_position = (screen_width - window_width) // 2y_position = (screen_height - window_height) // 2self.settings_window.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")def apply_settings(self):new_time = self.api_var.get()self.api = new_time.strip()data = {'api': self.api}with open('config.json', 'w+') as f:json.dump(data, f, indent=4)self.settings_window.destroy()def copy_info(self):pyperclip.copy(self.text_display.get(1.0, END))def load_image(self): if len(str(self.api)) < 10:messagebox.showwarning("警告!", "API设置不正确或者没有")self.show_settings()return# 选择导入方式choice = messagebox.askquestion("选择导入方式", "是:加载多个图片文件\n否:加载整个文件夹中的图片")image_paths = []if choice == 'yes':# 导入多个图片文件file_paths = filedialog.askopenfilenames(title="选择图片",filetypes=[("图片文件", "*.jpg;*.png;*.jpeg;*.bmp")])if file_paths:image_paths = [fp.replace("\\", "/") for fp in file_paths]# 显示第一张图片路径到 entryself.image_path_entry.delete(0, END)self.image_path_entry.insert(0, image_paths[0])elif choice == 'no':# 导入整个文件夹中的图片folder_path = filedialog.askdirectory(title="选择文件夹")if folder_path:folder_path = folder_path.replace("\\", "/")  # 替换为统一的路径分隔符for fname in os.listdir(folder_path):if fname.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):image_path = os.path.join(folder_path, fname).replace("\\", "/")image_paths.append(image_path)image_paths.sort()# 设置 entry 显示文件夹路径self.image_path_entry.delete(0, END)self.image_path_entry.insert(0, folder_path)# 若成功导入图片路径if image_paths:self.image_files = image_pathsself.current_image_index = 0self.current_scale = 1.0  # Reset zoom# 显示状态信息self.info_var.set(f"已加载图片: {os.path.basename(self.image_files[self.current_image_index])} "f"({self.current_image_index + 1}/{len(self.image_files)})")self.display_image(self.image_files[self.current_image_index])self.update_navigation_buttons()else:self.info_var.set("未选择任何图片")def update_navigation_buttons(self):"""Enable or disable navigation buttons based on image list and current index"""if len(self.image_files) > 1:self.prev_button.config(state="normal" if self.current_image_index > 0 else "disabled")self.next_button.config(state="normal" if self.current_image_index < len(self.image_files) - 1 else "disabled")else:self.prev_button.config(state="disabled")self.next_button.config(state="disabled")def previous_image(self):if self.current_image_index > 0:self.current_image_index -= 1self.image_path_entry.delete(0, END)self.image_path_entry.insert(0, self.image_files[self.current_image_index])self.info_var.set(f"已加载图片: {os.path.basename(self.image_files[self.current_image_index])} ({self.current_image_index + 1}/{len(self.image_files)})")self.current_scale = 1.0  # Reset zoom scaleself.display_image(self.image_files[self.current_image_index])self.update_navigation_buttons()def next_image(self):if self.current_image_index < len(self.image_files) - 1:self.current_image_index += 1self.image_path_entry.delete(0, END)self.image_path_entry.insert(0, self.image_files[self.current_image_index])self.info_var.set(f"已加载图片: {os.path.basename(self.image_files[self.current_image_index])} ({self.current_image_index + 1}/{len(self.image_files)})")self.current_scale = 1.0  # Reset zoom scaleself.display_image(self.image_files[self.current_image_index])self.update_navigation_buttons()def display_image(self, image_path):# Open the image and display it as previewimg = Image.open(image_path)# Estimate text area height (15 lines of font "微软雅黑" size 12)text_font = font.Font(family="微软雅黑", size=12)line_height = text_font.metrics("linespace")target_height = int(line_height * 15 * self.current_scale)# Calculate width based on aspect ratiooriginal_width, original_height = img.sizetarget_width = int(target_height * original_width / original_height)img = img.resize((target_width, target_height), Image.Resampling.LANCZOS)self.image_preview = ImageTk.PhotoImage(img)self.image_label.config(image=self.image_preview)def zoom_in(self):# Increase image size by 10%self.current_scale *= 1.1self.update_image()def zoom_out(self):# Decrease image size by 10%self.current_scale *= 0.9self.update_image()def update_image(self):if not self.image_files or self.current_image_index >= len(self.image_files):messagebox.showwarning("警告", "请先加载图片")returnimage_path = self.image_files[self.current_image_index]try:img = Image.open(image_path)# Estimate text area height (15 lines of font "微软雅黑" size 12)text_font = font.Font(family="微软雅黑", size=12)line_height = text_font.metrics("linespace")target_height = int(line_height * 15 * self.current_scale)# Calculate width based on aspect ratiooriginal_width, original_height = img.sizetarget_width = int(target_height * original_width / original_height)img = img.resize((target_width, target_height), Image.Resampling.LANCZOS)self.image_preview = ImageTk.PhotoImage(img)self.image_label.config(image=self.image_preview)# 更新路径栏显示当前图片(可选)self.image_path_entry.delete(0, END)self.image_path_entry.insert(0, image_path)except Exception as e:messagebox.showerror("错误", f"无法加载图片:{e}")def start_evaluation(self):threading.Thread(target=self.evaluate_essay).start()def evaluate_essay(self):if not self.image_files:messagebox.showerror("错误", "请先导入图片文件或文件夹!")returnself.info_var.set("正在提取内容,请稍候...")try:for file in self.image_files:result = self.chat_doubao(file)base_name = os.path.splitext(os.path.basename(file))[0]output_path = os.path.join(self.output_dir, f"{base_name}.txt")with open(output_path, "a+", encoding="utf-8") as f:f.write(result)self.info_var.set("提取完成!")except Exception as e:messagebox.showerror("错误", f"提取失败: {e}")self.info_var.set("提取失败,请重试")def get_order(self):with open("order.txt","r",encoding="utf-8") as f:order = f.read().strip()return orderdef image_to_base64(self,image_path):# 获取图片文件的MIME类型ext = os.path.splitext(image_path)[1].lower()mime_type = f"image/{ext[1:]}" if ext in ['.jpg', '.jpeg', '.png', '.gif'] else "image/jpeg"with open(image_path, "rb") as image_file:# 读取文件内容并进行Base64编码base64_data = base64.b64encode(image_file.read()).decode('utf-8')# 返回完整的data URI格式return f"data:{mime_type};base64,{base64_data}"def chat_doubao(self,local_image_path):# 初始化客户端client = OpenAI(base_url="https://ark.cn-beijing.volces.com/api/v3",api_key="<YOUR API KEY>"  # 这里要输入自己的API)try:# 转换本地图片为Base64编码image_data = self.image_to_base64(local_image_path)# 调用API处理图片response = client.chat.completions.create(model="doubao-seed-1-6-250615",messages=[{"role": "user","content": [{"type": "image_url","image_url": {"url": image_data  # 使用Base64编码的本地图片数据},},{"type": "text", "text": self.get_order()},],}])# 提取并打印内容content = response.choices[0].message.contentself.text_display.insert(END, f"{content}\n")self.text_display.see(END)# 更新预览图片显示self.display_image(local_image_path)# 更新顶部路径栏显示self.image_path_entry.delete(0, END)self.image_path_entry.insert(0, local_image_path)except FileNotFoundError:self.text_display.insert('1.0',f"错误:找不到图片文件 '{local_image_path}'")except Exception as e:print(f"处理过程中发生错误:{str(e)}")return contentdef open_output_dir(self):os.startfile(self.output_dir)if __name__ == "__main__":root = Tk()app = ImageEssayEvaluator(root)root.mainloop()

上面程序中,为了实现本地图片的读取,我们通过image_to_base64这个函数进行图像信息的转化,如果不转化,我们就得从网址里获取,有可能需要网络存储桶,不仅不方便,也会延迟速度。

三、学后总结

1. 人工智能性能不断提升,未来对于多模态数据如:图片、音频和视频的处理就变得非常方便。借用Python批量处理的特点,我们可以很好地实现指定文本的提取和保存。

2. 此工具还可以拓展。把指令文件order.txt修改一下,通过修改指令可以实现发票信息提取、作文批改等功能。如果未来支持音频和视频,也可以这么操作。

http://www.dtcms.com/a/490103.html

相关文章:

  • 从图纸到三维模型:智能装配指导的突破之路
  • 「JMM+Java锁+AQS」 知识图谱
  • 【广州公共资源交易-注册安全分析报告-无验证方式导致安全隐患】
  • C++ 学习日记
  • 晶晨S905L3SB芯片_安卓9.0_高安版_支持外置WIFI_线刷固件包
  • 4G5G 移动代理实战:什么时候必须用移动 IP?
  • 【OpenHarmony】传感器轻量级服务模块架构
  • 面向服务架构(SOA)模式全解析:设计、实践与价值
  • HTML 零基础入门到实战:从骨架到页面的完整指南
  • 【Java EE进阶 --- SpringBoot】Mybatis操作数据库(进阶)
  • 成都海鸥手表网站crm系统的销售管理功能包括
  • 『 QT 』QT信号机制深度解析
  • stp,rstp,mstp的区别
  • 海外盲盒APP开发:从“未知”到“精准”的用户体验革命
  • 网站建设yuanmus站长工具seo综合查询5g
  • 使用 IntelliJ IDEA 结合 DBeaver 连接 MySQL 数据库并实现数据增删查改的详细步骤:
  • 零知IDE——基于STM32F407VET6和ESP-01的SHT2X温湿度监测与云传输系统
  • 记一次生产服务器磁盘I/O性能瓶颈与负载过高分析与处理
  • MEMS加速度计深度解析:从智能手机到结构健康监测
  • LLMs-from-scratch(dataloader)
  • 兴义哪有做网站婚纱影楼网站源码
  • C++_394_tableWidget控件,两种模式,1、行显示模式 2、网格显示模式
  • MyBatis拦截器实现saas租户同库同表数据隔离
  • 求n以内最大的k个素数以及它们的和
  • 手机 网站建设在线自动取名网站怎么做
  • PHP电动汽车租赁管理系统-计算机毕业设计源码35824
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十二)Python3编程之python基础
  • 大型网站怎样做优化PHP营销推广的主要方法
  • 【泛3C篇】AI深度学习在手机前/后摄像头外观缺陷检测应用方案
  • 建设网站需要申请网站建设与管理专业好找工作吗