lemon-manga-translator
일본어 만화 페이지를 한국어로 번역하는 파이프라인입니다. 학습된 검출 모델로 글자와 말풍선을 찾고, Vision LLM 한 번의 호출로 글자 묶음·원문·번역을 받은 뒤, 배치할 수 있는 영역의 원문만 지우고 한국어를 그립니다.
글자·말풍선 검출 → Vision LLM 읽기·번역 → 배치 검증 → 원문 삭제 → 한국어 합성
사용법
from lemon_manga_translator import MangaTranslator
from PIL import Image
translator = MangaTranslator(
openrouter_api_key="sk-or-...",
openrouter_model="google/gemini-3.1-flash-lite",
device="cpu", # "cuda"면 onnxruntime 대신 onnxruntime-gpu를 설치해야 합니다.
mask_background=False, # True면 LLM에 보내는 페이지에서 글자 영역 밖을 흰색으로 가립니다.
)
translator.prepare() # HuggingFace에서 모델을 내려받아 캐시합니다.
result = translator.translate(Image.open("page.jpg"))
result.image.save("output.png")
- 결과는
TranslationResult(image, vision_results, vision_error)입니다.vision_error는 LLM 호출이 2회 모두 실패했을 때만 채워지며, 이때 원문을 그대로 남깁니다. - Vision 호출 설정(temperature
0, reasoningminimal, 최대 2회 시도, 요청당 120초 제한)은 검수한 값으로 고정되어 있습니다. 프롬프트는prompts/vision_system.txt입니다. - 대사·내레이션·제목·이름표·표지판을 번역합니다. 효과음·포장 상품명·저작권 표시·읽을 수 없는 글자, 그리고 번역에 가나나 기호만 남은 경우는 원문을 보존합니다.
mask_background=True는 액션 장면처럼 LLM 콘텐츠 필터에 걸리는 페이지를 위한 옵션입니다. 말풍선 확대 이미지는 가리지 않습니다.- Docker 이미지에서는 빌드 단계에서
MangaTranslator.pre_download()를 실행해 모델을 미리 캐시합니다.
진행 상황과 중간 결과
result = translator.translate(image, on_progress=print, on_stage_done=handle)
on_progress는 단계를 시작할 때PipelineStage(detect→translate→inpaint→render)로 호출됩니다. 글자가 없는 페이지는detect에서 끝납니다.on_stage_done은 단계가 끝날 때StageResult로 호출됩니다.
| 단계 | 채워지는 필드 |
|---|---|
DETECT |
text_blocks. 자동 번역에서는 LLM이 글자를 묶은 뒤에 보고합니다. |
TRANSLATE |
vision_results (block_index, no_translate, ko_translation) |
INPAINT |
image (원문을 지운 이미지) |
RENDER |
image (최종 이미지) |
번역을 고쳐 다시 그리기
result = translator.translate(image, translations=edited_results, text_boxes=previous_boxes)
translations를 넘기면 LLM을 호출하지 않고 그 번역으로 다시 그립니다.no_translate=True인 블록은 원문을 남기고,no_translate=False에 빈 번역을 넘기면 원문만 지웁니다.- 같은 인스턴스는 최근 64개 이미지의 글자 묶음을 기억합니다. 캐시가 만료되었거나 프로세스가 재시작되었다면 이전
DETECT의 bbox를text_boxes로 함께 넘겨야 하며, 둘 다 없으면ValueError가 발생합니다. text_boxes에서 좌표를 바꾸거나 추가한 박스는 그 사각형 전체를 삭제·배치 영역으로 사용합니다. 좌표가 같은 박스는 검출 mask를 유지합니다.
디버그 산출물
translate(image, debug_dir="debug/page_001")로 단계별 산출물을 저장합니다. rude-image-translator가 이 파일 이름으로 S3에 올리고 관리자 화면에 표시합니다.
| 파일 | 내용 |
|---|---|
00_input.png, 00_params.json |
입력 이미지, 모델과 mask_background |
02_bboxes.png, 02_text_blocks.json |
LLM이 묶은 뒤의 글자 블록과 검출 점수 |
05a_annotated.png |
LLM에 보낸 번호 박스 이미지 |
05_vision.json, 05_cost.json |
블록별 번역 결과, 토큰 사용량과 비용(원) |
03c_mask_filtered_overlay.png |
실제로 지운 영역 |
04_inpainted.png |
원문을 지운 이미지 |
05b_render_bboxes.png |
번역 블록의 bbox(빨강)와 배치 영역(초록) |
06_final.png |
최종 결과 |
로컬 이미지는 다음 스크립트로 번역해 볼 수 있습니다.
uv run --env-file .env python scripts/translate.py page.jpg pages/ --out-dir out
개발
uv sync
uv run pytest
v*태그를 push하면 GitHub Actions가 PyPI에 배포합니다.
모델·폰트 출처
| 구성 요소 | 출처 | 라이선스 |
|---|---|---|
| 글자·말풍선 검출 | mayocream/koharu-layout-rfdetr-seg-2xl-1152의 ONNX 변환본 ShiniShiho/koharu-layout-rfdetr-seg-2xl-1152-onnx | other (Manga109 학술 용도 데이터로 학습) |
| AOT 인페인팅 | manga-image-translator beta-0.3의 체크포인트를 ONNX로 변환해 lemondouble/lemon-manga-translator에 배포 | GPL-3.0 |
assets/fonts/Jua-Regular.ttf |
Google Fonts: Jua | SIL OFL 1.1 |
assets/fonts/PretendardJP-Regular.otf |
orioncactus/pretendard | SIL OFL 1.1 |
License
Metadata
Release files for lemon-manga-translator 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lemon_manga_translator-0.1.0.tar.gz | 3.5 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lemon_manga_translator-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 7.0 MB
Release files / lemon_manga_translator-0.1.0.tar.gz
| Download URL | lemon_manga_translator-0.1.0.tar.gz |
|---|---|
| Size | 3.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
89b677a4552ee65d837c20996f2be34c99f492d08d4965b35bf0641379057c45
|
|
BLAKE2b-256 checksum How to use checksums |
154695a80bee44b78a093dedb59de080c3894ec9c4b0a8a927c3dd28c6aa2608
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / lemon_manga_translator-0.1.0-py3-none-any.whl
| Download URL | lemon_manga_translator-0.1.0-py3-none-any.whl |
|---|---|
| Size | 3.5 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6d3bfeccbed5fdb9aa3375fbddcfdc94beb3a59b4e90aef06db7349eb642f3a
|
|
BLAKE2b-256 checksum How to use checksums |
58ff0e48caff8e6ab892a8bc00dcb4fa25ea18b9744637da55f79333a0b6e920
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log