赞
踩
获取文字识别应用的AppID、API KEY、Secret Key
加入百度翻译开放平台,获取百度翻译应用的APP ID、密钥
获取有道翻译应用的APP ID、密钥
阅读百度官方提供的API文档,图片的文字识别需要安装百度ai的包,pip install baidu-aip
# -*- coding: utf-8 -*- __author__ = 'iccool' from aip import AipOcr """ 你的 APPID AK SK """ APP_ID = '你的 App ID' API_KEY = '你的 Api Key' SECRET_KEY = '你的 Secret Key' """ 如果有可选参数 """ ai_options = {} ai_options["language_type"] = "CHN_ENG" ai_options["detect_direction"] = "true" ai_options["detect_language"] = "true" ai_options["probability"] = "true" ''' 获取百度api连接 ''' def getConnect(APP_ID, API_KEY, SECRET_KEY): client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # client.setProxies(proxies) return client ''' 读取图片 ''' def get_file_content(filePath): with open(filePath, 'rb') as fp: return fp.read() """ 调用通用文字识别, 图片参数为本地图片 """ def ocr_image(client, image): message = client.basicGeneral(image, ai_options) return message image = 'example.jpg' client = getConnect(APP_ID, API_KEY, SECRET_KEY) message = ocr_image(client, image) """ 调用通用文字识别, 图片参数为本地图片 """ # client.basicGeneral(image) """ 带参数调用通用文字识别, 图片参数为本地图片 """ # client.basicGeneral(image, options)
返回结果示例
{
"log_id": 2471272194,
"words_result_num": 2,
"words_result":
[
{"words": " TSINGTAO"},
{"words": "青島睥酒"}
]
}
至此,简单版图片文字识别已完成,详细阅读官方文档
通用翻译API HTTP地址:http://api.fanyi.baidu.com/api/trans/vip/translate
通用翻译API HTTPS地址:https://fanyi-api.baidu.com/api/trans/vip/translate
下面我们需要拼接这个url请求,官方解释如下:
q:请求翻译query,例如文字识别出的文字
注:若翻译多个单词或者多段文本,需要发送请求之前对q字段做URL encode,urllib.parse.quote(q)
from:翻译源语言,语言选择代码见官方文档,常见的有:auto-自动检测,zh-中文,en-英文
to:译文语言 注:不可设置为auto
appid: APP ID
salt:随机数 例如 salt = random.randint(1, 65536)
sign:签名 appid+q+salt+密钥 的MD5值
def get_md5(data):
sign = hashlib.md5(data.encode(encoding='UTF-8')).hexdigest()
return sign
data = appID + q + str(salt) + secretKEY
sign = get_md5(data)
返回示例
{
"from": "en",
"to": "zh",
"trans_result": [
{
"src": "apple",
"dst": "苹果"
}
]
}
from | TEXT | 翻译源语言 |
---|---|---|
to | TEXT | 译文语言 |
trans_result | MIXED LIST | 翻译结果 |
src | TEXT | 原文 |
dst | TEXT | 译文 |
注:若返回的是response.text,在解析时,需要将字符串转化为json,json_result = json.loads(result)
至此,百度通用翻译已完成,详细阅读官方文档
有道翻译API HTTP地址:http://openapi.youdao.com/api
有道翻译API HTTPS地址:https://openapi.youdao.com/api
字段名 | 类型 | 含义 | 必填 | 备注 |
---|---|---|---|---|
q | text | 要翻译的文本 | True | 必须是UTF-8编码 |
from | text | 源语言 | True | 语言列表 (可设置为auto) |
to | text | 目标语言 | True | 语言列表 (可设置为auto) |
appKey | text | 应用 ID | True | 可在 应用管理 查看 |
salt | text | 随机数 | True | |
sign | text | 签名,通过md5(appKey+q+salt+应用密钥)生成 | True | appKey+q+salt+应用密钥的MD5值 |
ext | 翻译结果音频格式,支持mp3 | false | mp3 | |
voice | 翻译结果发音选择,0为女声,1为男声,默认为女声 | false | 0 |
* 来自官方文档
中英文语言代码:zh-CHS-中文,EN-英文,更多见 支持语言表
具体请求操作与百度翻译类似,就不赘述了。
官方示例如下:
{ "errorCode":"0", "query":"good", //查询正确时,一定存在 "translation": [ //查询正确时一定存在 "好" ], "basic":{ // 有道词典-基本词典,查词时才有 "phonetic":"gʊd" "uk-phonetic":"gʊd" //英式音标 "us-phonetic":"ɡʊd" //美式音标 "uk-speech": "XXXX",//英式发音 "us-speech": "XXXX",//美式发音 "explains":[ "好处", "好的" "好" ] }, "web":[ // 有道词典-网络释义,该结果不一定存在 { "key":"good", "value":["良好","善","美好"] }, {...} ] ], "dict":{ "url":"yddict://m.youdao.com/dict?le=eng&q=good" }, "webdict":{ "url":"http://m.youdao.com/dict?le=eng&q=good" }, "l":"EN2zh-CHS", "tSpeakUrl":"XXX",//翻译后的发音地址 "speakUrl": "XXX" //查询文本的发音地址 }
与百度翻译类似,若返回的是response.text,需要将字符串转化为json
接下来就是根据需要,解析json从而获得想要的结果。
至此,有道通用翻译已完成,详细阅读官方文档
from PIL import Image,ImageGrab
im = ImageGrab.grabclipboard()
if isinstance(im,Image.Image):
pass
ImageGrab.grabclipboard() 获取剪贴板的快照对象, 调用isinstance() 判断是否为图片。
如何将剪贴板的图片对象传入到百度文字识别函数中?
将读到的图片对象写入到内存字节缓冲区中,然后百度文字识别函数从内存字节缓冲区中读取到图片进行识别
# 获取剪贴板中的图片
def ocr_clipboard():
# 获取剪切板对象
im = ImageGrab.grabclipboard()
# 如果是 Image对象
if isinstance(im, Image.Image):
# 写入到内存中
mf = io.BytesIO()
# 临时保存
im.save(mf, 'PNG')
# 将流位置初始化到0
mf.seek(0)
以上,将mf对象传给百度文字识别函数
# 读取图片
def ocr(imagePath):
# 如果读取的是截图 内存字节流
if isinstance(imagePath,io.BytesIO):
# 将流位置初识化到0
imagePath.seek(0)
# 读取图片内容
image = imagePath.read()
else:
# 如果读到的本地图片地址 调用文件读取函数
image = get_file_content(imagePath)
感觉整个项目过程中,属图形界面最花时间,也是最让我烦恼的。不过说到底还是对tkinter不熟悉,需要用的时候都是现查。虽然之前做过一个小demo–天气查询,基础功能已实现,看起来很low。
初始设计图如下:
效果图如下(还存在一些问题):
root = tk.Tk() # 获取窗体大小 # root.winfo_height() # root.winfo_width() # 设置窗口标题 TITLE root.title(TITLE) # 获取屏幕分辨率 cx_screen = GetSystemMetrics(0) cy_screen = GetSystemMetrics(1) # 设置 窗口大小 window_width = cx_screen * 0.8 window_height = cy_screen * 0.7 # 设置窗口起始位置 window_start_x, window_start_y = 20, 20 root.geometry('%dx%d+%d+%d' % (window_width, window_height, window_start_x, window_start_y)) # 设置图标 root.iconbitmap('trans.ico')
''' 左边的Frame 图片 中间的Frame 控制区域 粘贴 浏览 识别 下拉列表 翻译按钮 右边的Frame 上 显示识别出的文字 下 显示翻译出的结果 底部的Frame 版权信息 ''' frm = tk.Frame(root) frm_L = tk.Frame(frm) frm_M = tk.Frame(frm) frm_R = tk.Frame(frm) frm_B = tk.Frame(frm) frm_L.grid(column=0, row=0) frm_M.grid(column=1, row=0) frm_R.grid(column=2, row=0) frm_B.grid(column=0, row=1,columnspan=3)
# 左 Frame
# 默认的图片控件的长宽
w_box = window_width * 0.5
h_box = w_box
lef = tk.Label(frm_L, width=30, height=30,text='')
lef.grid(column=0, row=0, padx=10)
# 中 Frame # 按钮 粘贴 b_paste = ttk.Button(frm_M, text='粘贴', width=12, command=lambda: ocr_clipboard(frm_L, w_box, h_box)) b_paste.grid(column=0, row=0, pady=15) # 按钮 浏览 b_scan = ttk.Button(frm_M, text='浏览', width=12, command=lambda: scan_image(frm_L, w_box, h_box)) b_scan.grid(column=0, row=1, pady=15) # 按钮 识别 传入图片的地址 b_ocr = ttk.Button(frm_M, text="识别", width=12, command=lambda: ocr_image(imagePath)) b_ocr.grid(column=0, row=2, pady=15) # 下拉选择 翻译软件 soft_str = tk.StringVar() soft_chosen = ttk.Combobox(frm_M, width=10, textvariable=soft_str) soft_chosen['value'] = ('百度翻译', '有道翻译') soft_chosen.grid(column=0, row=3, pady=2) # 设置其在界面中出现的位置 column代表列 row 代表行 soft_chosen.current(0) soft_chosen.bind("<<ComboboxSelected>>", show_msg(soft_str)) # 下拉选择 互译 lang_str = tk.StringVar() lang_chosen = ttk.Combobox(frm_M, width=10, textvariable=lang_str) lang_chosen['value'] = ('英译中', '中译英') lang_chosen.grid(column=0, row=4, pady=2) lang_chosen.current(0) lang_chosen.bind("<<ComboboxSelected>>", show_msg(lang_str)) # 按钮 翻译 b_trans = ttk.Button(frm_M, text='翻译', width=12, command=lambda: trans(soft_chosen.get(),lang_chosen.get(), label_ocr)) b_trans.grid(column=0, row=5, pady=15)
以上控件会涉及到一些函数
ocr_clipboard()
从剪贴板获取图片,第四章已经提到了,补充 图片自适应窗体大小
# 打开 内存字节流文件 图片
im_obj = Image.open(mf)
# 图片自适应
pil_image_resized = resize(w_box, h_box, im_obj)
# 将 缩放后的图片 传递给ImageTk
tkImage = ImageTk.PhotoImage(image=pil_image_resized, size=30)
# label显示图片
lb_image = tk.Label(frm_L, width=w_box, height=h_box, image=tkImage)
lb_image.grid(column=0, row=0, padx=10)
resize()
# 缩放图片 # 传入 图片控件的长宽和图片文件 def resize(w_box, h_box, pil_image): ''' resize a pil_image object so it will fit into a box of size w_box times h_box, but retain aspect ratio 对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例 ''' # 获取图片的长宽 w, h = pil_image.size # 获取 图片控件与原始图片的缩放比例 f1 = 1.0 * w_box / w f2 = 1.0 * h_box / h # 比较 长宽 获取较小的值 factor = min([f1, f2]) # print(f1, f2, factor) # test # use best down-sizing filter width = int(w * factor) height = int(h * factor) # print(width,height) return pil_image.resize((width, height), Image.ANTIALIAS)
scan_image()
# 调用浏览文件函数 def scan_image(frm_L, w_box, h_box): # 打开文件 imagePath = filedialog.askopenfilename() if imagePath.endswith(('.png', 'jpg', 'jpeg', '.bmp')): pilImage = Image.open(imagePath) # 图片自适应 pil_image_resized = resize(w_box, h_box, pilImage) # 将 缩放后的图片 传递给tk tkImage = ImageTk.PhotoImage(image=pil_image_resized, size=30) # label显示图片 lb_image = tk.Label(frm_L, width=w_box, height=h_box, image=tkImage) print(w_box,h_box) lb_image.grid(column=0, row=0, padx=10) else: # 注如果打开文件时 点击'取消',返回 '' messagebox.showinfo(title='警告', message='请重新选择图片文件')
ocr_image()
# 调用识别图片函数
def ocr_image(imagePath):
text = ocr.ocr(imagePath)
label_ocr.delete(1.0, tk.END)
label_ocr.insert(1.0, text)
ocr()
调用第二章中的百度图片文字识别
show_msg()
# 调用下拉框 返回下拉框选择值
def show_msg(obj):
return obj.get()
trans()
# 调用翻译函数
def trans(soft,lang, label_ocr):
text = ocr.translate(soft, lang, label_ocr.get('1.0', tk.END))
label_trans.delete(1.0, tk.END)
label_trans.insert('1.0', text)
translate()
调用第三章中的文字翻译函数
# 右 Frame
global label_ocr
label_ocr = tk.Text(frm_R, width=60, height=8, state='normal')
label_ocr.grid(row=0, pady=10, padx=10)
global label_trans
label_trans = tk.Text(frm_R, width=60, height=8, state='normal')
label_trans.grid(row=1, pady=10, padx=10)
# 底部 版权 COPYRIGHT
copy_right = tk.Label(frm_B,width=20,height=2,text=COPYRIGHT)
copy_right.grid(row=0,column=0)
在调用识别、翻译时都是需要网络的,在特殊情况下,本地网络需要走代理,这时需要灵活地设置代理功能。想法是设计一个类似微信客户端的代理设置界面(弹窗设置)。
整体效果:
import tkinter as tk from tkinter import ttk # 设置代理 弹窗 class MyAgentDialog(tk.Toplevel): def __init__(self): super().__init__() self.title('设置代理信息') # 弹窗界面 self.setup_UI() self.agent_info = None def setup_UI(self): # 顶部 Frame frm_T = tk.Frame(self) frm_T.grid(column=0,row=0,padx=10) ttk.Label(frm_T, text='使用代理').grid(column=0, row=0, pady=15) self.radVar = tk.IntVar() r_no_use = tk.Radiobutton(frm_T, text='关闭', variable=self.radVar, value=0, command=lambda: self.close_agent()) r_no_use.grid(column=1, row=0) r_use = tk.Radiobutton(frm_T, text='启用', variable=self.radVar, value=1, command=lambda: self.open_agent()) r_use.grid(column=2, row=0) # 中部 Frame frm_M = tk.Frame(self) frm_M.grid(column=0, row=1, columnspan=3) ttk.Label(frm_M, text='地址 *').grid(column=0, row=0, pady=5, padx=10, sticky='W') self.s_addr = tk.StringVar() self.e_addr = tk.Entry(frm_M, textvariable=self.s_addr, state='disabled') self.e_addr.grid(column=1, row=0, columnspan=2, sticky='W,E') ttk.Label(frm_M, text='端口 *').grid(column=0, row=1, pady=5) self.s_port = tk.StringVar() self.e_port = tk.Entry(frm_M, textvariable=self.s_port, state='disabled') self.e_port.grid(column=1, row=1, columnspan=2) ttk.Label(frm_M, text='用户').grid(column=0, row=2, pady=5) self.s_user = tk.StringVar() self.e_user = tk.Entry(frm_M, textvariable=self.s_user, state='disabled') self.e_user.grid(column=1, row=2, columnspan=2) ttk.Label(frm_M, text='密码').grid(column=0, row=3, pady=5) self.s_passwd = tk.StringVar() self.e_passwd = tk.Entry(frm_M, show='*', textvariable=self.s_passwd, state='disabled') self.e_passwd.grid(column=1, row=3, columnspan=2) # 底部Frame frm_B = tk.Frame(self) frm_B.grid(column=0, row=5, columnspan=3) b_ok = ttk.Button(frm_B, text='确定', command=lambda: self.ok()) b_ok.grid(column=0, row=0, pady=15, padx=30) b_cancel = ttk.Button(frm_B, text='取消', command=lambda: self.cancel()) b_cancel.grid(column=1, row=0, pady=15, padx=10) # 关闭代理 Entry 不可编辑状态 def close_agent(self): self.e_addr.config(state='disabled') self.e_port.config(state='disabled') self.e_user.config(state='disabled') self.e_passwd.config(state='disabled') # 开启代理 Entry 可编辑 def open_agent(self): self.e_addr.config(state='normal') self.e_port.config(state='normal') self.e_user.config(state='normal') self.e_passwd.config(state='normal') # 确定按钮 Entry中的值 def ok(self): self.agent_info = [self.s_addr.get(),self.s_port.get(),self.s_user.get(),self.s_passwd.get()] self.destroy() # 销毁窗口 def cancel(self): self.agent_info = None self.destroy()
主窗体添加设置代理按钮
# 底部 设置代理
b_proxy = ttk.Button(frm_M,text="设置代理", width=12, command=lambda: self.set_proxy())
b_proxy.grid(column=0,row=6)
set_proxy()
def set_proxy():
# 接收返回数据
agent = get_info()
get_info()
import agent
def get_info(self):
# 导入agent.py中的类 MyAgentDialog
inputDialog = agent.MyAgentDialog()
inputDialog.setup_UI()
# 等待窗口 destroy 返回数据
inputDialog.wait_window()
# 返回 agent数据
return inputDialog.agent_info
在百度识图和翻译调用函数中,需要传输代理参数。具体如何添加就不多讲了,
# proxies = set_proxy(agent)
# 调用百度文字识别client
# client.setProxies(proxies)
# 翻译调用请求
# response = requests.get(myurl, headers=headers, proxies=proxies)
set_proxy()
解析agent,获取addr,port,user,passwd即可,注proxies是字典类型
重新打开程序的时候,代理设置就会被初始化(初始化代理状态是关闭)。
如果是读取配置文件,那么程序运行后会生成一个config文件;但初衷是只打包成一个exe文件,双击即可运行。
程序初始运行,窗体如上图所示,左侧图片控件内容为空时,未加载指定大小,若插入图片后,左侧Frame会扩展为指定大小,中部和右侧Frame会向右移动,见第五章的程序界面设计效果图;而且底部Frame未显示,需要手动向下放大才能显示Label(Copyright)。不知如何解决,tkinter的窗口调试太麻烦了。
界面如同90年代的Windows 98风格(笑哭),太丑了(无力吐槽)。
以上问题欢迎提供解决方案
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。