Skip to content

Commit de01151

Browse files
committed
fix: normalize transparent image inputs
1 parent 0fc2e20 commit de01151

24 files changed

Lines changed: 100 additions & 151 deletions

doc/CHANGELOG_v2.2.10.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
- 修复 API 管理面板图片类接口测试图过小的问题;测试用 PNG 从 2 像素调整为 50 像素,避免部分图片 API 拒绝过小输入。
5656
- 修复开启气泡英文排版时,渲染阶段尝试写入只读的 `TextBlock.horizontal` 属性导致任务中断的问题;现在会通过文本方向字段强制横排。
5757
- 修复 AI 渲染默认提示词只要求去掉编号框、未明确要求去掉数字标签的问题;启动时会自动迁移旧版默认渲染提示词,避免保留编号数字。
58+
- 修复带透明通道或非标准 4 通道模式图片在 Real-CUGAN、MangaJaNai、ESRGAN、AI 上色/渲染、OCR 等路径中可能被作为 4 通道张量输入模型的问题;现在统一在图像边界将 `RGBA``RGBa``LA`、带透明 `P``RGBX``CMYK` 等模式规范化为白底 RGB。
5859

5960
## 📝 说明
6061

manga_translator/colorization/manga_colorization_v2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from PIL import Image
77
from torchvision.transforms import ToTensor
88

9+
from ..utils.image_modes import normalize_rgb_image
910
from .common import OfflineColorizer
1011
from .manga_colorization_v2_utils.denoising.denoiser import FFDNetDenoiser
1112
from .manga_colorization_v2_utils.networks.models import Colorizer
@@ -49,7 +50,7 @@ async def _unload(self):
4950

5051
async def _infer(self, image: Image.Image, colorization_size: int, denoise_sigma=25, **kwargs) -> Image.Image:
5152
# Size has to be multiple of 32
52-
img = np.array(image.convert('RGBA'))
53+
img = np.array(normalize_rgb_image(image))
5354
original_size = image.size # 保存原始尺寸 (width, height)
5455
max_size = min(*img.shape[:2])
5556
max_size -= max_size % 32

manga_translator/colorization/model_api_colorizer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def _build_colorizer_request(self, image: Image.Image, kwargs) -> tuple[str, lis
169169
continue
170170
try:
171171
with Image.open(ref.resolved_path) as reference_image:
172-
reference_rgb = reference_image.convert("RGB")
172+
reference_rgb = normalize_ai_image(reference_image)
173173
reference_images.append(
174174
{
175175
"kind": "prompt_reference",
@@ -269,10 +269,10 @@ async def _fetch_image_from_url(self, url: str) -> Image.Image:
269269
response = await self.client.session.get(url, timeout=600.0)
270270
if response.status_code != 200:
271271
raise RuntimeError(f"Failed to download generated image: HTTP {response.status_code}")
272-
return Image.open(io.BytesIO(response.content)).convert("RGB")
272+
return normalize_ai_image(Image.open(io.BytesIO(response.content)))
273273

274274
def _load_image_from_bytes(self, payload: bytes) -> Image.Image:
275-
return Image.open(io.BytesIO(payload)).convert("RGB")
275+
return normalize_ai_image(Image.open(io.BytesIO(payload)))
276276

277277
async def _reset_client_for_candidate(self, endpoint, error: Exception):
278278
del endpoint, error

manga_translator/detection/panel_finder.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import numpy as np
66
from PIL import Image
77

8+
from ..utils.image_modes import normalize_rgb_image
9+
810
KERNEL_SIZE = 7
911
BORDER_SIZE = 10
1012

@@ -19,7 +21,7 @@ def panel_process_image(img: Image.Image):
1921
The preprocessed image.
2022
"""
2123

22-
img_gray = cv.cvtColor(np.array(img), cv.COLOR_BGR2GRAY)
24+
img_gray = cv.cvtColor(np.array(normalize_rgb_image(img)), cv.COLOR_RGB2GRAY)
2325
img_gray = cv.GaussianBlur(img_gray, (KERNEL_SIZE, KERNEL_SIZE), 0)
2426
img_gray = cv.threshold(img_gray, 200, 255, cv.THRESH_BINARY)[1]
2527

manga_translator/inpainting/booru_tagger.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pandas as pd
77
from PIL import Image
88

9+
from ..utils.image_modes import normalize_rgb_image
910
from ..utils.onnx_runtime import (
1011
create_inference_session,
1112
create_session_options,
@@ -58,11 +59,7 @@ def __init__(self, filename) -> None:
5859
_, self.height, _, _ = self.model.get_inputs()[0].shape
5960

6061
def label(self, image: Image) -> Dict[str, float] :
61-
# alpha to white
62-
image = image.convert('RGBA')
63-
new_image = Image.new('RGBA', image.size, 'WHITE')
64-
new_image.paste(image, mask=image)
65-
image = new_image.convert('RGB')
62+
image = normalize_rgb_image(image)
6663
image = np.asarray(image)
6764

6865
# PIL RGB to OpenCV BGR

manga_translator/manga_translator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
get_original_txt_path,
8282
get_work_image_path,
8383
)
84+
from .utils.ai_image_preprocess import normalize_ai_image
8485
from .utils.translation_text import remove_trailing_period_if_needed
8586

8687
# Will be overwritten by __main__.py if module is being run directly (with python -m)
@@ -1542,7 +1543,7 @@ def _append_colorizer_history_image(self, config: Config, image) -> None:
15421543
if not isinstance(image, Image.Image):
15431544
image = Image.fromarray(np.asarray(image).astype(np.uint8))
15441545

1545-
history_image = image.convert("RGB").copy()
1546+
history_image = normalize_ai_image(image).copy()
15461547
self._colorizer_history_images.append(history_image)
15471548

15481549
history_pages = self._get_ai_colorizer_history_pages(config)

manga_translator/ocr/model_api_ocr.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from ..api_key_rotation import run_with_api_candidates
2121
from ..utils import Quadrilateral
2222
from ..utils.generic import AvgMeter
23+
from ..utils.image_modes import normalize_rgb_image
2324
from .common import OfflineOCR
2425
from .prompt_loader import (
2526
DEFAULT_AI_OCR_PROMPT,
@@ -175,8 +176,7 @@ def _normalize_ocr_text(self, text: str) -> str:
175176

176177
def _encode_region_png_base64(self, region: np.ndarray) -> str:
177178
image = Image.fromarray(region.astype(np.uint8))
178-
if image.mode != "RGB":
179-
image = image.convert("RGB")
179+
image = normalize_rgb_image(image)
180180
buffer = io.BytesIO()
181181
image.save(buffer, format="PNG")
182182
return base64.b64encode(buffer.getvalue()).decode("ascii")

manga_translator/ocr/model_paddleocr_vl.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from ..config import OcrConfig
2020
from ..utils import Quadrilateral
2121
from ..utils.generic import AvgMeter
22+
from ..utils.image_modes import normalize_rgb_image
2223
from .common import OfflineOCR
2324

2425

@@ -398,9 +399,7 @@ def _recognize_single(self, img: np.ndarray, prompt_text: str) -> str:
398399
else:
399400
pil_img = img
400401

401-
# 确保是 RGB 模式
402-
if pil_img.mode != 'RGB':
403-
pil_img = pil_img.convert('RGB')
402+
pil_img = normalize_rgb_image(pil_img)
404403

405404
last_output = ''
406405
for attempt, (generation_config, retry_suffix) in enumerate(zip(

manga_translator/rendering/model_api_renderer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ async def _fetch_image_from_url(self, url: str) -> Image.Image:
219219
response = await self.client.session.get(url, timeout=600.0)
220220
if response.status_code != 200:
221221
raise RuntimeError(f"Failed to download rendered image: HTTP {response.status_code}")
222-
return Image.open(io.BytesIO(response.content)).convert("RGB")
222+
return normalize_ai_image(Image.open(io.BytesIO(response.content)))
223223

224224
async def _reset_client_for_candidate(self, endpoint, error: Exception):
225225
del endpoint, error
@@ -253,7 +253,7 @@ def _extract_gemini_image(self, response) -> Optional[Image.Image]:
253253
data = inline_data.get("data")
254254
if not data:
255255
continue
256-
return Image.open(io.BytesIO(base64.b64decode(data))).convert("RGB")
256+
return normalize_ai_image(Image.open(io.BytesIO(base64.b64decode(data))))
257257
return None
258258

259259
async def render(self, img: np.ndarray, text_regions: List[TextBlock], config) -> np.ndarray:

manga_translator/rendering/text_render_pillow_eng.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from PIL import Image, ImageDraw, ImageFont
77

88
from ..utils import TextBlock
9+
from ..utils.image_modes import normalize_rgb_image
910
from .ballon_extractor import extract_ballon_region
1011
from .text_render_eng import _write_region_br_from_lines, seg_eng
1112

@@ -254,7 +255,7 @@ def calculate_font_values(font, words, delimiter=' '):
254255
bboxes[i][0][j] += int(offset[j])
255256

256257
# Apply strokes and paste text
257-
img_pil = img_pil.convert("RGB")
258+
img_pil = normalize_rgb_image(img_pil)
258259
img_array = np.array(img_pil)
259260

260261
for rotated_layer, bbox, sw in zip(rotated_text_layers, bboxes, sws):

0 commit comments

Comments
 (0)