成人欧美一区二区三区的电影,日韩一级一欧美一级国产,国产成人国拍亚洲精品,无码人妻精品一区二区三区毛片,伊人久久无码大香线蕉综合

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

Python自動(dòng)化:圖片轉(zhuǎn)Excel終極方案,多模態(tài)大模型+Python ,掃描件→可編輯Excel只需3秒!

admin
2025年9月27日 9:1 本文熱度 756

將圖片轉(zhuǎn)換為表格一直是我們數(shù)海丹心社區(qū)群里備受關(guān)注的話(huà)題,也是討論度最高的話(huà)題之一,一直以來(lái)大佬們也是試了各種方式,都沒(méi)有很好的解決這個(gè)難題,最近,隨著我對(duì)大語(yǔ)言模型和多模態(tài)模型的深入研究,最終很好的解決了這個(gè)問(wèn)題。

我們常常遇到需要將掃描的表格、截圖或照片中的數(shù)據(jù)轉(zhuǎn)換為Excel表格進(jìn)行進(jìn)一步處理的情況。然而,傳統(tǒng)的OCR工具如uniocr雖然能夠識(shí)別文字,但精度不高,且難以還原表格結(jié)構(gòu)。而像paddleocr或微信ocr這樣的工具,雖然能夠識(shí)別文字,卻無(wú)法將識(shí)別結(jié)果還原成表格格式,這無(wú)疑增加了我們的工作量。

隨著大語(yǔ)言模型,尤其是多模態(tài)大語(yǔ)言模型的快速發(fā)展,這一問(wèn)題終于迎來(lái)了解決方案。阿里云推出的Qwen-VL系列模型,不僅能夠識(shí)別圖片中的文字,還能理解其結(jié)構(gòu),實(shí)現(xiàn)圖片到Excel的直接轉(zhuǎn)換,并且成本極低。

Qwen-VL大模型:表格識(shí)別的新革命

Qwen-VL系列模型是專(zhuān)為多模態(tài)任務(wù)設(shè)計(jì)的大模型,它能夠處理包括表格、文檔、試題、手寫(xiě)體在內(nèi)的多種圖像內(nèi)容。與傳統(tǒng)OCR工具相比,Qwen-VL在表格識(shí)別方面具有顯著優(yōu)勢(shì):

  • 高精度識(shí)別:不僅識(shí)別文字,還能理解表格結(jié)構(gòu),準(zhǔn)確還原合并單元格和多級(jí)表頭。

  • 低成本:使用成本遠(yuǎn)低于傳統(tǒng)OCR服務(wù),個(gè)人和小團(tuán)隊(duì)也能輕松負(fù)擔(dān)。

  • 易于集成:提供API接口,開(kāi)發(fā)者可以輕松集成到自己的應(yīng)用中。

  • 多功能支持:支持單圖片和批量圖片識(shí)別

實(shí)現(xiàn)原理:從圖片到Excel

Qwen-VL模型通過(guò)分析圖片內(nèi)容,理解其中的表格結(jié)構(gòu),然后將識(shí)別結(jié)果輸出為CSV格式,最后轉(zhuǎn)換為Excel文件。這一過(guò)程涉及到圖像處理、自然語(yǔ)言理解和文本生成等多個(gè)技術(shù)領(lǐng)域。

操作簡(jiǎn)便:一鍵轉(zhuǎn)換,省時(shí)省力

為了讓大家能夠更方便地使用Qwen-VL模型,我們開(kāi)發(fā)了一個(gè)簡(jiǎn)單的GUI工具,只需幾個(gè)步驟就能完成圖片到Excel的轉(zhuǎn)換:

獲取API Key:訪(fǎng)問(wèn)阿里云幫助文檔獲取您的API Key【https://help.aliyun.com/zh/model-studio/get-api-key?】。

  1. 選擇圖片:通過(guò)GUI選擇需要轉(zhuǎn)換的圖片文件。

  2. 指定輸出路徑:設(shè)置轉(zhuǎn)換后的Excel文件保存路徑。

  3. 一鍵轉(zhuǎn)換:點(diǎn)擊“開(kāi)始識(shí)別”按鈕,等待轉(zhuǎn)換完成。

示例代碼

import osimport base64import tkinter as tkfrom tkinter import ttk, filedialog, messageboxfrom openpyxl import Workbookimport csvimport time# ========== GUI 主程序 ==========class OCRApp:    def __init__(self, root):        self.root = root        self.root.title("Qwen-VL OCR 表格識(shí)別工具 v3.0")        self.root.geometry("700x500")        self.root.resizable(FalseFalse)        self.root.configure(bg="#f0f0f0")        # 設(shè)置樣式        style = ttk.Style()        style.theme_use('clam')        style.configure("TButton", font=("微軟雅黑"10), padding=5)        style.configure("TLabel", font=("微軟雅黑"10), background="#f0f0f0")        style.configure("TEntry", font=("微軟雅黑"10), padding=3)        style.configure("TProgressbar", thickness=8)        style.configure("Green.TButton", background="#2ecc71",                        foreground="white", font=("微軟雅黑"12"bold"))        style.configure("Radio.TRadiobutton",                        background="#f0f0f0", font=("微軟雅黑"10))        # 標(biāo)題        title_label = tk.Label(root, text="?? Qwen-VL OCR 表格識(shí)別工具",                               font=("微軟雅黑"14"bold"), bg="#f0f0f0", fg="#2c3e50")        title_label.pack(pady=10)        # 處理模式選擇        frame_mode = tk.Frame(root, bg="#f0f0f0")        frame_mode.pack(pady=5, fill="x", padx=20)        tk.Label(frame_mode, text="?? 處理模式:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.process_mode = tk.StringVar(value="single")        ttk.Radiobutton(frame_mode, text="單文件處理", variable=self.process_mode,                        value="single", style="Radio.TRadiobutton",                        command=self.toggle_process_mode).pack(side="left", padx=10)        ttk.Radiobutton(frame_mode, text="批量文件夾處理", variable=self.process_mode,                        value="batch", style="Radio.TRadiobutton",                        command=self.toggle_process_mode).pack(side="left")        # API Key 輸入框        frame_api = tk.Frame(root, bg="#f0f0f0")        frame_api.pack(pady=5, fill="x", padx=20)        tk.Label(frame_api, text="?? API Key:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.api_key_entry = tk.Entry(            frame_api, width=40, show="*", font=("Consolas"10))        self.api_key_entry.pack(side="left", padx=10, expand=True, fill="x")        # 單文件處理 - 圖片選擇        self.frame_single_image = tk.Frame(root, bg="#f0f0f0")        self.frame_single_image.pack(pady=5, fill="x", padx=20)        tk.Label(self.frame_single_image, text="??? 圖片路徑:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.image_path_var = tk.StringVar()        self.image_entry = tk.Entry(self.frame_single_image, textvariable=self.image_path_var, width=30, font=(            "Consolas"10), state='readonly')        self.image_entry.pack(side="left", padx=5, expand=True, fill="x")        ttk.Button(self.frame_single_image, text="?? 選擇圖片",                   command=self.select_image).pack(side="left", padx=5)        # 單文件處理 - 輸出路徑        self.frame_single_output = tk.Frame(root, bg="#f0f0f0")        self.frame_single_output.pack(pady=5, fill="x", padx=20)        tk.Label(self.frame_single_output, text="?? 輸出路徑:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.output_path_var = tk.StringVar()        self.output_entry = tk.Entry(self.frame_single_output, textvariable=self.output_path_var, width=30, font=(            "Consolas"10), state='readonly')        self.output_entry.pack(side="left", padx=5, expand=True, fill="x")        ttk.Button(self.frame_single_output, text="?? 選擇輸出",                   command=self.select_output).pack(side="left", padx=5)        # 批量處理 - 文件夾選擇        self.frame_batch_folder = tk.Frame(root, bg="#f0f0f0")        self.frame_batch_folder.pack(pady=5, fill="x", padx=20)        self.frame_batch_folder.pack_forget()  # 默認(rèn)隱藏        tk.Label(self.frame_batch_folder, text="?? 圖片文件夾:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.folder_path_var = tk.StringVar()        self.folder_entry = tk.Entry(self.frame_batch_folder, textvariable=self.folder_path_var, width=30, font=(            "Consolas"10), state='readonly')        self.folder_entry.pack(side="left", padx=5, expand=True, fill="x")        ttk.Button(self.frame_batch_folder, text="?? 選擇文件夾",                   command=self.select_folder).pack(side="left", padx=5)        # 批量處理 - 輸出文件夾        self.frame_batch_output = tk.Frame(root, bg="#f0f0f0")        self.frame_batch_output.pack(pady=5, fill="x", padx=20)        self.frame_batch_output.pack_forget()  # 默認(rèn)隱藏        tk.Label(self.frame_batch_output, text="?? 輸出文件夾:", font=(            "微軟雅黑"10), bg="#f0f0f0").pack(side="left")        self.batch_output_var = tk.StringVar()        self.batch_output_entry = tk.Entry(self.frame_batch_output, textvariable=self.batch_output_var, width=30, font=(            "Consolas"10), state='readonly')        self.batch_output_entry.pack(            side="left", padx=5, expand=True, fill="x")        ttk.Button(self.frame_batch_output, text="?? 選擇輸出",                   command=self.select_batch_output).pack(side="left", padx=5)        # 進(jìn)度條        frame_progress = tk.Frame(root, bg="#f0f0f0")        frame_progress.pack(pady=10, fill="x", padx=20)        self.progress_label = tk.Label(frame_progress, text="準(zhǔn)備就緒...", font=(            "微軟雅黑"9), bg="#f0f0f0", fg="#7f8c8d")        self.progress_label.pack(side="top", anchor="w")        self.progress_bar = ttk.Progressbar(            frame_progress, length=500, mode='determinate')        self.progress_bar.pack(side="top", pady=5)        # 開(kāi)始按鈕        start_frame = tk.Frame(root, bg="#f0f0f0")        start_frame.pack(pady=15)        self.start_button = ttk.Button(            start_frame, text="?? 開(kāi)始識(shí)別", command=self.start_processing, width=20)        self.start_button.pack()        self.start_button.configure(style="Green.TButton")        # 狀態(tài)標(biāo)簽        self.status_label = tk.Label(root, text="", font=(            "微軟雅黑"10), bg="#f0f0f0", fg="#2c3e50")        self.status_label.pack(pady=10)    def toggle_process_mode(self):        """切換單文件/批量處理模式的UI顯示"""        mode = self.process_mode.get()        if mode == "single":            # 顯示單文件處理UI,隱藏批量處理UI            self.frame_single_image.pack(pady=5, fill="x", padx=20)            self.frame_single_output.pack(pady=5, fill="x", padx=20)            self.frame_batch_folder.pack_forget()            self.frame_batch_output.pack_forget()        else:            # 顯示批量處理UI,隱藏單文件處理UI            self.frame_single_image.pack_forget()            self.frame_single_output.pack_forget()            self.frame_batch_folder.pack(pady=5, fill="x", padx=20)            self.frame_batch_output.pack(pady=5, fill="x", padx=20)    def select_image(self):        path = filedialog.askopenfilename(            title="選擇表格圖片",            filetypes=[("Image Files""*.png *.jpg *.jpeg *.gif *.bmp")]        )        if path:            self.image_path_var.set(path)            # 自動(dòng)設(shè)置輸出路徑            output_path = os.path.splitext(path)[0] + ".xlsx"            self.output_path_var.set(output_path)    def select_output(self):        path = filedialog.asksaveasfilename(            title="選擇輸出 Excel 文件",            defaultextension=".xlsx",            filetypes=[("Excel 文件""*.xlsx"), ("所有文件""*.*")]        )        if path:            self.output_path_var.set(path)    def select_folder(self):        path = filedialog.askdirectory(title="選擇圖片文件夾")        if path:            self.folder_path_var.set(path)            # 自動(dòng)設(shè)置輸出文件夾為圖片文件夾            self.batch_output_var.set(path)    def select_batch_output(self):        path = filedialog.askdirectory(title="選擇批量輸出文件夾")        if path:            self.batch_output_var.set(path)    def image_to_base64(self, image_path):        """將本地圖片轉(zhuǎn)為 base64 字符串"""        with open(image_path, "rb"as f:            return base64.b64encode(f.read()).decode("utf-8")    def update_progress(self, value, message):        """更新進(jìn)度條和狀態(tài)信息"""        self.progress_bar['value'] = value        self.progress_label.config(text=message)        self.root.update_idletasks()    def process_single_file(self, api_key, image_path, output_path):        """處理單個(gè)圖片文件"""        try:            # 延遲僅用于視覺(jué)效果,實(shí)際使用可刪除            time.sleep(0.2)            # 導(dǎo)入OpenAI客戶(hù)端(放在這里避免啟動(dòng)時(shí)就需要安裝)            from openai import OpenAI            # 初始化客戶(hù)端            client = OpenAI(                api_key=api_key,                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"            )            self.update_progress(30"正在讀取圖片...")            # 圖片轉(zhuǎn) base64            image_b64 = self.image_to_base64(image_path)            self.update_progress(50"正在調(diào)用模型識(shí)別...")            # 構(gòu)造多模態(tài)消息            messages = [                {                    "role""user",                    "content": [                        {                            "type""image_url",                            "image_url": {                                "url"f"data:image/png;base64,{image_b64}"                            }                        },                        {                            "type""text",                            "text": (                                "請(qǐng)識(shí)別這張圖片中的表格內(nèi)容,并以標(biāo)準(zhǔn) CSV 格式輸出,包含表頭。\n"                                "不要添加任何解釋、前綴或后綴,只輸出純 CSV 內(nèi)容。\n"                                "例如:\n姓名,年齡,城市\(zhòng)n張三,25,北京\n李四,30,上海"                            )                        }                    ]                }            ]            # 調(diào)用 OCR 模型            completion = client.chat.completions.create(                model="qwen-vl-ocr-2025-04-13",                messages=messages,                max_tokens=4096,                temperature=0.0            )            csv_text = completion.choices[0].message.content.strip()            self.update_progress(80"正在保存為 Excel...")            # 解析 CSV 文本并保存為 Excel            self.save_csv_to_excel(csv_text, output_path)            return Truef"成功處理: {os.path.basename(image_path)}"        except Exception as e:            return Falsef"處理 {os.path.basename(image_path)} 失敗: {str(e)}"    def save_csv_to_excel(self, csv_text, output_path):        """將CSV文本保存為Excel文件"""        lines = csv_text.splitlines()        if not lines:            raise ValueError("模型未返回有效數(shù)據(jù)")        # 創(chuàng)建工作簿        wb = Workbook()        ws = wb.active        # 逐行寫(xiě)入        for line in lines:            row_data = line.split(',')            ws.append(row_data)        # 保存到文件        wb.save(output_path)    def start_processing(self):        """開(kāi)始處理(單文件或批量)"""        api_key = self.api_key_entry.get().strip()        if not api_key:            messagebox.showerror("錯(cuò)誤""請(qǐng)先輸入 API Key!")            return        try:            self.update_progress(10"正在初始化...")            # 根據(jù)模式選擇處理方式            if self.process_mode.get() == "single":                # 單文件處理                image_path = self.image_path_var.get()                output_path = self.output_path_var.get()                if not image_path:                    messagebox.showerror("錯(cuò)誤""請(qǐng)選擇圖片文件!")                    return                if not output_path:                    messagebox.showerror("錯(cuò)誤""請(qǐng)選擇輸出文件路徑!")                    return                success, message = self.process_single_file(                    api_key, image_path, output_path)                self.update_progress(100, message)                self.status_label.config(text=message)                if success:                    messagebox.showinfo("成功"f"表格已保存至:\n{output_path}")            else:                # 批量處理                folder_path = self.folder_path_var.get()                output_folder = self.batch_output_var.get()                if not folder_path:                    messagebox.showerror("錯(cuò)誤""請(qǐng)選擇圖片文件夾!")                    return                if not output_folder:                    messagebox.showerror("錯(cuò)誤""請(qǐng)選擇輸出文件夾!")                    return                # 獲取文件夾中所有圖片文件                image_extensions = ('.png''.jpg''.jpeg''.gif''.bmp')                image_files = [                    f for f in os.listdir(folder_path)                    if f.lower().endswith(image_extensions)                    and os.path.isfile(os.path.join(folder_path, f))                ]                if not image_files:                    messagebox.showinfo("提示""所選文件夾中沒(méi)有圖片文件!")                    self.update_progress(0"準(zhǔn)備就緒...")                    return                total_files = len(image_files)                success_count = 0                error_messages = []                # 批量處理每個(gè)文件                for i, filename in enumerate(image_files, 1):                    try:                        # 更新總體進(jìn)度                        overall_progress = 10 + (i / total_files) * 80                        self.update_progress(overall_progress,                                             f"正在處理 {i}/{total_files}{filename}")                        image_path = os.path.join(folder_path, filename)                        # 生成輸出文件名(與圖片同名,擴(kuò)展名為xlsx)                        base_name = os.path.splitext(filename)[0]                        output_path = os.path.join(                            output_folder, f"{base_name}.xlsx")                        # 處理單個(gè)文件                        success, msg = self.process_single_file(                            api_key, image_path, output_path)                        if success:                            success_count += 1                        else:                            error_messages.append(msg)                    except Exception as e:                        error_messages.append(f"處理 {filename} 時(shí)出錯(cuò): {str(e)}")                # 處理完成                self.update_progress(                    100f"批量處理完成: {success_count}/{total_files} 成功")                self.status_label.config(                    text=f"批量處理完成: {success_count}/{total_files} 成功")                result_msg = f"批量處理完成!\n成功: {success_count} 個(gè)文件\n失敗: {total_files - success_count} 個(gè)文件"                if error_messages:                    result_msg += "\n\n錯(cuò)誤詳情:\n" + \                        "\n".join(error_messages[:5])  # 只顯示前5個(gè)錯(cuò)誤                    if len(error_messages) > 5:                        result_msg += f"\n... 還有 {len(error_messages) - 5} 個(gè)錯(cuò)誤"                messagebox.showinfo("批量處理完成", result_msg)        except Exception as e:            self.update_progress(0f"? 錯(cuò)誤: {str(e)}")            messagebox.showerror("錯(cuò)誤"f"處理失敗:\n{str(e)}")# ========== 啟動(dòng)主程序 ==========if __name__ == "__main__":    root = tk.Tk()    app = OCRApp(root)    root.mainloop()

實(shí)際效果:精準(zhǔn)還原,效率翻倍

使用Qwen-VL模型轉(zhuǎn)換后的Excel文件,不僅數(shù)據(jù)準(zhǔn)確無(wú)誤,而且表格結(jié)構(gòu)與原圖完全一致,極大地提高了工作效率。無(wú)論是財(cái)務(wù)報(bào)表、合同文件還是其他任何需要表格化的數(shù)據(jù),都能快速轉(zhuǎn)換,省去了手動(dòng)輸入的時(shí)間。

加入我們,探索更多可能

如果你對(duì)Qwen-VL模型感興趣,或者想要了解更多關(guān)于多模態(tài)大模型的應(yīng)用,歡迎加入我們的微信公眾號(hào)社區(qū)群。在這里,你可以獲取最新的模型信息、技術(shù)分享和實(shí)用工具。

    讓我們共同期待,隨著技術(shù)的不斷進(jìn)步,未來(lái)會(huì)有更多像Qwen-VL這樣的模型出現(xiàn),為我們的工作帶來(lái)更多便利。

    閱讀原文:https://mp.weixin.qq.com/s/_XYZ4YqOZvCWj6ffyW3uZw


    該文章在 2025/9/28 9:47:47 編輯過(guò)
    關(guān)鍵字查詢(xún)
    相關(guān)文章
    正在查詢(xún)...
    點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
    點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
    點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
    點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
    Copyright 2010-2025 ClickSun All Rights Reserved