import os
import pytesseract
from PIL import ImageGrab
import tkinter as tk
import time
import threading
import cv2
import numpy as np
import requests
import json
# 动态检测Tesseract路径
import os # 确保os模块在最外层导入
try:
# 优化后的路径检测逻辑
import winreg
# 1. 先尝试系统PATH环境变量
try:
pytesseract.pytesseract.tesseract_cmd = 'tesseract'
# 添加调试信息
print(f"尝试PATH中的tesseract路径: {pytesseract.pytesseract.tesseract_cmd}")
# 验证PATH是否有效
if not os.path.exists(pytesseract.pytesseract.tesseract_cmd):
raise FileNotFoundError(f"未找到文件: {pytesseract.pytesseract.tesseract_cmd}")
except Exception:
# 2. 检查默认安装路径
default_paths = [
r"C:\Program Files\Tesseract-OCR\tesseract.exe",
r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
r"D:\Tesseract-OCR\tesseract.exe", # 常见第三方安装路径
r"C:\Users\{}\AppData\Local\Tesseract-OCR\tesseract.exe".format(os.getenv('USERNAME')),
os.path.expanduser(r"~\AppData\Local\Programs\Tesseract-OCR\tesseract.exe"),
r"C:\Users\Public\Tesseract-OCR\tesseract.exe", # 公共用户目录
r"C:\Tesseract-OCR\tesseract.exe", # 根目录安装
os.path.expandvars(r"%LOCALAPPDATA%\Tesseract-OCR\tesseract.exe"), # 环境变量路径
r"C:\Program Files\WindowsApps\*Tesseract*" # Windows应用商店安装路径
]
found = False
# 修复缩进并优化路径检测
for path in default_paths:
# 使用os.path.expandvars处理环境变量
expanded_path = os.path.expandvars(os.path.expanduser(path))
if os.path.exists(expanded_path):
pytesseract.pytesseract.tesseract_cmd = expanded_path
found = True
break
if not found:
# 3. 合并所有可能路径并进行统一检测
all_paths = list({
r"C:\Program Files\Tesseract-OCR\tesseract.exe",
r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
r"C:\Users\{}\AppData\Local\Tesseract-OCR\tesseract.exe".format(os.getenv('USERNAME')),
os.path.expanduser(r"~\AppData\Local\Programs\Tesseract-OCR\tesseract.exe"),
r"D:\Tesseract-OCR\tesseract.exe",
r"C:\Users\Public\Tesseract-OCR\tesseract.exe",
r"C:\Program Files\WindowsApps\*Tesseract*",
os.path.expandvars(r"%LOCALAPPDATA%\Programs\Tesseract-OCR\tesseract.exe")
})
print("正在扫描所有已知安装路径...")
for path in all_paths:
try:
expanded_path = os.path.expandvars(os.path.expanduser(path))
# 处理通配符路径
if '*' in expanded_path:
import glob
matches = glob.glob(expanded_path)
if matches:
expanded_path = sorted(matches, reverse=True)[0] # 取最新版本
if os.path.exists(expanded_path):
print(f"找到有效路径: {expanded_path}")
pytesseract.pytesseract.tesseract_cmd = expanded_path
found = True
break
except Exception as e:
print(f"路径检测异常: {str(e)}")
# 最终PATH环境变量检查
if not found:
print("正在系统PATH中搜索...")
path_dirs = [os.path.expandvars(d) for d in os.getenv('PATH').split(';') if d.strip()]
for dir_path in path_dirs:
test_path = os.path.join(dir_path, 'tesseract.exe')
print(f"检查PATH目录: {test_path}")
if os.path.isfile(test_path):
print(f"在系统PATH中找到: {test_path}")
pytesseract.pytesseract.tesseract_cmd = test_path
found = True
break
# 最终验证
if not found:
print("错误: 所有检测方式均未找到Tesseract")
raise RuntimeError(
"Tesseract OCR安装问题解决方案:\n\n"
"1. 安装Tesseract OCR:\n"
" - 方法一:使用winget快速安装\n"
" winget install -e --id UB-Mannheim.TesseractOCR\n\n"
" - 方法二:手动下载安装包\n"
" https://github.com/UB-Mannheim/tesseract/wiki\n\n"
"2. 配置环境变量:\n"
" - 右键'此电脑' → 属性 → 高级系统设置 → 环境变量\n"
" - 在系统变量的Path中添加:\n"
" C:\\Program Files\\Tesseract-OCR\n\n"
"3. 验证安装:\n"
" - 打开新的CMD窗口执行:\n"
" tesseract --version\n\n"
"4. 注意事项:\n"
" - 安装时务必勾选'Add to PATH'选项\n"
" - 需要重启所有CMD/VSCode窗口使PATH生效\n"
" - 如果已安装,请检查杀毒软件是否误删文件\n"
" - 32位系统需安装32位版本"
)
except Exception as e:
raise RuntimeError(
"Tesseract OCR安装问题解决方案:\n\n"
"1. 安装Tesseract OCR:\n"
" - 方法一:使用winget快速安装\n"
" winget install -e --id UB-Mannheim.TesseractOCR\n\n"
" - 方法二:手动下载安装包\n"
" https://github.com/UB-Mannheim/tesseract/wiki\n\n"
"2. 配置环境变量:\n"
" - 右键'此电脑' → 属性 → 高级系统设置 → 环境变量\n"
" - 在系统变量的Path中添加:\n"
" C:\\Program Files\\Tesseract-OCR\n\n"
"3. 验证安装:\n"
" - 打开新的CMD窗口执行:\n"
" tesseract --version\n\n"
"4. 注意事项:\n"
" - 安装时务必勾选'Add to PATH'选项\n"
" - 需要重启所有CMD/VSCode窗口使PATH生效\n"
" - 如果已安装,请检查杀毒软件是否误删文件\n"
" - 32位系统需安装32位版本"
) from e
class TranslationApp:
def __init__(self):
self.root = tk.Tk()
self.root.overrideredirect(True)
self.root.attributes('-topmost', True)
self.root.attributes('-alpha', 0.9)
# 创建主框架
self.frame = tk.Frame(self.root, bg='#2C3E50')
self.frame.pack(padx=5, pady=5)
# 创建标签显示翻译结果
self.label = tk.Label(self.frame, text="等待翻译...",
font=('微软雅黑', 12),
bg='#2C3E50', fg='#ECF0F1',
wraplength=300, justify='left',
padx=10, pady=5)
self.label.pack()
self.running = True
self.update_interval = 2 # 截图间隔2秒
self.last_text = "" # 存储上一次识别的文本
# 翻译API的请求头
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
self.setup_ui()
self.start_capture()
def translate_text(self, text):
try:
# 检测文本语言
is_chinese = any('\u4e00' <= c <= '\u9fa5' for c in text)
from_lang = 'zh' if is_chinese else 'en'
to_lang = 'en' if is_chinese else 'zh'
# 构建API URL
url = f"https://fy.httpcn.com/bdaify/?s1={from_lang}&t1={to_lang}&q={text}"
# 发送翻译请求
response = requests.get(url, headers=self.headers, timeout=5)
result = response.json()
if 'result' in result and 'trans_result' in result['result']:
return result['result']['trans_result'][0]['dst']
else:
print(f"翻译错误: {result}")
return None
except Exception as e:
print(f"翻译过程出错: {str(e)}")
return None
def capture_and_translate(self):
try:
# 获取屏幕截图
screenshot = ImageGrab.grab()
# 转换为灰度图像并增强对比度
img_np = np.array(screenshot)
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
enhanced = cv2.convertScaleAbs(gray, alpha=1.2, beta=0)
# OCR识别文本
text = pytesseract.image_to_string(enhanced, lang='eng')
text = text.strip()
# 如果识别到的文本与上次相同,则跳过
if text and text != self.last_text:
self.last_text = text
# 翻译文本
translation = self.translate_text(text)
if translation:
self.update_display(f"原文: {text}\n译文: {translation}")
else:
self.update_display("翻译失败,请检查网络连接")
except Exception as e:
self.update_display(f"错误: {str(e)}")
def update_display(self, text):
try:
self.label.config(text=text)
# 自动调整窗口大小
self.root.update_idletasks()
self.frame.update_idletasks()
self.root.geometry('')
except Exception as e:
print(f"更新显示出错: {str(e)}")
def start_capture(self):
def capture_loop():
while self.running:
self.capture_and_translate()
time.sleep(self.update_interval)
thread = threading.Thread(target=capture_loop, daemon=True)
thread.start()
def setup_ui(self):
# 添加控制按钮框架
control_frame = tk.Frame(self.frame, bg='#2C3E50')
control_frame.pack(fill='x', pady=(5,0))
# 添加开始/暂停按钮
self.toggle_btn = tk.Button(control_frame, text="暂停",
command=self.toggle_capture,
bg='#3498DB', fg='white',
relief='flat', width=6)
self.toggle_btn.pack(side='left', padx=2)
# 添加退出按钮
exit_btn = tk.Button(control_frame, text="退出",
command=self.exit_app,
bg='#E74C3C', fg='white',
relief='flat', width=6)
exit_btn.pack(side='right', padx=2)
# 绑定拖动事件
self.label.bind('<Button-1>', self.start_move)
self.label.bind('<B1-Motion>', self.on_move)
def toggle_capture(self):
self.running = not self.running
btn_text = "暂停" if self.running else "开始"
btn_color = "#3498DB" if self.running else "#2ECC71"
self.toggle_btn.config(text=btn_text, bg=btn_color)
def start_move(self, event):
self._drag_start_x = event.x
self._drag_start_y = event.y
def on_move(self, event):
self.target_x = self.root.winfo_x() - self._drag_start_x + event.x
self.target_y = self.root.winfo_y() - self._drag_start_y + event.y
def update_position(self):
if hasattr(self, 'target_x'):
current_x = self.root.winfo_x()
current_y = self.root.winfo_y()
dx = (self.target_x - current_x) * 0.3
dy = (self.target_y - current_y) * 0.3
self.root.geometry(f"+{int(current_x + dx)}+{int(current_y + dy)}")
self.root.after(10, self.update_position)
def exit_app(self):
self.running = False
self.root.destroy()
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = TranslationApp()
app.run()
这个API每天的免费配额很少,建议换别的API进行调试,初学者也不知道哪里有渠道获得更好的又免费的翻译API地址。
希望这个项目能够帮助到更多像我一样的编程初学者,让我们一起在学习编程的旅程中探索更多的可能性!如果你对这个项目感兴趣,欢迎提出建议或参与开发!
附上源码:
蓝奏:https://wwdd.lanzouw.com/iJqaA2nld2pc 密码:52pj