一直想用python做一个截图并自动翻译的工具,恰好最近有时间就在网上找了资料,根据资料以及自己的理解做了一个简单的截图翻译工具。整理一下并把代码放在github给大家参考。界面用python自带的GUI的tkinter,截图用的是pillow,图片识别用的是百度ocr的api,翻译用的是百度翻译api。
1、前期准备
(1) demo环境
window 10 python3.6 baidu-aip==2.2.18.0 certifi==2019.11.28 chardet==3.0.4 idna==2.8 Pillow==6.2.1 requests==2.22.0 urllib3==1.25.7
(2)安装第三方包
pip install pillow
pip install baidu-aip
(3)百度ocr的api申请步骤参考 点击跳转
申请百度的ocr的api,添加项目获取相应的appid等信息
(4)百度翻译api申请步骤参考 点击跳转
申请百度翻译的api,添加项目获取相应的appid等信息
(5)tkinter教程参考 点击跳转
使用tkinter制作GUI界面。
设计思路:
1)点击截图按钮先截取当前屏幕的全屏截图
2)在截取的全屏截图上点击鼠标左键拖动鼠标选择需要截取的区域,截取成功后调用百度ocr的api完成图片的识别,并把结果返回到左边的文本框。
3)点击翻译按钮调用百度翻译的api把刚才识别的结果翻译成英文(目前只做了中文翻译成英文)并把结果返回到右边的文本框。
最终效果图:
(6)pillow教程参考 点击跳转
用pillow模块实现最终的截图效果并保存图片
#安装 pip install pyinstaller #到项目文件夹打包你要的打包的python文件 pyinstaller -w myCapture1.3.py
2、最终项目代码 github地址
有问题请留言!觉得项目不错记得点个star,谢谢!
1 # -*- coding: utf-8 -*- 2 # __author: rock 3 # @time: 2019-12-03 4 import tkinter 5 # import asyncio 6 from PIL import ImageGrab 7 from aip import AipOcr 8 import time 9 import os 10 import http.client 11 import hashlib 12 import json 13 import urllib 14 import random 15 16 17 class MyCapture: 18 19 def __init__(self): 20 # 变量X和Y用来记录鼠标左键按下的位置 21 self.X = tkinter.IntVar(value=0) 22 self.Y = tkinter.IntVar(value=0) 23 self.sel = False 24 self.ocr_text = None 25 self.capture_png_path = '' 26 self.capture_text_box = tkinter.Text(window) # 创建text容器用于存放截图识别的文字 27 self.capture_text_box.place(x=20, y=50, anchor='nw', width=170, height=330) 28 29 self.translate_text_box = tkinter.Text(window) # 创建text容器用于存放翻译后的文字 30 self.translate_text_box.place(x=210, y=50, anchor='nw', width=170, height=330) 31 32 self.capture_btn = tkinter.Button(text='截图', command=self.capture_cmd) # 创建一个按钮 33 self.capture_btn.place(x=80, y=10, anchor='nw', width=60, height=20) # 在创建的窗口的西北角x=20,y=10处放置按钮 34 35 self.capture_btn = tkinter.Button(text='翻译', command=self.translate_cmd) # 创建一个按钮 36 self.capture_btn.place(x=260, y=10, anchor='nw', width=60, height=20) 37 # 屏幕尺寸 38 self.screenWidth = window.winfo_screenwidth() 39 self.screenHeight = window.winfo_screenheight() 40 self.temp_png = 'temp.png' 41 # self.create_canvas() 42 43 def create_canvas(self): 44 time.sleep(0.2) 45 im = ImageGrab.grab() 46 im.save(self.temp_png) 47 im.close() 48 # 创建顶级组件容器 49 self.top = tkinter.Toplevel(window, width=self.screenWidth, height=self.screenHeight) 50 # 不显示最大化、最小化按钮 51 self.top.overrideredirect(True) 52 self.canvas = tkinter.Canvas(self.top, bg='white', width=self.screenWidth, height=self.screenHeight) 53 # 显示全屏截图,在全屏截图上进行区域截图 54 self.image = tkinter.PhotoImage(file=self.temp_png) 55 self.canvas.create_image(self.screenWidth // 2, self.screenHeight // 2, image=self.image) 56 57 # 鼠标左键按下的位置 58 self.canvas.bind('<Button-1>', self.mouse_left_down) 59 # 鼠标左键移动,显示选取的区域 60 self.canvas.bind('<B1-Motion>', self.mouse_move) 61 # 获取鼠标左键抬起的位置,保存区域截图 62 self.canvas.bind('<ButtonRelease-1>', self.mouse_left_up) 63 64 self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES) 65 66 def mouse_left_down(self, event): 67 """鼠标左键按下的位置""" 68 self.X.set(event.x) 69 self.Y.set(event.y) 70 self.sel = True # 开始截图 71 72 # 鼠标左键移动,显示选取的区域 73 def mouse_move(self, event): 74 if not self.sel: 75 return 76 try: 77 # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形 78 self.canvas.delete(self.lastDraw) 79 except Exception as e: 80 pass 81 self.lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red') 82 83 def mouse_left_up(self, event): 84 """获取鼠标左键抬起的位置,保存区域截图""" 85 self.sel = False 86 try: 87 self.canvas.delete(self.lastDraw) 88 except Exception as e: 89 pass 90 # 考虑鼠标左键从右下方按下而从左上方抬起的截图 91 x1, x2 = sorted([self.X.get(), event.x]) # tkinter记录的坐标点 92 y1, y2 = sorted([self.Y.get(), event.y]) 93 94 pic = ImageGrab.grab((x1+1, y1+1, x2, y2)) 95 # pic.show() 96 self.capture_png_path = 'capture_png.png' 97 pic.save(self.capture_png_path) 98 99 # 关闭当前窗口 100 self.top.destroy() 101 102 def capture_cmd(self): 103 """点击截图按钮触发函数""" 104 window.iconify() # 窗口最小化 105 # 显示全屏幕截图 106 self.create_canvas() 107 self.capture_btn.wait_window(self.top) 108 os.remove(self.temp_png) 109 self.ocr_text = self.baidu_ocr(self.capture_png_path) 110 # print(self.ocr_text) 111 if self.ocr_text: 112 self.capture_text_box.delete('1.0', tkinter.END) # 清空文本框 113 self.translate_text_box.delete('1.0', tkinter.END) 114 self.capture_text_box.insert('end', self.ocr_text) 115 window.deiconify() # 窗口显示 116 os.remove(self.capture_png_path) 117 118 def translate_cmd(self): 119 """点击翻译按钮触发函数""" 120 if self.ocr_text: 121 self.translate_text = self.baidu_translate(self.ocr_text) 122 self.translate_text_box.delete('1.0', tkinter.END) 123 if self.translate_text: 124 self.translate_text_box.insert('end', self.translate_text) 125 126 def baidu_ocr(self, file_path): 127 """ 调用通用文字识别, 图片参数为本地图片 """ 128 app_id = '' 129 api_key = '' 130 secret_key = '' 131 ocr_text = '' 132 if os.path.isfile(file_path): 133 with open(file_path, 'rb') as fp: 134 image = fp.read() 135 ocr_ret = AipOcr(app_id, api_key, secret_key).basicGeneral(image) 136 words = ocr_ret.get('words_result') 137 if words is not None and len(words): 138 for word in words: 139 # print(word['words'], end=' ') 140 ocr_text += word['words'] + ' ' 141 return ocr_text 142 else: 143 return None 144 else: 145 return None 146 147 def baidu_translate(self, content): 148 app_id = '' 149 secret_key = '' 150 http_client = None 151 myurl = '/api/trans/vip/translate' 152 q = content 153 from_lang = 'zh' # 源语言 154 to_lang = 'en' # 翻译后的语言 155 salt = random.randint(32768, 65536) 156 sign = app_id + q + str(salt) + secret_key 157 sign = hashlib.md5(sign.encode()).hexdigest() 158 myurl = myurl + '?appid=' + app_id + '&q=' + urllib.parse.quote( 159 q) + '&from=' + from_lang + '&to=' + to_lang + '&salt=' + str( 160 salt) + '&sign=' + sign 161 162 try: 163 http_client = http.client.HTTPConnection('api.fanyi.baidu.com') 164 http_client.request('GET', myurl) 165 # response是HTTPResponse对象 166 response = http_client.getresponse() 167 json_response = response.read().decode("utf-8") # 获得返回的结果,结果为json格式 168 js = json.loads(json_response) # 将json格式的结果转换字典结构 169 dst = str(js["trans_result"][0]["dst"]) # 取得翻译后的文本结果 170 # print(dst) # 打印结果 171 return dst 172 except Exception as e: 173 print(e) 174 return None 175 finally: 176 if http_client: 177 http_client.close() 178 179 180 window = tkinter.Tk() 181 window.title('Capture') 182 # 创建tkinter主窗口 183 window.geometry('400x400') # 指定主窗口位置与大小 184 MyCapture() 185 window.mainloop()
可选择语言版本1.3
# -*- coding: utf-8 -*- # __author: rock # @time: 2019-12-03 import tkinter # import asyncio from PIL import ImageGrab from aip import AipOcr import time import os import http.client import hashlib import json import urllib import random from tkinter import ttk # def get_from_lang(self): # print(self.from_lang.get()) # # return # # # def get_to_lang(self): # print(self.to_lang.get()) # # return class MyCapture: def __init__(self): # 变量X和Y用来记录鼠标左键按下的位置 self.X = tkinter.IntVar(value=0) self.Y = tkinter.IntVar(value=0) self.sel = False self.ocr_text = None self.capture_png_path = '' self.capture_text_box = tkinter.Text(window) # 创建text容器用于存放截图识别的文字 self.capture_text_box.place(x=20, y=70, anchor='nw', width=170, height=330) self.translate_text_box = tkinter.Text(window) # 创建text容器用于存放翻译后的文字 self.translate_text_box.place(x=210, y=70, anchor='nw', width=170, height=330) self.capture_btn = tkinter.Button(text='截图', command=self.capture_cmd) # 创建一个按钮 self.capture_btn.place(x=80, y=10, anchor='nw', width=60, height=20) # 在创建的窗口的西北角x=20,y=10处放置按钮 self.capture_btn = tkinter.Button(text='翻译', command=self.translate_cmd) # 创建一个按钮 self.capture_btn.place(x=270, y=10, anchor='nw', width=60, height=20) # 下拉选择框 self.from_lang = 'zh' self.to_lang = 'en' self.lang_dic = {'自动识别': 'auto', '中文': 'zh', '英语': 'en', '日语': 'jp'} self.from_lang_L = tkinter.Label(window, text='原语言:') self.from_lang_box = ttk.Combobox(window, state="readonly") self.from_lang_box['value'] = ('自动识别', '中文', '英语', '日语') self.from_lang_box.current(1) self.from_lang_L.place(x=20, y=40, anchor='nw') self.from_lang_box.place(x=80, y=40, anchor='nw', width=80, height=20) self.from_lang_box.bind("<<ComboboxSelected>>", self.get_from_lang) self.to_lang_L = tkinter.Label(window, text='目标语言:') self.to_lang_box = ttk.Combobox(window,state="readonly") self.to_lang_box['value'] = ('中文', '英语', '日语') self.to_lang_box.current(1) self.to_lang_L.place(x=210, y=40, anchor='nw') self.to_lang_box.place(x=270, y=40, anchor='nw', width=60, height=20) self.to_lang_box.bind("<<ComboboxSelected>>", self.get_to_lang) # 屏幕尺寸 self.screenWidth = window.winfo_screenwidth() self.screenHeight = window.winfo_screenheight() self.temp_png = 'temp.png' # self.create_canvas() def create_canvas(self): time.sleep(0.2) im = ImageGrab.grab() im.save(self.temp_png) im.close() # 创建顶级组件容器 self.top = tkinter.Toplevel(window, width=self.screenWidth, height=self.screenHeight) # 不显示最大化、最小化按钮 self.top.overrideredirect(True) self.canvas = tkinter.Canvas(self.top, bg='white', width=self.screenWidth, height=self.screenHeight) # 显示全屏截图,在全屏截图上进行区域截图 self.image = tkinter.PhotoImage(file=self.temp_png) self.canvas.create_image(self.screenWidth // 2, self.screenHeight // 2, image=self.image) # 鼠标左键按下的位置 self.canvas.bind('<Button-1>', self.mouse_left_down) # 鼠标左键移动,显示选取的区域 self.canvas.bind('<B1-Motion>', self.mouse_move) # 获取鼠标左键抬起的位置,保存区域截图 self.canvas.bind('<ButtonRelease-1>', self.mouse_left_up) self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES) def mouse_left_down(self, event): """鼠标左键按下的位置""" self.X.set(event.x) self.Y.set(event.y) self.sel = True # 开始截图 # 鼠标左键移动,显示选取的区域 def mouse_move(self, event): if not self.sel: return try: # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形 self.canvas.delete(self.lastDraw) except Exception as e: pass self.lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red') def mouse_left_up(self, event): """获取鼠标左键抬起的位置,保存区域截图""" self.sel = False try: self.canvas.delete(self.lastDraw) except Exception as e: pass # 考虑鼠标左键从右下方按下而从左上方抬起的截图 x1, x2 = sorted([self.X.get(), event.x]) # tkinter记录的坐标点 y1, y2 = sorted([self.Y.get(), event.y]) pic = ImageGrab.grab((x1+1, y1+1, x2, y2)) # pic.show() self.capture_png_path = 'capture_png.png' pic.save(self.capture_png_path) # 关闭当前窗口 self.top.destroy() def capture_cmd(self): """点击截图按钮触发函数""" window.iconify() # 窗口最小化 # 显示全屏幕截图 self.create_canvas() self.capture_btn.wait_window(self.top) os.remove(self.temp_png) self.ocr_text = self.baidu_ocr(self.capture_png_path) print(self.ocr_text) if self.ocr_text: self.capture_text_box.delete('1.0', tkinter.END) # 清空文本框 self.translate_text_box.delete('1.0', tkinter.END) self.capture_text_box.insert('end', self.ocr_text) window.deiconify() # 窗口显示 os.remove(self.capture_png_path) def translate_cmd(self): """点击翻译按钮触发函数""" if self.ocr_text: self.translate_text = self.baidu_translate(self.ocr_text) self.translate_text_box.delete('1.0', tkinter.END) if self.translate_text: self.translate_text_box.insert('end', self.translate_text) def baidu_ocr(self, file_path): """ 调用通用文字识别, 图片参数为本地图片 """ app_id = '你自己的appid' api_key = '你自己的api_key' secret_key = '你自己的secret_key' ocr_text = '' if os.path.isfile(file_path): with open(file_path, 'rb') as fp: image = fp.read() ocr_ret = AipOcr(app_id, api_key, secret_key).basicGeneral(image) words = ocr_ret.get('words_result') if words is not None and len(words): for word in words: # print(word['words'], end=' ') ocr_text += word['words'] + ' ' return ocr_text else: return None else: return None def baidu_translate(self, content): app_id = '你自己的appid' secret_key = '你自己的secretkey' http_client = None myurl = '/api/trans/vip/translate' q = content # from_lang = 'zh' # 源语言 from_lang = self.from_lang # 源语言 to_lang = self.to_lang # 翻译后的语言 # to_lang = 'en' # 翻译后的语言 salt = random.randint(32768, 65536) sign = app_id + q + str(salt) + secret_key sign = hashlib.md5(sign.encode()).hexdigest() myurl = myurl + '?appid=' + app_id + '&q=' + urllib.parse.quote( q) + '&from=' + from_lang + '&to=' + to_lang + '&salt=' + str( salt) + '&sign=' + sign try: http_client = http.client.HTTPConnection('api.fanyi.baidu.com') http_client.request('GET', myurl) # response是HTTPResponse对象 response = http_client.getresponse() json_response = response.read().decode("utf-8") # 获得返回的结果,结果为json格式 js = json.loads(json_response) # 将json格式的结果转换字典结构 # print(js) dst = str(js["trans_result"][0]["dst"]) # 取得翻译后的文本结果 # print(dst) # 打印结果 return dst except Exception as e: print(e) return None finally: if http_client: http_client.close() def get_from_lang(self, event): # print(self.from_lang_box.get()) self.from_lang = self.lang_dic[self.from_lang_box.get()] # return def get_to_lang(self, event): # print(self.to_lang_box.get()) self.to_lang = self.lang_dic[self.to_lang_box.get()] # return window = tkinter.Tk() window.title('Capture') # 创建tkinter主窗口 window.geometry('400x420') # 指定主窗口位置与大小 capture = MyCapture() # capture.from_lang.bind("<<ComboboxSelected>>", get_from_lang(capture)) # capture.to_lang.bind("<<ComboboxSelected>>", get_to_lang(capture)) window.mainloop()