Fix bg removal in final assets

This commit is contained in:
Michele Rossi
2026-07-09 20:54:56 +02:00
parent 9c4474b93c
commit 8b3431ff12
2 changed files with 46 additions and 11 deletions

View File

@@ -407,10 +407,10 @@ class VnAssetsSession:
The upsampler is lazy-loaded on first call and reused across
calls. Uses ``RealESRGAN_x4plus_anime_6B`` (17 MB,
auto-downloaded).
auto-downloaded). Preserves alpha channel when present.
Args:
input_path: Path to the input RGB image.
input_path: Path to the input image (RGB or RGBA).
output_path: Where to save the upscaled PNG.
scale: Output scale factor (2, 3, or 4).

View File

@@ -72,13 +72,32 @@ def _build_upsampler(device: str = "cuda") -> RealESRGANer:
return upsampler
def _load_rgb_alpha(img: Image.Image) -> tuple[np.ndarray, np.ndarray | None]:
"""Extract RGB array and optional alpha channel from a PIL image.
Returns (rgb_np, alpha_np). ``alpha_np`` is None when the image has no
alpha channel. For paletted images, the palette is expanded first.
"""
if img.mode == "P":
img = img.convert("RGBA" if "transparency" in img.info else "RGB")
if img.mode in ("RGBA", "LA"):
rgb = img.convert("RGB")
alpha = img.getchannel("A")
return np.array(rgb), np.array(alpha)
return np.array(img.convert("RGB")), None
def upscale(
input_path: str,
output_path: str,
scale: int = 2,
upsampler: RealESRGANer | None = None,
) -> None:
"""Upscale a single image. Output is an RGB PNG.
"""Upscale a single image. Preserves alpha channel when present.
When the input is RGBA, the RGB channels are upscaled through the
model and the alpha channel is resized with LANCZOS interpolation.
Output format matches input: RGB for RGB inputs, RGBA for RGBA inputs.
Args:
input_path: Path to the input image.
@@ -107,17 +126,25 @@ def upscale(
if _upsampler is None:
_upsampler = _build_upsampler()
img = Image.open(input_file).convert("RGB")
img_np = np.array(img)
src = Image.open(input_file)
rgb_np, alpha_np = _load_rgb_alpha(src)
w, h = src.size
src.close()
t0 = time.perf_counter()
result, _ = _upsampler.enhance(img_np, outscale=scale)
result, _ = _upsampler.enhance(rgb_np, outscale=scale)
t_elapsed = round(time.perf_counter() - t0, 3)
result_img = Image.fromarray(result)
if alpha_np is not None:
alpha_img = Image.fromarray(alpha_np)
alpha_scaled = alpha_img.resize(result_img.size, Image.LANCZOS)
result_img = result_img.convert("RGBA")
result_img.putalpha(alpha_scaled)
result_img.save(output_file)
w, h = img.size
rw, rh = result_img.size
print(f"Saved {output_file} ({w}×{h}{rw}×{rh}, {t_elapsed}s)")
@@ -158,17 +185,25 @@ def upscales(
stem = Path(input_path).stem
output_path = out_dir / f"{stem}_x{scale}.png"
img = Image.open(input_path).convert("RGB")
img_np = np.array(img)
src = Image.open(input_path)
rgb_np, alpha_np = _load_rgb_alpha(src)
w, h = src.size
src.close()
t0 = time.perf_counter()
result, _ = _upsampler.enhance(img_np, outscale=scale)
result, _ = _upsampler.enhance(rgb_np, outscale=scale)
t_elapsed = time.perf_counter() - t0
total += t_elapsed
result_img = Image.fromarray(result)
if alpha_np is not None:
alpha_img = Image.fromarray(alpha_np)
alpha_scaled = alpha_img.resize(result_img.size, Image.LANCZOS)
result_img = result_img.convert("RGBA")
result_img.putalpha(alpha_scaled)
result_img.save(output_path)
w, h = img.size
rw, rh = result_img.size
print(f"Saved {output_path} ({w}×{h}{rw}×{rh}, {t_elapsed:.3f}s)")