From 2b971292bd3d6d8923eaf05e327a5e4012038704 Mon Sep 17 00:00:00 2001 From: SiiriusXT <1160925501@qq.com> Date: Fri, 4 Dec 2020 20:09:41 +0800 Subject: [PATCH] first commit --- OCR.py | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ api.conf | 4 ++ ocr.ico | Bin 0 -> 67646 bytes 3 files changed, 190 insertions(+) create mode 100644 OCR.py create mode 100644 api.conf create mode 100644 ocr.ico diff --git a/OCR.py b/OCR.py new file mode 100644 index 0000000..c6bd547 --- /dev/null +++ b/OCR.py @@ -0,0 +1,186 @@ +from aip import AipOcr +import pyperclip +from PIL import ImageGrab +import tkinter +import ctypes +import io +import keyboard +import wx +import wx.adv +import _thread +import sys +from win10toast import ToastNotifier +import configparser +class MyTaskBarIcon(wx.adv.TaskBarIcon): + ICON = "ocr.ico" # 图标地址 + ID_ABOUT = wx.NewIdRef() # 菜单选项“关于”的ID + ID_EXIT = wx.NewIdRef() # 菜单选项“退出”的ID + # ID_SHOW_WEB = wx.NewId() # 菜单选项“显示页面”的ID + TITLE = "OCR" #鼠标移动到图标上显示的文字 + + def __init__(self): + wx.adv.TaskBarIcon.__init__(self) + self.SetIcon(wx.Icon(self.ICON), self.TITLE) # 设置图标和标题 + self.Bind(wx.EVT_MENU, self.onAbout, id=self.ID_ABOUT) # 绑定“关于”选项的点击事件 + self.Bind(wx.EVT_MENU, self.onExit, id=self.ID_EXIT) # 绑定“退出”选项的点击事件 + # self.Bind(wx.EVT_MENU, self.onShowWeb, id=self.ID_SHOW_WEB) # 绑定“显示页面”选项的点击事件 + + # “关于”选项的事件处理器 + def onAbout(self, event): + wx.MessageBox('程序作者:Sirius \n最后更新日期:2020-12-4', "关于") + + # “退出”选项的事件处理器 + def onExit(self, event): + wx.Exit() + sys.exit(0) + # “显示页面”选项的事件处理器 + def onShowWeb(self, event): + pass + + # 创建菜单选项 + def CreatePopupMenu(self): + menu = wx.Menu() + for mentAttr in self.getMenuAttrs(): + menu.Append(mentAttr[1], mentAttr[0]) + return menu + + # 获取菜单的属性元组 + def getMenuAttrs(self): + return [#('进入程序', self.ID_SHOW_WEB), + ('关于', self.ID_ABOUT), + ('退出', self.ID_EXIT)] + + +class MyFrame(wx.Frame): + def __init__(self): + wx.Frame.__init__(self) + MyTaskBarIcon()#显示系统托盘图标 + + +class MyApp(wx.App): + def OnInit(self): + MyFrame() + return True + +class CTkPrScrn: + def __init__(self): + self.__start_x, self.__start_y = 0, 0 + self.__scale = 1 + + self.__win = tkinter.Tk() + self.__win.attributes("-alpha", 0.4) # 设置窗口半透明 + self.__win.attributes("-fullscreen", True) # 设置全屏 + self.__win.attributes("-topmost", True) # 设置窗口在最上层 + + self.__width, self.__height = self.__win.winfo_screenwidth(), self.__win.winfo_screenheight() + + # 创建画布 + self.__canvas = tkinter.Canvas(self.__win, width=self.__width, height=self.__height, bg="white") + + self.__win.bind('', self.xFunc1) # 绑定鼠标左键点击事件 + self.__win.bind('', self.xFunc1) # 绑定鼠标左键点击释放事件 + self.__win.bind('', self.xFunc2) # 绑定鼠标左键点击移动事件 + # self.__win.bind('', lambda e: self.__win.destroy()) # 绑定Esc按键退出事件 + + user32 = ctypes.windll.user32 + gdi32 = ctypes.windll.gdi32 + dc = user32.GetDC(None) + widthScale = gdi32.GetDeviceCaps(dc, 8) # 分辨率缩放后的宽度 + # heightScale = gdi32.GetDeviceCaps(dc, 10) # 分辨率缩放后的高度 + width = gdi32.GetDeviceCaps(dc, 118) # 原始分辨率的宽度 + # height = gdi32.GetDeviceCaps(dc, 117) # 原始分辨率的高度 + self.__scale = width / widthScale + self.__win.mainloop() # 窗口持久化 + def xFunc1(self, event): + # print(f"鼠标左键点击了一次坐标是:x={g_scale * event.x}, y={g_scale * event.y}") + if event.state == 8: # 鼠标左键按下 + self.__start_x, self.__start_y = event.x, event.y + elif event.state == 264: # 鼠标左键释放 + if event.x == self.__start_x or event.y == self.__start_y: + return + + self.__win.update() + # sleep(0.5) + self.__win.destroy() + sx = min(self.__scale * self.__start_x,self.__scale * event.x) + ex = max(self.__scale * self.__start_x,self.__scale * event.x) + sy = min(self.__scale * self.__start_y,self.__scale * event.y) + ey = max(self.__scale * self.__start_y,self.__scale * event.y) + img = ImageGrab.grab((sx, sy,ex,ey)) + img_bytes = io.BytesIO() + img.save(img_bytes, format="PNG") + self.image_bin = img_bytes.getvalue() + def xFunc2(self, event): + # print(f"鼠标左键点击了一次坐标是:x={self.__scale * event.x}, y={self.__scale * event.y}") + if event.x == self.__start_x or event.y == self.__start_y: + return + self.__canvas.delete("prscrn") + self.__canvas.create_rectangle(self.__start_x, self.__start_y, event.x, event.y, + fill='black', outline='red', tag="prscrn") + # 包装画布 + self.__canvas.pack() + + +def OCR(APP_ID, API_KEY, SECRET_KEY,image_bin): + client = AipOcr(APP_ID, API_KEY, SECRET_KEY) + options = {} + options["detect_direction"] = "true" + options["probability"] = "true" + return client.basicAccurate(image_bin, options)['words_result'] + + +""" 你的 APPID AK SK """ +cf = configparser.ConfigParser() +cf.read("api.conf") +APP_ID = cf.get("default", "APP_ID") +API_KEY = cf.get("default", "API_KEY") +SECRET_KEY = cf.get("default", "SECRET_KEY") + +def 通知(title,msg,icon_path,duration): + try: + ToastNotifier().show_toast(title=title, msg=msg, + icon_path=icon_path,duration=duration) + except: + pass + +def CTkPrScrn_OCR(): + toast = ToastNotifier() + + try: + image = CTkPrScrn() + image_bin = image.image_bin + except Exception as e: + # print("截图出错\n" + str(e)) + _thread.start_new_thread(通知, ("截图出错", str(e), r"ocr.ico", 3)) + # toast.show_toast(title="截图出错", msg=str(e), + # icon_path=r"ocr.ico", duration=3) + else: + try: + returnresult=OCR(APP_ID, API_KEY, SECRET_KEY, image_bin) + result = "" + for line in returnresult: + result += line['words'] + "\n" + pyperclip.copy(result) + # print("识别结果已经复制到剪切板") + _thread.start_new_thread(通知, ("识别结果已经复制到剪切板", result, r"ocr.ico", 3)) + # toast.show_toast(title="识别结果已经复制到剪切板", msg=result, + # icon_path=r"ocr.ico", duration=3) + except Exception as e: + # print("OCR出错\n" + str(e)) + _thread.start_new_thread(通知, ("OCR出错",str(e),r"ocr.ico",15)) + # toast.show_toast(title="OCR出错", msg="str(e)", + # icon_path=r"ocr.ico", duration=3) + + +def tuopan(a): + app = MyApp() + app.MainLoop() + +_thread.start_new_thread( tuopan, (1 ,) ) + +keyboard.add_hotkey('alt+o', CTkPrScrn_OCR) +keyboard.wait() + + + + diff --git a/api.conf b/api.conf new file mode 100644 index 0000000..8f218bd --- /dev/null +++ b/api.conf @@ -0,0 +1,4 @@ +[default] +APP_ID = 425525 +API_KEY = jhL6kD534ibkQOhzAAKjTS0 +SECRET_KEY = uAbfbe8gAFAFakLv7X3j2fg \ No newline at end of file diff --git a/ocr.ico b/ocr.ico new file mode 100644 index 0000000000000000000000000000000000000000..c944f5c51ded1a92cfdea6d6fb242e054645362a GIT binary patch literal 67646 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 Re%)U&2q6mc@h_v>{{xp{bIkw% literal 0 HcmV?d00001