MetricMogul's picture
Update image_utils.py
6577790 verified
from typing import Optional, Tuple
import gradio as gr
import numpy as np
from PIL import Image, ImageChops, ImageOps
NEGATIVE_DEFAULT = (
"blurry, ugly, bad anatomy, deformed, distorted, extra fingers, "
"extra limbs, poorly drawn hands, poorly drawn face, low quality"
)
def round_to_multiple_of_8(x: int) -> int:
x = int(x)
return max(64, x - (x % 8))
def resize_keep_aspect(img: Image.Image, max_side: int, resample) -> Image.Image:
w, h = img.size
longest = max(w, h)
if longest <= max_side:
return img
scale = max_side / float(longest)
new_w = round_to_multiple_of_8(int(w * scale))
new_h = round_to_multiple_of_8(int(h * scale))
return img.resize((new_w, new_h), resample)
def merge_layer_alphas(layers) -> Optional[Image.Image]:
if not layers:
return None
merged = None
for layer in layers:
if layer is None:
continue
if not isinstance(layer, Image.Image):
layer = Image.fromarray(np.array(layer))
rgba = layer.convert("RGBA")
alpha = rgba.getchannel("A")
if merged is None:
merged = alpha
else:
merged = ImageChops.lighter(merged, alpha)
return merged
def threshold_mask(mask_l: Image.Image, threshold: int = 10) -> Image.Image:
arr = np.array(mask_l, dtype=np.uint8)
arr = np.where(arr > threshold, 255, 0).astype(np.uint8)
return Image.fromarray(arr, mode="L")
def extract_image_and_mask(editor_value) -> Tuple[Image.Image, Image.Image]:
if editor_value is None:
raise gr.Error("Upload an image first.")
bg = editor_value.get("background", None)
layers = editor_value.get("layers", None)
if bg is None:
raise gr.Error("Upload an image first.")
if not isinstance(bg, Image.Image):
bg = Image.fromarray(np.array(bg))
bg = ImageOps.exif_transpose(bg).convert("RGB")
mask = merge_layer_alphas(layers)
if mask is None:
raise gr.Error("Paint a mask first.")
if mask.size != bg.size:
mask = mask.resize(bg.size, Image.NEAREST)
mask = threshold_mask(mask.convert("L"))
if mask.getbbox() is None:
raise gr.Error("Paint a mask first.")
return bg, mask
def prepare_inputs_for_cpu(
image: Image.Image,
mask: Image.Image,
max_side: int,
) -> Tuple[Image.Image, Image.Image]:
image = resize_keep_aspect(image, max_side=max_side, resample=Image.LANCZOS)
mask = mask.resize(image.size, Image.NEAREST)
w, h = image.size
w = round_to_multiple_of_8(w)
h = round_to_multiple_of_8(h)
if image.size != (w, h):
image = image.resize((w, h), Image.LANCZOS)
if mask.size != (w, h):
mask = mask.resize((w, h), Image.NEAREST)
return image, mask