尧图精选

基于DeepSeek的翻译工具

🕒 发布时间:2026/9/2 6:03:40 📁 来源:尧图网络
从截图到原位替换一个 Windows 截屏翻译工具的技术沉淀本文整理自 TranslateUtil 这个 Windows 小工具的真实开发过程。核心需求快捷键框选屏幕区域OCR 识别英文AI 翻译成中文再把译文覆盖到原文所在位置尽量保留原文字号、颜色和排版。软件使用需要先配置deepseek的api key 通过这个网址配置。DeepSeek开发平台使用的时候只需要按住 CtrlAlt空格键就可以截图翻译。当然这个快捷键也是支持设置的。支持对翻译的内容追问。2026.9.1更新可以翻译选中的文字。选中文字后还是用翻译快捷键。会先判断是否有选中的内容。如果没有的话。会再启动截图翻译。还可以调整上面翻译的样式优化了翻译后的定位。原图是这样的使用下载绑定的资源运行这里面的exe文件就行了一、这个工具最终长什么样TranslateUtil 是一个 Windows 桌面 exe最终形态非常简单用户按Ctrl Alt Space框选屏幕区域。选区中央显示一个半透明圆形进度提示。系统 OCR 精确定位每一行文字。DeepSeek 多模态模型理解截图上下文并翻译。程序生成一张“替换图”把英文说明替换成中文代码标识符保留原样。选区位置弹出一个无边框覆盖层可切换原文/译文、滚动查看、追问模型。这个工具经过多次需求变化最终放弃了本地小模型统一使用 DeepSeek 多模态接口本地不打包 OCR 模型只调用 Windows 自带的 OCR 做定位。这样 exe 体积较小翻译质量也更稳定。二、整体架构全局热键框选屏幕区域mss 截取选区Windows OCR 逐行定位DeepSeek 多模态逐行翻译生成替换图无边框覆盖层显示原文/译文切换与追问技术栈很轻语言PythonGUI / 覆盖层Tkinter截图mss系统 OCRWindows.Media.Ocr / WinRTAI 翻译DeepSeek 多模态接口图像合成Pillow全局快捷键Windows 低层键盘钩子打包PyInstaller onefile三、核心设计 1让 OCR 负责定位AI 只负责翻译早期版本让 DeepSeek 自己同时返回原文、译文和坐标{items:[{source_text:...,translated_text:...,box:[left,top,right,bottom]}]}看起来省事实际有两个严重问题坐标不准确。模型预测的框经常偏大、偏小或错位导致覆盖层盖不住原文。容易漏行。截图较长时模型会合并、跳过下半段内容出现“翻译没翻译全”。后来改成Windows OCR 负责逐行识别直接使用 OCR 返回的bounding_rect。把 OCR 行按1..N编号和截图一起交给 DeepSeek。DeepSeek 只返回每行对应的line_index、修正后的source_text和translated_text不再返回坐标。核心提示词约束大致是items 数量必须等于上述行数 line_index 必须从 1 到 N 连续完整 不能跳过、合并或新增。 代码声明、标识符、API 名保留原样。请求结构类似messages[{role:user,content:[{type:text,text:prompt},{type:image_url,image_url:{url:encode_image_data_url(image),},},],}]这样定位精度直接来自系统 OCR翻译质量来自多模态模型两者职责清晰。即使模型偶尔漏行还可以用一次纯文本补译请求兜底。四、核心设计 2先生成替换图再显示覆盖层覆盖层不是直接画很多小窗口而是用 Pillow 合成一张完整图片再交给 TkinterCanvas显示。生成替换图的关键顺序是复制原截图。先擦除每个 OCR 原文区域用该区域的背景色填充。再绘制所有中文译文块。# 1. 擦原文forpatchinsource_patches:bg_patchImage.new(RGBA,(w,h),bg(255,))canvas.alpha_composite(bg_patch,(left,top))# 2. 画译文forlayoutinlayouts:bg_patchImage.new(RGBA,(w,h),bg(255,))canvas.alpha_composite(bg_patch,(left,top))draw.multiline_text((leftpadding,toppadding),\n.join(lines),fontfont,fillfg(255,),)这里最重要的经验是先擦原文再画译文。如果直接画译文块遇到译文比原文长、或者后续行被向下推挤时原英文很容易从缝隙里露出来。同时做了几个细节根据原文高度估算目标字号但设置下限避免字太小无法识别。根据原文背景色估算前景色并做对比度修正。代码标识符、类名、方法名、常量名保留原样。中文行数变多时允许覆盖图高于原始选区覆盖层里用滚动条查看。五、核心设计 3覆盖层的按需滚动覆盖层是一个无边框Toplevel内部只有Canvas和一个垂直滚动条。最初滚动条一直显示即使内容正好等于选区高度。后来改成按需显示def_sync_scrollbar(self):ifself.display_image.heightviewport_height:self.scrollbar.grid()self.canvas.configure(yscrollcommandself.scrollbar.set)else:self.scrollbar.grid_remove()self.canvas.configure(yscrollcommand)self.canvas.yview_moveto(0)鼠标滚轮也做了保护只有内容真的溢出、滚动条可见时才滚动def_on_mousewheel(self,event):ifnotself.scrollbar.winfo_ismapped():returnbreakself.canvas.yview_scroll(...)returnbreak覆盖层还提供看原文 / 看译文、追问、关闭三个控制按钮切换视图时重新计算滚动区域。六、核心设计 4拦截全局快捷键pynput.keyboard.GlobalHotKeys能监听快捷键但不能阻止其他应用也收到这个按键。所以后来换成了 Windows 低层键盘钩子WH_KEYBOARD_LL。基本做法hookuser32.SetWindowsHookExW(WH_KEYBOARD_LL,hook_proc,kernel32.GetModuleHandleW(None),0,)在钩子回调里判断当前按下的虚拟键是否组成目标快捷键。命中后返回1表示拦截这次事件不再传给其他应用ifsuppress:return1returnuser32.CallNextHookEx(0,n_code,w_param,l_param)需要同时处理WM_KEYDOWN、WM_SYSKEYDOWN、WM_KEYUP、WM_SYSKEYUP并维护当前按下的按键集合。触发后还要吞掉这个组合键后续的keyup避免出现“只吞了一半”的奇怪状态。一个诚实的结论是Windows 没有绝对意义上的“全局最高优先级热键”。低层钩子已经能挡住普通应用但如果另一个程序也安装了更晚加载的低层钩子它仍可能先看到事件。要做到绝对优先只能上驱动级方案普通桌面工具通常没有必要。七、核心设计 5Tkinter 的线程模型AI 翻译和截图处理不能阻塞主线程否则界面会卡死。项目采用了一个很经典的模式工作线程只负责截图、OCR、AI 请求。工作线程通过queue.Queue把事件发给主线程。Tkinter 主线程用after周期性消费队列。def_process_region(self,region):try:imagecapture_region(region)itemsself.deepseek.translate_image(image,ocr_lines)self._post_ui(show_result,(region,image,items))exceptExceptionasexc:self._post_ui(error,exc)def_drain_ui_queue(self):whileTrue:action,payloadself.ui_queue.get_nowait()ifactionshow_result:self._show_result(...)elifactionshow_progress:self._show_progress(...)self.root.after(50,self._drain_ui_queue)这样避免了“在工作线程里直接操作 Tk 控件”导致的各种随机崩溃。进度弹窗也通过这个队列关闭翻译完成后强制销毁。八、追问窗口与 Markdown 显示翻译结果旁边有一个“追问”按钮点击后打开聊天式窗口。这里没有引入复杂前端而是直接用tk.Text做轻量 Markdown 渲染。支持了标题加粗、斜体行内代码和代码块引用无序列表链接快捷提问按钮解释这段文字通俗易懂解释总结内容这部分的经验是小工具不需要上 WebViewtk.Text加标签就能完成够用的富文本显示。九、PyInstaller 打包最终产物是一个 onefile exepyinstaller--noconfirm--clean--onefile--windowed--name TranslateUtil translate_util.py依赖包括mss Pillow pynput requests pystray winrt-Windows.Foundation winrt-Windows.Foundation.Collections winrt-Windows.Globalization winrt-Windows.Graphics.Imaging winrt-Windows.Media.Ocr winrt-Windows.Storage.Streams winrt-runtime pyinstaller打包时最容易踩的坑是旧的 exe 还在运行PyInstaller 覆盖文件时会出现PermissionError。因此构建前要先停掉所有TranslateUtil进程。十、踩坑清单模型自己返回坐标不靠谱定位交给系统 OCRAI 只翻译。翻译漏行用 OCR 行号约束模型必须逐行返回并加补译兜底。覆盖层露出原文先擦除原文区域再绘制译文。滚动条常驻很丑按内容高度动态显示/隐藏。全局热键冲突从GlobalHotKeys换成低层键盘钩子。Tkinter 多线程崩溃所有 UI 操作回到主线程通过队列通信。翻译过程中用户不知道状态在选区中央显示半透明圆形进度动画。PyInstaller 覆盖失败先检查并停止旧进程再打包。十一、可以复用的结论这个项目最终沉淀下来的核心思路只有三句话OCR 负责“在哪里”AI 负责“翻译成什么”。覆盖层先生成完整替换图再显示。所有系统级能力都通过最小、可替换的边界接入。这套结构不只适合截屏翻译也适合任何“识别屏幕内容然后原位替换或增强显示”的桌面工具例如截图转表格、图片公式识别、UI 文本替换预览等。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →