Koharu-inspired manga translation pipeline (JA->KO) in Python
Project description
lemon-manga-translator
일본어 → 한국어 만화(망가) 자동 번역 파이프라인.
한 페이지를 받아 텍스트 영역을 검출하고, Vision LLM으로 SFX 분류 + 번역을 동시에 수행한 뒤, AOT 인페인팅으로 원문을 지우고 그 위에 한국어 텍스트를 렌더한다.
Quick Start
pip install lemon-manga-translator
from lemon_manga_translator import MangaTranslator
from PIL import Image
mt = MangaTranslator(
openrouter_api_key="sk-or-...",
openrouter_model="google/gemini-3.1-flash-lite-preview",
)
mt.prepare() # HuggingFace에서 ONNX 모델 자동 다운로드
image = Image.open("page.jpg")
result = mt.translate(image)
result.save("output.png")
prepare() 호출 시 lemondouble/lemon-manga-translator에서 ONNX 모델(CTD 77 MB + AOT 23 MB)을 다운로드한다. 이후 캐시되어 재다운로드하지 않는다.
로컬 모델 사용
mt = MangaTranslator(
openrouter_api_key="sk-or-...",
openrouter_model="google/gemini-3.1-flash-lite-preview",
model_source="/path/to/local/models", # HF 대신 로컬 경로
)
파이프라인
원본 이미지 ──▶ 1) CTD 검출 ──▶ 2) 마스크 제한 ──▶ 3) Vision LLM ──▶ 4) SFX 드롭
│
▼
최종 이미지 ◀── 7) 텍스트 렌더 ◀── 6) 말풍선 확장 ◀── 5) AOT 인페인트
| 단계 | 설명 |
|---|---|
| 1) CTD 검출 | YOLOv5 bbox + UNet 마스크로 텍스트 영역을 검출한다. UNet이 잡고 YOLO가 놓친 영역은 connected component로 보조 복구. |
| 2) 마스크 제한 | YOLO bbox 밖의 마스크 픽셀을 제거해 페이지 번호·잡글자를 인페인트 대상에서 뺀다. |
| 3) Vision LLM | 페이지에 번호 박스를 그려 OpenRouter Vision API에 한 번만 호출. 각 블록에 대해 SFX 여부 + 한국어 번역을 JSON으로 받는다. |
| 4) SFX 드롭 | SFX(의성어/효과음)로 분류된 블록을 마스크에서 제거. 그림의 일부이므로 지우지 않는다. |
| 5) AOT 인페인트 | AOT-GAN으로 마스크된 텍스트를 자연스러운 배경으로 채운다. |
| 6) 말풍선 확장 | 인페인트 결과에 flood fill을 걸어 말풍선 전체 영역을 찾고, 렌더 영역을 확장한다. |
| 7) 텍스트 렌더 | 확장된 영역 안에 한국어 번역을 최대 폰트 크기로 이진탐색하여 렌더한다. 폰트: Jua(primary) + PretendardJP(fallback). |
Docker
pre_download()로 빌드 시 모델을 미리 캐싱하면 컨테이너 시작 시 다운로드 없이 바로 사용할 수 있다.
FROM python:3.11-slim
RUN pip install lemon-manga-translator
# 빌드 시 ONNX 모델을 캐시에 다운로드 (세션 로드 없음)
RUN python -c "from lemon_manga_translator import MangaTranslator; \
MangaTranslator.pre_download()"
COPY server.py .
CMD ["python", "server.py"]
# server.py — prepare()는 캐시에서 즉시 로드
mt = MangaTranslator(
openrouter_api_key=os.environ["OPENROUTER_API_KEY"],
openrouter_model="google/gemini-3.1-flash-lite-preview",
)
mt.prepare()
Debug
from lemon_manga_translator.api.debug_translator import DebugTranslator
dt = DebugTranslator(
openrouter_api_key="sk-or-...",
openrouter_model="google/gemini-3.1-flash-lite-preview",
)
dt.prepare()
image = Image.open("page.jpg")
result = dt.translate(image, debug_dir="./debug/")
result.detection # CTD 결과 (mask + text_blocks)
result.inpainted # AOT 인페인트 결과
result.vision_results # LLM 응답 (block_index, is_sfx, ko_translation)
result.save_all("./debug/")
debug_dir를 지정하면 각 단계의 중간 산출물이 파일명 prefix로 정렬되어 저장된다.
디버그 산출물 목록
| 파일 | 의미 |
|---|---|
00_input.png |
원본 입력 이미지 |
00_params.json |
실행 하이퍼파라미터 스냅샷 |
01_mask_raw.png |
UNet 원본 float 마스크 |
01_mask_refined.png |
임계화 + 모폴로지 후처리 후 마스크 |
01b_mask_bbox_restricted.png |
YOLO bbox 밖 마스크 제거 후 |
02_bboxes.png |
원본 위에 YOLO 텍스트 박스 표시 |
03_mask_overlay.png |
마스크를 원본 위에 핑크색 반투명 오버레이 |
03b_mask_filtered.png |
SFX 드롭 후 마스크 (해당 시만) |
03c_mask_filtered_overlay.png |
SFX 드롭 마스크 오버레이 (해당 시만) |
04_inpainted.png |
AOT 인페인트 결과 |
05a_annotated.png |
LLM에 전송된 번호 박스 이미지 |
05_vision.json |
LLM 응답 JSON |
05_cost.json |
토큰/비용 정보 |
05b_render_bboxes.png |
원본 bbox(빨강) + 확장된 render_bbox(초록) |
06_final.png |
최종 결과 |
모델·코드·폰트 출처
모델 가중치는 lemondouble/lemon-manga-translator에서 PyTorch(safetensors) + ONNX 형태로 제공된다.
| 구성 요소 | 출처 | 라이선스 |
|---|---|---|
| Comic Text Detector | 원 저자 dmMaze/comic-text-detector · 배포 manga-image-translator beta-0.3 | GPL-3.0 |
| AOT Inpainting | 아키텍처 AOT-GAN (Zeng et al., 2021) · 파인튜닝 manga-image-translator beta-0.3 · 리팩 mayocream/aot-inpainting | GPL-3.0 |
detection/ctd_utils/ |
zyddnys/manga-image-translator manga_translator/detection/ctd_utils (벤더) |
GPL-3.0 |
assets/fonts/Jua-Regular.ttf |
The Jua Project Authors / Woowahan Brothers · Google Fonts: Jua | SIL OFL 1.1 |
assets/fonts/PretendardJP-Regular.otf |
orioncactus/pretendard (Kil Hyung-jin) | SIL OFL 1.1 |
| Vision LLM (런타임 API) | OpenRouter 경유 호출 | 번들되지 않음. 사용 모델 제공자 ToS |
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lemon_manga_translator-0.0.4.tar.gz.
File metadata
- Download URL: lemon_manga_translator-0.0.4.tar.gz
- Upload date:
- Size: 3.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d9a0b4e9b18cf2d1819613ea2fe871d75bdee734bc7d75ecbdc736ad2883e69
|
|
| MD5 |
25a1658776a0cc79dbb69e9132542e84
|
|
| BLAKE2b-256 |
7b41e6b123c019a5b2a430b5b434d7074949641f3a5fa431b13dcd2c72d489f2
|
Provenance
The following attestation bundles were made for lemon_manga_translator-0.0.4.tar.gz:
Publisher:
publish.yml on LemonDouble/lemon-manga-translator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lemon_manga_translator-0.0.4.tar.gz -
Subject digest:
3d9a0b4e9b18cf2d1819613ea2fe871d75bdee734bc7d75ecbdc736ad2883e69 - Sigstore transparency entry: 1339393366
- Sigstore integration time:
-
Permalink:
LemonDouble/lemon-manga-translator@aeb56d261526177ba7100db3693339e6da6de9a9 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/LemonDouble
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aeb56d261526177ba7100db3693339e6da6de9a9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lemon_manga_translator-0.0.4-py3-none-any.whl.
File metadata
- Download URL: lemon_manga_translator-0.0.4-py3-none-any.whl
- Upload date:
- Size: 3.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9655344b4b1d5cda373d627ec419bf44fe7aecfb8a79a98f815cba075f6857e5
|
|
| MD5 |
60aa246eea4765eb99a2891115a6ad14
|
|
| BLAKE2b-256 |
e50000cfe47e72108b335f1045eba1d0af51a4cfc877520c58c673c5026f56bf
|
Provenance
The following attestation bundles were made for lemon_manga_translator-0.0.4-py3-none-any.whl:
Publisher:
publish.yml on LemonDouble/lemon-manga-translator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lemon_manga_translator-0.0.4-py3-none-any.whl -
Subject digest:
9655344b4b1d5cda373d627ec419bf44fe7aecfb8a79a98f815cba075f6857e5 - Sigstore transparency entry: 1339393426
- Sigstore integration time:
-
Permalink:
LemonDouble/lemon-manga-translator@aeb56d261526177ba7100db3693339e6da6de9a9 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/LemonDouble
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aeb56d261526177ba7100db3693339e6da6de9a9 -
Trigger Event:
push
-
Statement type: