from modules import script_callbacks import gradio as gr import numpy as np from PIL import Image import cv2 def check_alpha(img:np.array) -> bool: return img.shape[-1] == 4 and (img[:, :, 3] < 255).any() def preprocess_foreground(fg_img:Image, rotation:float, scale:float): if not check_alpha(np.asarray(fg_img)): print("Foreground Image contains no transparency...") return None w, h = fg_img.size w = int(float(w) * scale) h = int(float(h) * scale) return fg_img.resize((w, h), resample=Image.BILINEAR).rotate(rotation, resample=Image.BILINEAR, expand=True) def process_mask(bg: str, fg: str, tc: float, lt: float, ht: float, x:float, y:float, r:float, s:float): if (bg is None) or (fg is None): return [None, None] fg_img = preprocess_foreground(Image.open(fg), r, s) if fg_img is None: return [None, None] bg_img = Image.open(bg) width, height = bg_img.size new_fg = Image.new('RGBA', (width, height), (0, 0, 0, 0)) new_fg.paste(fg_img, (x, y), fg_img) mask = np.asarray(new_fg)[:, :, 3] kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) edge = cv2.Canny(mask, lt, ht) dilate = cv2.dilate(edge, kernel, iterations=tc) bg_img.paste(new_fg, (0, 0), new_fg) return [ bg_img, dilate.astype("uint8") ] def aaa_ui(): with gr.Blocks() as aaa_UI: with gr.Row(): background = gr.Image( image_mode="RGBA", sources="upload", type="filepath", label="Background Image", show_download_button=False, interactive=True, height=250 ) foreground = gr.Image( image_mode="RGBA", sources="upload", type="filepath", label="Foreground Image", show_download_button=False, interactive=True, height=250 ) img = gr.Image( image_mode="RGBA", label="Blended Image", elem_id="aaa_img", interactive=False, height=250, ) mask = gr.Image( image_mode="L", label="Mask", elem_id="aaa_mask", interactive=False, height=250 ) with gr.Row(): with gr.Column(): thicc = gr.Slider( label="Mask Thickness", minimum=5, maximum=50, step=5, value=10 ) low_t = gr.Slider( label="Low Threshold", minimum=0, maximum=255, step=1, value=0 ) high_t = gr.Slider( label="High Threshold", minimum=0, maximum=255, step=1, value=100 ) with gr.Column(): offset_x = gr.Slider( label="X Offset", minimum=-2048, maximum=2048, step=1, value=0 ) offset_y = gr.Slider( label="Y Offset", minimum=-2048, maximum=2048, step=1, value=0 ) with gr.Row(): offset_r = gr.Slider( label="Rotation", minimum=-180, maximum=180, step=1, value=0 ) offset_s = gr.Slider( label="Scale", minimum=0.0, maximum=2.0, step=0.1, value=1.0 ) with gr.Row(): proc_btn = gr.Button("Process Mask", variant="primary") send_btn = gr.Button("Send to Inpaint", variant="primary") proc_btn.click( process_mask, inputs=[background, foreground, thicc, low_t, high_t, offset_x, offset_y, offset_r, offset_s], outputs=[img, mask], ) send_btn.click( None, None, None, _js="() => { aaa_sendImage2InpaintUpload(); }" ) return [(aaa_UI, "AAA", "sd-webui-aaa")] script_callbacks.on_ui_tabs(aaa_ui)