bilegentile's picture
Upload folder using huggingface_hub
c19ca42 verified
raw
history blame contribute delete
3.23 kB
from typing import Tuple
import numpy as np
from ...utils.utils import get_h_w_c
from ..image_op import ImageOp, clipped
from ..image_utils import as_target_channels
def with_black_and_white_backgrounds(img: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
c = get_h_w_c(img)[2]
assert c == 4
black = np.copy(img[:, :, :3])
white = np.copy(img[:, :, :3])
for c in range(3):
black[:, :, c] *= img[:, :, 3]
white[:, :, c] = (white[:, :, c] - 1) * img[:, :, 3] + 1
return black, white
def denoise_and_flatten_alpha(img: np.ndarray) -> np.ndarray:
alpha_min = np.min(img, axis=2)
alpha_max = np.max(img, axis=2)
alpha_mean = np.mean(img, axis=2)
alpha = alpha_max * alpha_mean + alpha_min * (1 - alpha_mean)
return alpha
def convenient_upscale(
img: np.ndarray,
model_in_nc: int,
model_out_nc: int,
upscale: ImageOp,
separate_alpha: bool = False,
) -> np.ndarray:
"""
Upscales the given image in an intuitive/convenient way.
This method guarantees that the `upscale` function will be called with an image with
`model_in_nc` number of channels.
Additionally, guarantees that the number of channels of the output image will match
that of the input image in cases where `model_in_nc` == `model_out_nc`, and match
`model_out_nc` otherwise.
"""
in_img_c = get_h_w_c(img)[2]
upscale = clipped(upscale)
if model_in_nc != model_out_nc:
return upscale(as_target_channels(img, model_in_nc, True))
if in_img_c == model_in_nc:
return upscale(img)
if in_img_c == 4:
# Ignore alpha if single-color or not being replaced
unique = np.unique(img[:, :, 3])
if len(unique) == 1:
rgb = as_target_channels(
upscale(as_target_channels(img[:, :, :3], model_in_nc, True)), 3, True
)
unique_alpha = np.full(rgb.shape[:-1], unique[0], np.float32)
return np.dstack((rgb, unique_alpha))
if separate_alpha:
# Upscale the RGB channels and alpha channel separately
rgb = as_target_channels(
upscale(as_target_channels(img[:, :, :3], model_in_nc, True)), 3, True
)
alpha = denoise_and_flatten_alpha(
upscale(as_target_channels(img[:, :, 3], model_in_nc, True))
)
return np.dstack((rgb, alpha))
else:
# Transparency hack (white/black background difference alpha)
black, white = with_black_and_white_backgrounds(img)
black_up = as_target_channels(
upscale(as_target_channels(black, model_in_nc, True)), 3, True
)
white_up = as_target_channels(
upscale(as_target_channels(white, model_in_nc, True)), 3, True
)
# Interpolate between the alpha values to get a more defined alpha
alpha_candidates = 1 - (white_up - black_up) # type: ignore
alpha = denoise_and_flatten_alpha(alpha_candidates)
return np.dstack((black_up, alpha))
return as_target_channels(
upscale(as_target_channels(img, model_in_nc, True)), in_img_c, True
)