| """RGBA 합성 및 배경 처리 유틸.""" |
| import numpy as np |
| from PIL import Image, ImageFilter |
|
|
|
|
| def feather_alpha(alpha: np.ndarray, amount: float) -> np.ndarray: |
| """경계 부드럽게 (amount: 픽셀 반경).""" |
| if amount <= 0: |
| return alpha |
| img = Image.fromarray((np.clip(alpha, 0, 1) * 255).astype("uint8")) |
| img = img.filter(ImageFilter.GaussianBlur(radius=float(amount))) |
| return np.asarray(img, dtype="float32") / 255.0 |
|
|
|
|
| def apply_gamma(alpha: np.ndarray, gamma: float) -> np.ndarray: |
| """알파 대비 조정 (gamma<1: 전경 확장, >1: 수축).""" |
| if abs(gamma - 1.0) < 1e-3: |
| return alpha |
| return np.clip(np.power(np.clip(alpha, 0, 1), gamma), 0, 1) |
|
|
|
|
| def to_rgba(fg_rgb01: np.ndarray, alpha: np.ndarray) -> Image.Image: |
| rgb = (np.clip(fg_rgb01, 0, 1) * 255).astype("uint8") |
| a = (np.clip(alpha, 0, 1) * 255).astype("uint8") |
| rgba = np.dstack([rgb, a]) |
| return Image.fromarray(rgba, "RGBA") |
|
|
|
|
| def composite_color(fg_rgb01: np.ndarray, alpha: np.ndarray, color=(255, 255, 255)) -> Image.Image: |
| a = np.clip(alpha, 0, 1)[..., None] |
| bg = np.array(color, dtype="float32") / 255.0 |
| out = fg_rgb01 * a + bg * (1 - a) |
| return Image.fromarray((np.clip(out, 0, 1) * 255).astype("uint8"), "RGB") |
|
|