LunaTranslator 在 HOOK 模式下临时使用 OCR:`进行一次OCR` 按钮与快捷键全解析
2026/9/15 13:59:40 网站建设 项目流程

LunaTranslator 在 HOOK 模式下临时使用 OCR:进行一次OCR按钮与快捷键全解析

【免费下载链接】LunaTranslator视觉小说翻译器 / Visual Novel Translator项目地址: https://gitcode.com/GitHub_Trending/lu/LunaTranslator

LunaTranslator 是一款面向视觉小说(VN/AVG)场景的翻译工具,其最常用的文本提取方式是HOOK 模式(通过内存注入挂钩游戏引擎,自动提取对话文本)。但游戏中的菜单、选择肢(選択肢)、标题栏等非对话文本往往不会被 HOOK 捕获。本文围绕官方文档 docs/ja/gooduse/useocrinhook.md 讲解的内置解决方案——在 HOOK 模式下临时执行一次 OCR——展开,并结合仓库源码(translatorUI.py、rangeselect.py、ocrutil.py)深入说明其实现原理、按钮与快捷键配置,帮助读者彻底告别"切模式—选范围—切回来"的繁琐操作。

痛点:HOOK 模式的固有缺漏

HOOK 模式通过挂钩游戏进程内的文本输出函数来截获文本,因此凡是游戏引擎没有以文本形式渲染、而是以图片或自绘控件方式显示的内容,HOOK 都无法捕获。典型场景包括:

  • 游戏主菜单(メニュー)与暂停菜单;
  • 选择肢(選択肢)选项框;
  • 系统提示、地图 UI、状态栏等非对话文本;
  • 使用特殊渲染引擎的过场动画字幕。

面对这些文本,传统做法是:切换到 OCR 模式 → 手动框选识别范围 → 识别完成后再切换回 HOOK 模式。这个过程步骤多、打断游戏节奏,尤其在剧情分支处频繁出现选择肢时体验很差。

内置解决方案:进行一次OCR再次进行OCR

文档明确指出,LunaTranslator 早已内置了针对该场景的方案,无需手动切换文本源模式。核心是两个功能:

  1. 进行一次OCR(按钮图标 ,对应源码配置ocr_once
  2. 再次进行OCR(按钮图标 ,对应源码配置ocr_once_follow

其使用流程为:

  1. HOOK 模式下,点击「进行一次OCR」按钮或按对应快捷键;
  2. 屏幕上弹出范围选择框,拖拽框选要识别的文本区域;
  3. 松开鼠标后只执行一次 OCR,识别结果直接进入翻译流程;
  4. OCR 随即结束,工具无缝回到 HOOK 模式,继续自动提取游戏对话文本。

也就是说,这是一个"临时借用 OCR 能力补齐 HOOK 缺漏"的机制,识别完毕后文本源自动恢复为 HOOK,玩家的翻译流程不会被打断。

固定位置选择肢:用「再次进行OCR」复用上次选区

对于位置固定不变的选择肢(例如始终显示在屏幕底部、仅内容变化的选项),每次框选显然重复且低效。此时应使用「再次进行OCR」按钮或快捷键:它会直接沿用上一次「进行一次OCR」框选的范围再次执行一次 OCR,无需重新拖拽选区。

源码级原理剖析

配置项定义

两个功能的默认配置位于 defaultconfig/config.json:

"ocr_once": { "use": true, "tip": "进行一次OCR", "icon": "fa.crop", "align": 2 }, "ocr_once_follow": { "use": false, "tip": "再次进行OCR", "icon": "fa.spinner", "align": 2 }

关键信息:

  • ocr_once的默认图标是fa.crop(裁剪/框选图标),默认启用"use": true);
  • ocr_once_follow的默认图标是fa.spinner(旋转/再次执行图标),默认未启用("use": false),需用户在工具栏配置中手动打开;
  • 两按钮默认都排在align: 2(右侧工具栏)区域。

主界面实现(translatorUI.py)

主界面的核心实现位于 gui/translatorUI.py:

  • 定义信号ocr_once_signal(第 67 行);
  • ocr_once_function(第 343-348 行)中:
def ocr_once_function(self): def ocroncefunction(rect, img=None): self.ocr_once_follow_rect = rect # 记录本次选区,供“再次进行OCR”复用 self.ocr_do_function(rect, img) rangeselct_function(ocroncefunction, hideshow=True)
  • ocr_do_function(第 334-341 行)负责真正执行截图与识别:
@threader def ocr_do_function(self, rect, img=None): if not img: img = imageCut(0, rect) result = ocr_run(img) result = result.maybeerror() if result: gobject.base.textgetmethod(result, is_auto_run=False)
  • 工具栏绑定(第 582-586 行):
("ocr_once", self.ocr_once_signal.emit), ( "ocr_once_follow", lambda: self.ocr_do_function(self.ocr_once_follow_rect), ),

可以看到,ocr_once走"框选 → 记录选区 → 执行"流程,而ocr_once_follow直接复用self.ocr_once_follow_rect这个上次记录的选区(初始值为None,见第 778 行,因此在未执行过一次「进行一次OCR」前,直接使用「再次进行OCR」是无效的)。

选区交互(rangeselect.py)

rangeselct_function定义在 gui/rangeselect.py,其工作方式:

  1. hideshow=True(一次OCR场景即如此),会先把翻译窗口与已有 OCR 范围框临时移出屏幕(移动到(-9999, -9999)),并调用textsource.pause_recognition()暂停当前文本源识别,避免与选区操作互相干扰(第 427-441 行);
  2. 调用NativeUtils.CreateSelectRangeWindow_CB创建原生选区窗口(第 470-479 行),其外观受ocrselectalpha(选区遮罩透明度,默认 0.3)、ocrrangecolor(选区框颜色,默认#000000)、ocrrangewidth(框线宽度,默认 1)等全局配置控制;
  3. 回调__cb(第 461-468 行)中计算规范化后的矩形(自动处理拖拽方向导致的 x1>x2、y1>y2),截取对应图像区域,调用reset()恢复窗口位置并resume_recognition()恢复文本源识别,最后把rectpix交给回调(即ocr_once_function里的ocroncefunction)。

这解释了文档中"选取完范围后无缝回到 HOOK 模式"的机制:选区窗口关闭的同时文本源识别即被恢复

OCR 引擎调用(ocrutil.py)

截图与识别由 myutils/ocrutil.py 承担:

  • imageCut(hwnd, rect)(第 12-19 行):通过NativeUtils.GdiCropImage截取矩形区域图像;
  • ocr_run(qimage)(第 62 行起):调用ocr_init()按 config.json 中ocr段第一个use为 true 的引擎初始化(第 41-59 行),随后执行识别;
  • 识别结果通过gobject.base.textgetmethod(result, is_auto_run=False)进入文本处理与翻译管线,与 HOOK 抓取到的文本走同一套后续流程。

因此,"一次OCR"并不是切换到 OCR 文本源,而是直接调用 OCR 引擎执行单次识别,从机制上保证了识别完成后仍停留在 HOOK 模式。

一个常见误解:这不是 OCR 模式的按钮

文档特别强调了一个高频误用场景:

由于这个按钮的图标与 OCR 模式下"选取识别范围"按钮默认相同(都是fa.crop),很多原本想用 OCR 的用户误以为这就是 OCR 开关,于是在 HOOK 模式下点它框选范围后,发现并没有自动翻译。

原因在于:

  • 本按钮(ocr_once)只执行一次识别,不会持续对选区内的画面进行循环识别,因此后续画面变化不会自动翻译;
  • 真正的"OCR 模式"切换后,工具栏才会显示 OCR 模式专属的按钮(如持续选区识别、隐藏/显示范围框hideocrrange等,见 config.json)。

判断方法很简单:若需要持续识别某区域并自动翻译,应切换到 OCR 模式并使用其中的"选取 OCR 范围"按钮;若只是 HOOK 模式下偶尔补充识别一次菜单/选择肢,则用「进行一次OCR」。

快捷键配置

两个功能均支持快捷键,快捷键编号与默认名称定义在 defaultconfig/config.json:

快捷键编号名称说明
_26进行一次OCR弹出选区框,执行一次识别
_26_1再次进行OCR沿用上次选区,执行一次识别

快捷键的触发绑定位于 gui/setting/hotkey.py:

"_26": gobject.base.translation_ui.ocr_once_signal.emit, "_26_1": lambda: gobject.base.translation_ui.ocr_do_function( gobject.base.translation_ui.ocr_once_follow_rect ),

可以看到_26等价于点击「进行一次OCR」按钮(发信号 →ocr_once_function→ 框选 → 记录选区 → 识别),_26_1则等价于「再次进行OCR」(直接用ocr_once_follow_rect执行ocr_do_function)。此外在快捷键分组中两者都属于OCR 组(见 hotkey.py 第 300 行["OCR", ["_13", "_14", "_14_1", "_26", "_26_1", ...]]),可在设置 → 快捷键界面中为它们分配任意按键组合。

最佳实践小结

  • 场景匹配:HOOK 捕获不到的菜单、选择肢、系统提示 → 使用「进行一次OCR」;不要在 HOOK 模式下期望该按钮提供持续翻译。
  • 固定位置选择肢:第一次用「进行一次OCR」框选后,后续直接用「再次进行OCR」(_26_1)或快捷键复用选区,省去重复框选。
  • 前置条件:「再次进行OCR」依赖上一次「进行一次OCR」记录的选区,程序启动后未框选过时直接使用会因选区为空而无效,需要先框选一次。
  • 与 OCR 模式的分工:需要持续、自动识别固定区域(例如无 HOOK 支持的游戏全程字幕)时,请切换到 OCR 模式并使用其"选取 OCR 范围"功能;HOOK 模式下的「进行一次OCR」只做单次补漏。
  • 自定义外观:选区框颜色(ocrrangecolor)、遮罩透明度(ocrselectalpha)、框线宽度(ocrrangewidth)可在全局配置中调整,让选区更清晰可见。

掌握「进行一次OCR / 再次进行OCR」这两个内置工具,即可在不打断 HOOK 自动翻译流的前提下,快速补捉菜单与选择肢文本,让 LunaTranslator 在混合 UI 的游戏场景下也能保持流畅的沉浸式翻译体验。

【免费下载链接】LunaTranslator视觉小说翻译器 / Visual Novel Translator项目地址: https://gitcode.com/GitHub_Trending/lu/LunaTranslator

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询