一直想用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='\n') 140 ocr_text += word['words'] + '\n' 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='\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("<<ComboboxSelected>>", get_from_lang(capture)) # capture.to_lang.bind("<<ComboboxSelected>>", get_to_lang(capture)) window.mainloop()