Koharu 的工作方式¶
Koharu 围绕一条漫画翻译页面管线构建。用户看到的流程很简单,但实现上会刻意把版面分析、分割、OCR、修复、翻译和渲染拆成独立阶段。
管线总览¶
flowchart LR
A[输入漫画页面] --> B[Detect 阶段]
B --> B1[版面分析]
B --> B2[分割掩码]
B --> B3[字体提示]
B1 --> C[OCR 阶段]
B2 --> D[修复阶段]
C --> E[LLM 翻译阶段]
D --> F[渲染阶段]
E --> F
F --> G[本地化页面或 PSD 导出]
在公开的管线层面,Koharu 按以下顺序运行:
DetectOCRInpaintLLM GenerateRender
关键实现细节在于,Detect 本身已经是一个多模型阶段:
PP-DocLayoutV3负责找出类似文本的版面区域和阅读顺序comic-text-detector生成逐像素的文本概率图YuzuMarker.FontDetection估计后续渲染要用到的字体与颜色提示
正因为如此,Koharu 才能让一个模型负责“文字应该属于页面哪里”,另一个模型负责“究竟哪些像素应该被擦掉”。
每个阶段产出什么¶
| 阶段 | 主要模型 | 主要输出 |
|---|---|---|
| Detect | PP-DocLayoutV3, comic-text-detector, YuzuMarker.FontDetection |
文本块、分割掩码、字体提示 |
| OCR | PaddleOCR-VL-1.5 |
每个文本块识别出的原文 |
| Inpaint | lama-manga |
去除原文后的页面 |
| LLM Generate | 本地 GGUF LLM 或远程提供商 | 译文 |
| Render | Koharu renderer | 最终本地化页面或导出内容 |
为什么要拆成多阶段¶
漫画页面比普通文档 OCR 更难:
- 气泡形状不规则,经常弯曲
- 日文可能是纵排,旁边的注释或 SFX 又可能是横排
- 文本会压在背景、网点、速度线和分镜边框之上
- 阅读顺序本身就是页面结构的一部分,不只是像素问题
因此通常不能指望一个模型把所有事情都做好。Koharu 会先估计版面,再对裁剪出的区域做 OCR,再用分割掩码做清理,最后才把文本交给 LLM 翻译。
实现结构¶
从源码结构看,管线入口在 koharu-app/src/pipeline.rs,视觉栈的协调逻辑主要在 koharu-app/src/ml.rs。
一些重要的实现细节:
- detect 阶段先跑
PP-DocLayoutV3,再把文本类标签转换成TextBlock - OCR 之前会先去重高度重叠的框
- 文本方向会基于区域长宽比推断,这样纵排漫画文本能更早进入正确路径
- OCR 运行在裁剪后的文本区域上,而不是整页图像
- 修复阶段使用的是当前分割掩码,而不是简单矩形框
- 当你选择远程 LLM 时,Koharu 发送出去的是 OCR 文本,而不是整页图像
为什么这套技术栈很重要¶
Koharu 使用:
本地优先设计¶
默认情况下,Koharu 会:
- 在本地运行视觉模型
- 在本地运行本地 LLM
如果你配置了远程 LLM 提供商,Koharu 只会把待翻译文本发送给该提供商。
想看更深的技术版本?¶
请参见 技术深潜,了解模型类型、分割掩码理论、基于 FFT 的修复,以及维基百科图示和官方模型卡的背景说明。关于渲染器、纵排写字模式和当前版面限制,请参见 文本渲染与纵排 CJK 布局。