Buckets:
| """ | |
| Base classes and context for the manga translation pipeline. | |
| """ | |
| from __future__ import annotations | |
| import base64 | |
| import io | |
| import logging | |
| from dataclasses import dataclass, field | |
| from typing import Optional, Any | |
| import numpy as np | |
| from PIL import Image | |
| log = logging.getLogger("engine") | |
| class TextRegion: | |
| """Detected text region with bounding box and polygon.""" | |
| index: int | |
| bbox: list[int] # [x1, y1, x2, y2] | |
| polygon: list[list[int]] # [[x,y], ...] | |
| source_text: str = "" | |
| translated_text: str = "" | |
| confidence: float = 0.0 | |
| orientation: str = "horizontal" # horizontal | vertical | |
| fg_color: tuple = (0, 0, 0) | |
| bg_color: tuple = (255, 255, 255) | |
| font_size: int = 0 | |
| class PipelineContext: | |
| """Context object passed through the pipeline stages.""" | |
| input_image: Image.Image = None | |
| img_rgb: np.ndarray = None | |
| img_alpha: np.ndarray = None | |
| text_regions: list[TextRegion] = field(default_factory=list) | |
| mask: np.ndarray = None | |
| img_inpainted: np.ndarray = None | |
| result: Image.Image = None | |
| verbose: bool = False | |
| device: str = "cpu" | |
| metadata: dict = field(default_factory=dict) | |
| def pil_to_b64(img: Image.Image, fmt: str = "PNG", quality: int = 90) -> str: | |
| buf = io.BytesIO() | |
| if fmt.upper() in ("JPEG", "JPG"): | |
| # JPEG doesn't support alpha - convert RGBA to RGB | |
| if img.mode == "RGBA": | |
| img = img.convert("RGB") | |
| img.save(buf, format=fmt, quality=quality, optimize=True) | |
| else: | |
| img.save(buf, format=fmt) | |
| return base64.b64encode(buf.getvalue()).decode("ascii") | |
| def b64_to_pil(b64: str) -> Image.Image: | |
| return Image.open(io.BytesIO(base64.b64decode(b64))) | |
| def load_image(image: Image.Image) -> tuple[np.ndarray, np.ndarray]: | |
| """Convert PIL Image to RGB numpy array and extract alpha channel.""" | |
| img = np.array(image.convert("RGBA")) | |
| img_rgb = img[:, :, :3].copy() | |
| img_alpha = img[:, :, 3].copy() if img.shape[2] == 4 else None | |
| return img_rgb, img_alpha | |
| def dump_image(input_image: Image.Image, img_rgb: np.ndarray, img_alpha: np.ndarray) -> Image.Image: | |
| """Convert numpy array back to PIL Image, preserving alpha if present.""" | |
| if img_alpha is not None: | |
| rgba = np.dstack((img_rgb, img_alpha)) | |
| return Image.fromarray(rgba, "RGBA") | |
| return Image.fromarray(img_rgb, "RGB") | |
Xet Storage Details
- Size:
- 2.39 kB
- Xet hash:
- 9eec2f352e38b9b65568d8076694c604ef8f2407aafbff903f32b1f6002c9b55
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.