一直想用python做一个截图并自动翻译的工具,恰好最近有时间就在网上找了资料,根据资料以及自己的理解做了一个简单的截图翻译工具。整理一下并把代码放在github给大家参考。界面用python自带的GUI的tkinter,截图用的是pillow,图片识别用的是百度ocr的api,翻译用的是百度翻译api。
1、前期准备
(1) demo环境
window 10python3.6baidu-aip==2.2.18.0certifi==2019.11.28chardet==3.0.4idna==2.8Pillow==6.2.1requests==2.22.0
urllib3==1.25.7
(2)安装第三方包
pip install pillow
pip install baidu-aip
申请百度的ocr的api,添加项目获取相应的appid等信息
申请百度翻译的api,添加项目获取相应的appid等信息
使用tkinter制作GUI界面。
设计思路:
1)点击截图按钮先截取当前屏幕的全屏截图
2)在截取的全屏截图上点击鼠标左键拖动鼠标选择需要截取的区域,截取成功后调用百度ocr的api完成图片的识别,并把结果返回到左边的文本框。
3)点击翻译按钮调用百度翻译的api把刚才识别的结果翻译成英文(目前只做了中文翻译成英文)并把结果返回到右边的文本框。
最终效果图:
用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 importtkinter5 #import asyncio
6 from PIL importImageGrab7 from aip importAipOcr8 importtime9 importos10 importhttp.client11 importhashlib12 importjson13 importurllib14 importrandom15
16
17 classMyCapture: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 =False24 self.ocr_text =None25 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 defcreate_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('', self.mouse_left_down)59 #鼠标左键移动,显示选取的区域
60 self.canvas.bind('', self.mouse_move)61 #获取鼠标左键抬起的位置,保存区域截图
62 self.canvas.bind('', self.mouse_left_up)63
64 self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES)65
66 defmouse_left_down(self, event):67 """鼠标左键按下的位置"""
68 self.X.set(event.x)69 self.Y.set(event.y)70 self.sel = True #开始截图
71
72 #鼠标左键移动,显示选取的区域
73 defmouse_move(self, event):74 if notself.sel:75 return
76 try:77 #删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形
78 self.canvas.delete(self.lastDraw)79 exceptException 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 defmouse_left_up(self, event):84 """获取鼠标左键抬起的位置,保存区域截图"""
85 self.sel =False86 try:87 self.canvas.delete(self.lastDraw)88 exceptException 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 defcapture_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 ifself.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 deftranslate_cmd(self):119 """点击翻译按钮触发函数"""
120 ifself.ocr_text:121 self.translate_text =self.baidu_translate(self.ocr_text)122 self.translate_text_box.delete('1.0', tkinter.END)123 ifself.translate_text:124 self.translate_text_box.insert('end', self.translate_text)125
126 defbaidu_ocr(self, file_path):127 """调用通用文字识别, 图片参数为本地图片"""
128 app_id = ''
129 api_key = ''
130 secret_key = ''
131 ocr_text = ''
132 ifos.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 andlen(words):138 for word inwords:139 #print(word['words'], end='\n')
140 ocr_text += word['words'] + '\n'
141 returnocr_text142 else:143 returnNone144 else:145 returnNone146
147 defbaidu_translate(self, content):148 app_id = ''
149 secret_key = ''
150 http_client =None151 myurl = '/api/trans/vip/translate'
152 q =content153 from_lang = 'zh' #源语言
154 to_lang = 'en' #翻译后的语言
155 salt = random.randint(32768, 65536)156 sign = app_id + q + str(salt) +secret_key157 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=' +sign161
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 returndst172 exceptException as e:173 print(e)174 returnNone175 finally:176 ifhttp_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("<>", 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("<>", 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('', self.mouse_left_down)
# 鼠标左键移动,显示选取的区域
self.canvas.bind('', self.mouse_move)
# 获取鼠标左键抬起的位置,保存区域截图
self.canvas.bind('', 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='\n')
ocr_text += word['words'] + '\n'
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("<>", get_from_lang(capture))
# capture.to_lang.bind("<>", get_to_lang(capture))
window.mainloop()