紧跟潮流 也写个 OCR 图像识别 (调用本地 http )

查看 64|回复 11
作者:pyjiujiu   

更新

修复一个小bug,详细在文章末尾

[color=]**编写说明:
1 调用的是 Umi-OCR 的http 服务,所以需要先安装这个软件(开源的)
老实说 软件本身已经可以支持OCR的操作,为何多此一举
,理由如下
* http 服务可以面向局域网,调用接口通过路由器,还是有需求的
* 原软件比较花哨,看着晕,操作也不够友好(我的脚本 更简洁,适合一般任务)


测试4.JPG (87.95 KB, 下载次数: 0)
下载附件
2024-11-16 09:49 上传

           
2 脚本说明
* 支持 「打开图片」,「拖入图片」,「剪贴板粘贴」(ctrl+V 即可)三种输入方式
其中 打开图片 需要手动按识别按钮"operate"外,剪贴板和拖入 会自动识别
* 默认仅显示三个常用设置,点击「更多选项」还有三个选项
其中“忽略区域” 不能真正修改,待以后规划,“数据格式” 是http 返回的信息多与少,界面上没影响
* 需要安装额外的包
tkinterdnd2  #为了支持拖入图片
PIL                # 为了支持剪贴板拾图(python3 -m pip install --upgrade Pillow)
---分割线---
*umi 原软件除后台运行外,还需确保 http服务打开 (默认是打开的)


测试2.png (46.39 KB, 下载次数: 0)
下载附件
2024-11-16 10:01 上传

---分割线---
[color=]**下面是代码
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog, messagebox,scrolledtext
from tkinter import ttk
from tkinterdnd2 import TkinterDnD, DND_FILES
import json
import base64
import pathlib
import requests
import io
from PIL import ImageGrab  
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2)
url_base = 'http://127.0.0.1:1224/'
url_options = url_base + 'api/ocr/get_options'
url_ocr = url_base + "api/ocr"
def test_http(url_base):
    '''test the server'''
    try:
        response = requests.get(url=url_base)
        response.raise_for_status()
    except Exception as e:
        messagebox.showwarning("warning","服务未连通,请确保软件或服务端已经打开")
def img_base64(img_file):
    if isinstance(img_file,io.BytesIO):
        img_bytes = img_file.getvalue()
    else:
        img_bytes = pathlib.Path(img_file).read_bytes()
    return base64.b64encode(img_bytes).decode('utf-8')
def to_ocr(url,options:dict,img:str | io.BytesIO):
    data = {
    "base64":img_base64(img),
    "options": options
    }
    headers = {"Content-Type": "application/json"}
    data_str = json.dumps(data)
    response = requests.post(url,data=data_str, headers=headers)  #也可用 json 参数
    response.raise_for_status()
    res_dict = json.loads(response.text)
    return res_dict  
class OptTranslator:
    '''en --> zh'''
    __slots__=('ocr_language','tbpu_parser','opt_name')
    def __init__(self) -> None:
        self.opt_name:dict = {"ocr.language":"语言:","ocr.cls":"对正文字:","ocr.limit_side_len":"限制边长:","tbpu.parser":"排版:","tbpu.ignoreArea":"忽略区域:","data.format":"数据格式:",}
        self.ocr_language:dict={"简体中文":"models/config_chinese.txt",
                        "English":"models/config_en.txt",
                            "繁體中文":"models/config_chinese_cht(v2).txt",
                            "日本語":"models/config_japan.txt",
                            "한국어":"models/config_korean.txt",
                            "Русский":"models/config_cyrillic.txt"}
        self.tbpu_parser:dict = {"单栏-按自然段换行":"single_para",
                            "单栏-总是换行":"single_line",
                            "多栏-按自然段换行":"multi_para",
                            "多栏-总是换行":"multi_line",
                            "多栏-无换行":"multi_none",
                            "单栏-按自然段换行":"single_para",
                            "单栏-总是换行":"single_line",
                            "单栏-无换行":"single_none",
                            "单栏-保留缩进":"single_code",
                            "不做处理":"none"}
class App:
    def __init__(self, root):
        self.root = root
        self.root.title("OCR")
        self.root.geometry("520x450")
        self.file_path_label = tk.Label(root, text="File Path:")
        self.file_path_label.grid(row=0, column=0, sticky="w", padx=10, pady=10)
        self.file_path_entry = tk.Entry(root, width=50)
        self.file_path_entry.grid(row=0, column=1, padx=10, pady=10)
        self.open_button = tk.Button(root, text="Open", command=self.open_file)
        self.open_button.grid(row=0, column=2, padx=10, pady=10)
        self.root.drop_target_register(DND_FILES)
        self.root.dnd_bind('>', self.on_file_drop)
        self.clipboard = None
        self.root.bind("", self.on_paste)
        self.arg_vars = [tk.StringVar() for _ in range(6)]
        self.arg_comboboxes = []  
        self.arg_comboboxes_label = []
        self.OptTranslator = OptTranslator()
        self.option_list = [{'opt_name':'ocr.language','value':[ ("models/config_chinese.txt","简体中文"),
                                                                ("models/config_en.txt","English"),
                                                                ("models/config_chinese_cht(v2).txt","繁體中文"),
                                                                ("models/config_japan.txt","日本語"),
                                                                ("models/config_korean.txt","한국어"),
                                                                ("models/config_cyrillic.txt","Русский")]},
                            {'opt_name':'ocr.limit_side_len','value':("960", "2880", "4320", "999999")},
                            {'opt_name':'tbpu.parser','value':[
                                                                ("single_para","单栏-按自然段换行"),
                                                                ("single_line","单栏-总是换行"),
                                                                ("multi_para","多栏-按自然段换行"),
                                                                ("multi_line","多栏-总是换行"),
                                                                ("multi_none","多栏-无换行"),
                                                                ("single_para","单栏-按自然段换行"),
                                                                ("single_line","单栏-总是换行"),
                                                                ("single_none","单栏-无换行"),
                                                                ("single_code","单栏-保留缩进"),
                                                                ("none","不做处理")]},
                            {'opt_name':'ocr.cls','value':("false", "true")},
                            {'opt_name':'tbpu.ignoreArea','value':[""]},  #修复原始版本 "[]" -> "" ,旧版不会报错,新版2.1.4会报错
                            {'opt_name':'data.format','value':("text","dict")}]
        for i in range(6):
            arg_label = tk.Label(root, text=self.OptTranslator.opt_name[self.option_list['opt_name']])
            arg_combobox = ttk.Combobox(root, textvariable=self.arg_vars, values=self.option_list['value'], state="readonly", width=20)
            if i
脚本附加说明:
因为图片识别 时长比较短,故不再加入多线程(tkinter 本身是单线程的),用起来会有一点点运行的时间感受,这是正常的
---分割线---
最后,个人典型的使用场景是,截图,然后打开脚本界面,ctrl+v,结果就出来了
希望对大家有帮助,欢迎交流
---版本迭代 记录---
*11-17 修复参数传递值,代码第108行,为{'opt_name':'tbpu.ignoreArea','value':[""]} (旧版Umi软件不报错,但最新版2.1.4会)

换行, 自然

小小/ng   

可以搞个油猴脚本,自动识别验证码
pyjiujiu
OP
  


feilon5555 发表于 2024-11-16 12:12
怎么识别生成表格啊

看我最新回复,GOT-OCR 模型可以解决表格生成 的问题
但是成熟的脚本,要等一等,还在消化中
forever96   

完美诠释了什么叫脱裤子放屁,多此一举
dinosaur18   

ocr是练手神器
superworker2022   

下载学习,也复现一下~
qiu520   

太厉害了吧,佩服
z297171662   

这个现在的确很多。。。
Nuaza   

这个确实有用,感谢楼主分享
LuoBoYIng   

感谢大佬分享
您需要登录后才可以回帖 登录 | 立即注册