import spaces import os from stablepy import Model_Diffusers from stablepy.diffusers_vanilla.model import scheduler_names from stablepy.diffusers_vanilla.style_prompt_config import STYLE_NAMES import torch import re import shutil import random from stablepy import ( CONTROLNET_MODEL_IDS, VALID_TASKS, T2I_PREPROCESSOR_NAME, FLASH_LORA, SCHEDULER_CONFIG_MAP, scheduler_names, IP_ADAPTER_MODELS, IP_ADAPTERS_SD, IP_ADAPTERS_SDXL, REPO_IMAGE_ENCODER, ALL_PROMPT_WEIGHT_OPTIONS, SD15_TASKS, SDXL_TASKS, ) import urllib.parse from config import ( MINIMUM_IMAGE_NUMBER, MAXIMUM_IMAGE_NUMBER, DEFAULT_NEGATIVE_PROMPT, DEFAULT_POSITIVE_PROMPT ) from models.vae import VAE_LIST as download_vae from models.checkpoints import CHECKPOINT_LIST as download_model from models.loras import LORA_LIST as download_lora from models.format_models import FORMAT_MODELS as load_diffusers_format_model from models.upscaler import upscaler_dict_gui from models.controlnet import preprocessor_controlnet from models.embeds import download_embeds from examples.examples import example_prompts from utils.download_utils import download_things from utils.model_utils import get_model_list task_stablepy: dict = { 'txt2img': 'txt2img', 'img2img': 'img2img', 'inpaint': 'inpaint', # 'canny T2I Adapter': 'sdxl_canny_t2i', # NO HAVE STEP CALLBACK PARAMETERS SO NOT WORKS WITH DIFFUSERS 0.29.0 # 'sketch T2I Adapter': 'sdxl_sketch_t2i', # 'lineart T2I Adapter': 'sdxl_lineart_t2i', # 'depth-midas T2I Adapter': 'sdxl_depth-midas_t2i', # 'openpose T2I Adapter': 'sdxl_openpose_t2i', 'openpose ControlNet': 'openpose', 'canny ControlNet': 'canny', 'mlsd ControlNet': 'mlsd', 'scribble ControlNet': 'scribble', 'softedge ControlNet': 'softedge', 'segmentation ControlNet': 'segmentation', 'depth ControlNet': 'depth', 'normalbae ControlNet': 'normalbae', 'lineart ControlNet': 'lineart', # 'lineart_anime ControlNet': 'lineart_anime', 'shuffle ControlNet': 'shuffle', 'ip2p ControlNet': 'ip2p', 'optical pattern ControlNet': 'pattern', 'tile realistic': 'sdxl_tile_realistic', } # LOAD ALL ENV TOKEN CIVITAI_API_KEY: str = os.environ.get("CIVITAI_API_KEY") hf_token: str = os.environ.get("HF_TOKEN") task_model_list = list(task_stablepy.keys()) directory_models: str = 'models' os.makedirs( directory_models, exist_ok=True ) directory_loras: str = 'loras' os.makedirs( directory_loras, exist_ok=True ) directory_vaes: str = 'vaes' os.makedirs( directory_vaes, exist_ok=True ) directory_embeds: str = 'embedings' os.makedirs( directory_embeds, exist_ok=True ) # Download stuffs for url in [url.strip() for url in download_model.split(',')]: if not os.path.exists(f"./models/{url.split('/')[-1]}"): download_things( directory_models, url, hf_token, CIVITAI_API_KEY ) for url in [url.strip() for url in download_vae.split(',')]: if not os.path.exists(f"./vaes/{url.split('/')[-1]}"): download_things( directory_vaes, url, hf_token, CIVITAI_API_KEY ) for url in [url.strip() for url in download_lora.split(',')]: if not os.path.exists(f"./loras/{url.split('/')[-1]}"): download_things( directory_loras, url, hf_token, CIVITAI_API_KEY ) for url_embed in download_embeds: if not os.path.exists(f"./embedings/{url_embed.split('/')[-1]}"): download_things( directory_embeds, url_embed, hf_token, CIVITAI_API_KEY ) # Build list models embed_list = get_model_list(directory_embeds) model_list = get_model_list(directory_models) model_list = load_diffusers_format_model + model_list lora_model_list = get_model_list(directory_loras) lora_model_list.insert(0, "None") vae_model_list = get_model_list(directory_vaes) vae_model_list.insert(0, "None") def get_my_lora(link_url) -> tuple: for __url in [_url.strip() for _url in link_url.split(',')]: if not os.path.exists(f"./loras/{__url.split('/')[-1]}"): download_things( directory_loras, __url, hf_token, CIVITAI_API_KEY ) new_lora_model_list: list = get_model_list(directory_loras) new_lora_model_list.insert(0, "None") return gr.update( choices=new_lora_model_list ), gr.update( choices=new_lora_model_list ), gr.update( choices=new_lora_model_list ), gr.update( choices=new_lora_model_list ), gr.update( choices=new_lora_model_list ) print('\033[33m🏁 Download and listing of valid models completed.\033[0m') ####################### # GUI ####################### import spaces import gradio as gr from PIL import Image import IPython.display import time, json from IPython.utils import capture import logging from utils.string_utils import extract_parameters from stablepy import logger logging.getLogger("diffusers").setLevel(logging.ERROR) import diffusers diffusers.utils.logging.set_verbosity(40) import warnings warnings.filterwarnings( action="ignore", category=FutureWarning, module="diffusers" ) warnings.filterwarnings( action="ignore", category=UserWarning, module="diffusers" ) warnings.filterwarnings( action="ignore", category=FutureWarning, module="transformers" ) logger.setLevel(logging.DEBUG) class GuiSD: def __init__(self, stream=True): self.model = None print("Loading model...") self.model = Model_Diffusers( base_model_id="cagliostrolab/animagine-xl-3.1", task_name="txt2img", vae_model=None, type_model_precision=torch.float16, retain_task_model_in_cache=False, ) def load_new_model( self, model_name, vae_model, task, progress=gr.Progress(track_tqdm=True)): """ :param model_name: :param vae_model: :param task: :param progress: """ yield f"Loading model: {model_name}" vae_model = vae_model if vae_model != "None" else None if model_name in model_list: model_is_xl = "xl" in model_name.lower() sdxl_in_vae = vae_model and "sdxl" in vae_model.lower() model_type = "SDXL" if model_is_xl else "SD 1.5" incompatible_vae = (model_is_xl and vae_model and not sdxl_in_vae) or (not model_is_xl and sdxl_in_vae) if incompatible_vae: vae_model = None self.model.load_pipe( model_name, task_name=task_stablepy[task], vae_model=vae_model if vae_model != "None" else None, type_model_precision=torch.float16, retain_task_model_in_cache=False, ) yield f"Model loaded: {model_name}" @spaces.GPU def generate_pipeline( self, prompt, neg_prompt, num_images, steps, cfg, clip_skip, seed, lora1, lora_scale1, lora2, lora_scale2, lora3, lora_scale3, lora4, lora_scale4, lora5, lora_scale5, sampler, img_height, img_width, model_name, vae_model, task, image_control, preprocessor_name, preprocess_resolution, image_resolution, style_prompt, # list [] style_json_file, image_mask, strength, low_threshold, high_threshold, value_threshold, distance_threshold, controlnet_output_scaling_in_unet, controlnet_start_threshold, controlnet_stop_threshold, textual_inversion, syntax_weights, upscaler_model_path, upscaler_increases_size, esrgan_tile, esrgan_tile_overlap, hires_steps, hires_denoising_strength, hires_sampler, hires_prompt, hires_negative_prompt, hires_before_adetailer, hires_after_adetailer, loop_generation, leave_progress_bar, disable_progress_bar, image_previews, display_images, save_generated_images, image_storage_location, retain_compel_previous_load, retain_detailfix_model_previous_load, retain_hires_model_previous_load, t2i_adapter_preprocessor, t2i_adapter_conditioning_scale, t2i_adapter_conditioning_factor, xformers_memory_efficient_attention, freeu, generator_in_cpu, adetailer_inpaint_only, adetailer_verbose, adetailer_sampler, adetailer_active_a, prompt_ad_a, negative_prompt_ad_a, strength_ad_a, face_detector_ad_a, person_detector_ad_a, hand_detector_ad_a, mask_dilation_a, mask_blur_a, mask_padding_a, adetailer_active_b, prompt_ad_b, negative_prompt_ad_b, strength_ad_b, face_detector_ad_b, person_detector_ad_b, hand_detector_ad_b, mask_dilation_b, mask_blur_b, mask_padding_b, retain_task_cache_gui, image_ip1, mask_ip1, model_ip1, mode_ip1, scale_ip1, image_ip2, mask_ip2, model_ip2, mode_ip2, scale_ip2): vae_model = vae_model if vae_model != "None" else None loras_list: list = [lora1, lora2, lora3, lora4, lora5] vae_msg: str = f"VAE: {vae_model}" if vae_model else "" msg_lora: list = [] if model_name in model_list: model_is_xl = "xl" in model_name.lower() sdxl_in_vae = vae_model and "sdxl" in vae_model.lower() model_type = "SDXL" if model_is_xl else "SD 1.5" incompatible_vae = ((model_is_xl and vae_model and not sdxl_in_vae) or (not model_is_xl and sdxl_in_vae)) if incompatible_vae: msg_inc_vae = ( f"The selected VAE is for a {'SD 1.5' if model_is_xl else 'SDXL'} model, but you" f" are using a {model_type} model. The default VAE " "will be used." ) gr.Info(msg_inc_vae) vae_msg = msg_inc_vae vae_model = None for la in loras_list: if la is None or la == "None" or la not in lora_model_list: continue print(la) lora_type = ("animetarot" in la.lower() or "Hyper-SD15-8steps".lower() in la.lower()) if (model_is_xl and lora_type) or (not model_is_xl and not lora_type): msg_inc_lora = f"The LoRA {la} is for {'SD 1.5' if model_is_xl else 'SDXL'}, but you are using {model_type}." gr.Info(msg_inc_lora) msg_lora.append(msg_inc_lora) task = task_stablepy[task] params_ip_img: list = [] params_ip_msk: list = [] params_ip_model: list = [] params_ip_mode: list = [] params_ip_scale: list = [] all_adapters = [ (image_ip1, mask_ip1, model_ip1, mode_ip1, scale_ip1), (image_ip2, mask_ip2, model_ip2, mode_ip2, scale_ip2), ] for (imgip, mskip, modelip, modeip, scaleip) in all_adapters: if imgip: params_ip_img.append(imgip) if mskip: params_ip_msk.append(mskip) params_ip_model.append(modelip) params_ip_mode.append(modeip) params_ip_scale.append(scaleip) # First load model_precision = torch.float16 if not self.model: from modelstream import Model_Diffusers2 print("Loading model...") self.model = Model_Diffusers2( base_model_id=model_name, task_name=task, vae_model=vae_model if vae_model != "None" else None, type_model_precision=model_precision, retain_task_model_in_cache=retain_task_cache_gui, ) if task != "txt2img" and not image_control: raise ValueError( "No control image found: To use this function, " "you have to upload an image in 'Image ControlNet/Inpaint/Img2img'" ) if task == "inpaint" and not image_mask: raise ValueError("No mask image found: Specify one in 'Image Mask'") if upscaler_model_path in [None, "Lanczos", "Nearest"]: upscaler_model = upscaler_model_path else: directory_upscalers = 'upscalers' os.makedirs(directory_upscalers, exist_ok=True) url_upscaler = upscaler_dict_gui[upscaler_model_path] if not os.path.exists(f"./upscalers/{url_upscaler.split('/')[-1]}"): download_things( directory_upscalers, url_upscaler, hf_token ) upscaler_model = f"./upscalers/{url_upscaler.split('/')[-1]}" logging.getLogger("ultralytics").setLevel(logging.INFO if adetailer_verbose else logging.ERROR) print("Config model:", model_name, vae_model, loras_list) self.model.load_pipe( model_name, task_name=task, vae_model=vae_model if vae_model != "None" else None, type_model_precision=model_precision, retain_task_model_in_cache=retain_task_cache_gui, ) if textual_inversion and self.model.class_name == "StableDiffusionXLPipeline": print("No Textual inversion for SDXL") adetailer_params_A = { "face_detector_ad": face_detector_ad_a, "person_detector_ad": person_detector_ad_a, "hand_detector_ad": hand_detector_ad_a, "prompt": prompt_ad_a, "negative_prompt": negative_prompt_ad_a, "strength": strength_ad_a, # "image_list_task" : None, "mask_dilation": mask_dilation_a, "mask_blur": mask_blur_a, "mask_padding": mask_padding_a, "inpaint_only": adetailer_inpaint_only, "sampler": adetailer_sampler, } adetailer_params_B = { "face_detector_ad": face_detector_ad_b, "person_detector_ad": person_detector_ad_b, "hand_detector_ad": hand_detector_ad_b, "prompt": prompt_ad_b, "negative_prompt": negative_prompt_ad_b, "strength": strength_ad_b, # "image_list_task" : None, "mask_dilation": mask_dilation_b, "mask_blur": mask_blur_b, "mask_padding": mask_padding_b, } pipe_params = { "prompt": prompt, "negative_prompt": neg_prompt, "img_height": img_height, "img_width": img_width, "num_images": num_images, "num_steps": steps, "guidance_scale": cfg, "clip_skip": clip_skip, "seed": seed, "image": image_control, "preprocessor_name": preprocessor_name, "preprocess_resolution": preprocess_resolution, "image_resolution": image_resolution, "style_prompt": style_prompt if style_prompt else "", "style_json_file": "", "image_mask": image_mask, # only for Inpaint "strength": strength, # only for Inpaint or ... "low_threshold": low_threshold, "high_threshold": high_threshold, "value_threshold": value_threshold, "distance_threshold": distance_threshold, "lora_A": lora1 if lora1 != "None" else None, "lora_scale_A": lora_scale1, "lora_B": lora2 if lora2 != "None" else None, "lora_scale_B": lora_scale2, "lora_C": lora3 if lora3 != "None" else None, "lora_scale_C": lora_scale3, "lora_D": lora4 if lora4 != "None" else None, "lora_scale_D": lora_scale4, "lora_E": lora5 if lora5 != "None" else None, "lora_scale_E": lora_scale5, "textual_inversion": embed_list if textual_inversion and self.model.class_name != "StableDiffusionXLPipeline" else [], "syntax_weights": syntax_weights, # "Classic" "sampler": sampler, "xformers_memory_efficient_attention": xformers_memory_efficient_attention, "gui_active": True, "loop_generation": loop_generation, "controlnet_conditioning_scale": float(controlnet_output_scaling_in_unet), "control_guidance_start": float(controlnet_start_threshold), "control_guidance_end": float(controlnet_stop_threshold), "generator_in_cpu": generator_in_cpu, "FreeU": freeu, "adetailer_A": adetailer_active_a, "adetailer_A_params": adetailer_params_A, "adetailer_B": adetailer_active_b, "adetailer_B_params": adetailer_params_B, "leave_progress_bar": leave_progress_bar, "disable_progress_bar": disable_progress_bar, "image_previews": image_previews, "display_images": display_images, "save_generated_images": save_generated_images, "image_storage_location": image_storage_location, "retain_compel_previous_load": retain_compel_previous_load, "retain_detailfix_model_previous_load": retain_detailfix_model_previous_load, "retain_hires_model_previous_load": retain_hires_model_previous_load, "t2i_adapter_preprocessor": t2i_adapter_preprocessor, "t2i_adapter_conditioning_scale": float(t2i_adapter_conditioning_scale), "t2i_adapter_conditioning_factor": float(t2i_adapter_conditioning_factor), "upscaler_model_path": upscaler_model, "upscaler_increases_size": upscaler_increases_size, "esrgan_tile": esrgan_tile, "esrgan_tile_overlap": esrgan_tile_overlap, "hires_steps": hires_steps, "hires_denoising_strength": hires_denoising_strength, "hires_prompt": hires_prompt, "hires_negative_prompt": hires_negative_prompt, "hires_sampler": hires_sampler, "hires_before_adetailer": hires_before_adetailer, "hires_after_adetailer": hires_after_adetailer, "ip_adapter_image": params_ip_img, "ip_adapter_mask": params_ip_msk, "ip_adapter_model": params_ip_model, "ip_adapter_mode": params_ip_mode, "ip_adapter_scale": params_ip_scale, } # print(pipe_params) random_number = random.randint(1, 100) if random_number < 25 and num_images < 3: if (not upscaler_model and steps < 45 and task in ["txt2img", "img2img"] and not adetailer_active_a and not adetailer_active_b): num_images *= 2 pipe_params["num_images"] = num_images gr.Info("Num images x 2 🎉") # Maybe fix lora issue: 'Cannot copy out of meta tensor; no data!'' self.model.pipe.to("cuda:0" if torch.cuda.is_available() else "cpu") info_state = f"PROCESSING" for img, seed, data in self.model(**pipe_params): info_state += "." if data: info_state = f"COMPLETED. Seeds: {str(seed)}" if vae_msg: info_state = info_state + "
" + vae_msg if msg_lora: info_state = info_state + "
" + "
".join(msg_lora) yield img, info_state sd_gen = GuiSD() with open("app.css", "r") as f: CSS: str = f.read() sdxl_task = [k for k, v in task_stablepy.items() if v in SDXL_TASKS] sd_task = [k for k, v in task_stablepy.items() if v in SD15_TASKS] def update_task_options(model_name, task_name): if model_name in model_list: if "xl" in model_name.lower(): new_choices = sdxl_task else: new_choices = sd_task if task_name not in new_choices: task_name = "txt2img" return gr.update( value=task_name, choices=new_choices ) else: return gr.update( value=task_name, choices=task_model_list ) # APP with gr.Blocks(css=CSS) as app: gr.Markdown("# 🧩 (Ivan) DiffuseCraft") with gr.Tab("Generation"): with gr.Row(): with gr.Column(scale=2): task_gui = gr.Dropdown( label="Task", choices=sdxl_task, value=task_model_list[0], ) model_name_gui = gr.Dropdown( label="Model", choices=model_list, value=model_list[-6] or model_list[0], allow_custom_value=True ) prompt_gui = gr.Textbox( lines=5, placeholder="Enter Positive prompt", label="Positive Prompt", value=DEFAULT_POSITIVE_PROMPT ) neg_prompt_gui = gr.Textbox( lines=3, placeholder="Enter Negative prompt", label="Negative prompt", value=DEFAULT_NEGATIVE_PROMPT ) with gr.Row(equal_height=False): set_params_gui = gr.Button(value="↙️") clear_prompt_gui = gr.Button(value="🗑️") set_random_seed = gr.Button(value="🎲") generate_button = gr.Button( value="GENERATE", variant="primary" ) model_name_gui.change( update_task_options, [model_name_gui, task_gui], [task_gui], ) load_model_gui = gr.HTML() result_images = gr.Gallery( label="Generated images", show_label=False, elem_id="gallery", columns=[2], rows=[2], object_fit="contain", # height="auto", interactive=False, preview=False, selected_index=50, ) actual_task_info = gr.HTML() with gr.Column(scale=1): steps_gui = gr.Slider( minimum=1, maximum=100, step=1, value=43, label="Steps" ) cfg_gui = gr.Slider( minimum=0, maximum=30, step=0.5, value=7.5, label="CFG" ) sampler_gui = gr.Dropdown( label="Sampler", choices=scheduler_names, value="DPM++ 2M Karras" ) img_width_gui = gr.Slider( minimum=64, maximum=4096, step=8, value=1024, label="Img Width" ) img_height_gui = gr.Slider( minimum=64, maximum=4096, step=8, value=1024, label="Img Height" ) seed_gui = gr.Number( minimum=-1, maximum=9999999999, value=-1, label="Seed" ) with gr.Row(): clip_skip_gui = gr.Checkbox( value=True, label="Layer 2 Clip Skip" ) free_u_gui = gr.Checkbox( value=True, label="FreeU" ) with gr.Row(equal_height=False): def run_set_params_gui(base_prompt): valid_receptors: dict = { # default values "prompt": gr.update(value=base_prompt), "neg_prompt": gr.update(value=""), "Steps": gr.update(value=30), "width": gr.update(value=1024), "height": gr.update(value=1024), "Seed": gr.update(value=-1), "Sampler": gr.update(value="Euler a"), "scale": gr.update(value=7.5), # cfg "skip": gr.update(value=True), } valid_keys = list(valid_receptors.keys()) parameters: dict = extract_parameters(base_prompt) for key, val in parameters.items(): # print(val) if key in valid_keys: if key == "Sampler": if val not in scheduler_names: continue elif key == "skip": if int(val) >= 2: val = True if key == "prompt": if ">" in val and "<" in val: val = re.sub(r'<[^>]+>', '', val) print("Removed LoRA written in the prompt") if key in ["prompt", "neg_prompt"]: val = val.strip() if key in ["Steps", "width", "height", "Seed"]: val = int(val) if key == "scale": val = float(val) if key == "Seed": continue valid_receptors[key] = gr.update(value=val) # print(val, type(val)) # print(valid_receptors) return [value for value in valid_receptors.values()] set_params_gui.click( run_set_params_gui, [prompt_gui], [ prompt_gui, neg_prompt_gui, steps_gui, img_width_gui, img_height_gui, seed_gui, sampler_gui, cfg_gui, clip_skip_gui, ], ) def run_clear_prompt_gui(): return gr.update(value=""), gr.update(value="") clear_prompt_gui.click( run_clear_prompt_gui, [], [prompt_gui, neg_prompt_gui] ) def run_set_random_seed(): return -1 set_random_seed.click( run_set_random_seed, [], seed_gui ) num_images_gui = gr.Slider( minimum=MINIMUM_IMAGE_NUMBER, maximum=MAXIMUM_IMAGE_NUMBER, step=1, value=1, label="Images" ) prompt_s_options = [ ("Classic format: (word:weight)", "Classic"), ("Compel format: (word)weight", "Compel"), ("Classic-original format: (word:weight)", "Classic-original"), ("Classic-no_norm format: (word:weight)", "Classic-no_norm"), ("Classic-ignore", "Classic-ignore"), ("None", "None"), ] prompt_syntax_gui = gr.Dropdown( label="Prompt Syntax", choices=prompt_s_options, value=prompt_s_options[0][1] ) vae_model_gui = gr.Dropdown( label="VAE Model", choices=vae_model_list, value=vae_model_list[1] ) with gr.Accordion( "Hires fix", open=False, visible=True): upscaler_keys = list(upscaler_dict_gui.keys()) upscaler_model_path_gui = gr.Dropdown( label="Upscaler", choices=upscaler_keys, value=upscaler_keys[0] ) upscaler_increases_size_gui = gr.Slider( minimum=1.1, maximum=6., step=0.1, value=1.4, label="Upscale by" ) esrgan_tile_gui = gr.Slider( minimum=0, value=100, maximum=500, step=1, label="ESRGAN Tile" ) esrgan_tile_overlap_gui = gr.Slider( minimum=1, maximum=200, step=1, value=10, label="ESRGAN Tile Overlap" ) hires_steps_gui = gr.Slider( minimum=0, value=30, maximum=100, step=1, label="Hires Steps" ) hires_denoising_strength_gui = gr.Slider( minimum=0.1, maximum=1.0, step=0.01, value=0.55, label="Hires Denoising Strength" ) hires_sampler_gui = gr.Dropdown( label="Hires Sampler", choices=["Use same sampler"] + scheduler_names[:-1], value="Use same sampler" ) hires_prompt_gui = gr.Textbox( label="Hires Prompt", placeholder="Main prompt will be use", lines=3 ) hires_negative_prompt_gui = gr.Textbox( label="Hires Negative Prompt", placeholder="Main negative prompt will be use", lines=3 ) with gr.Accordion("LoRA", open=False, visible=True): lora1_gui = gr.Dropdown( label="Lora1", choices=lora_model_list ) lora_scale_1_gui = gr.Slider( minimum=-2, maximum=2, step=0.01, value=0.33, label="Lora Scale 1" ) lora2_gui = gr.Dropdown( label="Lora2", choices=lora_model_list ) lora_scale_2_gui = gr.Slider( minimum=-2, maximum=2, step=0.01, value=0.33, label="Lora Scale 2" ) lora3_gui = gr.Dropdown( label="Lora3", choices=lora_model_list ) lora_scale_3_gui = gr.Slider( minimum=-2, maximum=2, step=0.01, value=0.33, label="Lora Scale 3" ) lora4_gui = gr.Dropdown( label="Lora4", choices=lora_model_list ) lora_scale_4_gui = gr.Slider( minimum=-2, maximum=2, step=0.01, value=0.33, label="Lora Scale 4" ) lora5_gui = gr.Dropdown( label="Lora5", choices=lora_model_list ) lora_scale_5_gui = gr.Slider( minimum=-2, maximum=2, step=0.01, value=0.33, label="Lora Scale 5" ) with gr.Accordion( "From URL", open=False, visible=True): text_lora = gr.Textbox( label="URL", placeholder="http://...my_lora_url.safetensors", lines=1 ) button_lora = gr.Button("Get and update lists of LoRAs") button_lora.click( get_my_lora, [text_lora], [ lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui ] ) with gr.Accordion("IP-Adapter", open=False, visible=True): # IP-Adapter IP_MODELS = sorted( list( set( IP_ADAPTERS_SD + IP_ADAPTERS_SDXL ) ) ) MODE_IP_OPTIONS = [ "original", "style", "layout", "style+layout" ] with gr.Accordion("IP-Adapter 1", open=False, visible=True): image_ip1 = gr.Image( label="IP Image", type="filepath" ) mask_ip1 = gr.Image( label="IP Mask", type="filepath" ) model_ip1 = gr.Dropdown( value="plus_face", label="Model", choices=IP_MODELS ) mode_ip1 = gr.Dropdown( value="original", label="Mode", choices=MODE_IP_OPTIONS ) scale_ip1 = gr.Slider( minimum=0., maximum=2., step=0.01, value=0.7, label="Scale" ) with gr.Accordion("IP-Adapter 2", open=False, visible=True): image_ip2 = gr.Image( label="IP Image", type="filepath" ) mask_ip2 = gr.Image( label="IP Mask (optional)", type="filepath" ) model_ip2 = gr.Dropdown( value="base", label="Model", choices=IP_MODELS ) mode_ip2 = gr.Dropdown( value="style", label="Mode", choices=MODE_IP_OPTIONS ) scale_ip2 = gr.Slider( minimum=0., maximum=2., step=0.01, value=0.7, label="Scale" ) with gr.Accordion( "ControlNet / Img2img / Inpaint", open=False, visible=True): image_control = gr.Image( label="Image ControlNet/Inpaint/Img2img", type="filepath" ) image_mask_gui = gr.Image( label="Image Mask", type="filepath" ) strength_gui = gr.Slider( minimum=0.01, maximum=1.0, step=0.01, value=0.55, label="Strength", info="This option adjusts the level of changes for img2img and inpainting." ) image_resolution_gui = gr.Slider( minimum=64, maximum=2048, step=64, value=1024, label="Image Resolution" ) preprocessor_name_gui = gr.Dropdown( label="Preprocessor Name", choices=preprocessor_controlnet["canny"] ) def change_preprocessor_choices(task): task = task_stablepy[task] if task in preprocessor_controlnet.keys(): choices_task = preprocessor_controlnet[task] else: choices_task = preprocessor_controlnet["canny"] return gr.update( choices=choices_task, value=choices_task[0] ) task_gui.change( change_preprocessor_choices, [task_gui], [preprocessor_name_gui], ) preprocess_resolution_gui = gr.Slider( minimum=64, maximum=2048, step=64, value=512, label="Preprocess Resolution" ) low_threshold_gui = gr.Slider( minimum=1, maximum=255, step=1, value=100, label="Canny low threshold" ) high_threshold_gui = gr.Slider( minimum=1, maximum=255, step=1, value=200, label="Canny high threshold" ) value_threshold_gui = gr.Slider( minimum=1, maximum=2.0, step=0.01, value=0.1, label="Hough value threshold (MLSD)" ) distance_threshold_gui = gr.Slider( minimum=1, maximum=20.0, step=0.01, value=0.1, label="Hough distance threshold (MLSD)" ) control_net_output_scaling_gui = gr.Slider( minimum=0, maximum=5.0, step=0.1, value=1, label="ControlNet Output Scaling in UNet" ) control_net_start_threshold_gui = gr.Slider( minimum=0, maximum=1, step=0.01, value=0, label="ControlNet Start Threshold (%)" ) control_net_stop_threshold_gui = gr.Slider( minimum=0, maximum=1, step=0.01, value=1, label="ControlNet Stop Threshold (%)" ) with gr.Accordion( "T2I adapter", open=False, visible=True): t2i_adapter_preprocessor_gui = gr.Checkbox( value=True, label="T2i Adapter Preprocessor" ) adapter_conditioning_scale_gui = gr.Slider( minimum=0, maximum=5., step=0.1, value=1, label="Adapter Conditioning Scale" ) adapter_conditioning_factor_gui = gr.Slider( minimum=0, maximum=1., step=0.01, value=0.55, label="Adapter Conditioning Factor (%)" ) with gr.Accordion( "Styles", open=False, visible=True): try: style_names_found = sd_gen.model.STYLE_NAMES except: style_names_found = STYLE_NAMES style_prompt_gui = gr.Dropdown( style_names_found, multiselect=True, value=None, label="Style Prompt", interactive=True, ) style_json_gui = gr.File(label="Style JSON File") style_button = gr.Button("Load styles") def load_json_style_file(json): if not sd_gen.model: gr.Info("First load the model") return gr.update( value=None, choices=STYLE_NAMES ) sd_gen.model.load_style_file(json) gr.Info(f"{len(sd_gen.model.STYLE_NAMES)} styles loaded") return gr.update( value=None, choices=sd_gen.model.STYLE_NAMES ) style_button.click( load_json_style_file, [style_json_gui], [style_prompt_gui] ) with gr.Accordion( "Textual inversion", open=False, visible=False): active_textual_inversion_gui = gr.Checkbox( value=False, label="Active Textual Inversion in prompt" ) with gr.Accordion( "Detailfix", open=False, visible=True): # Adetailer Inpaint Only adetailer_inpaint_only_gui = gr.Checkbox(label="Inpaint only", value=True) # Adetailer Verbose adetailer_verbose_gui = gr.Checkbox(label="Verbose", value=False) # Adetailer Sampler adetailer_sampler_options = ["Use same sampler"] + scheduler_names[:-1] adetailer_sampler_gui = gr.Dropdown( label="Adetailer sampler:", choices=adetailer_sampler_options, value="Use same sampler" ) with gr.Accordion( "Detailfix A", open=False, visible=True): # Adetailer A adetailer_active_a_gui = gr.Checkbox( label="Enable Adetailer A", value=False ) prompt_ad_a_gui = gr.Textbox( label="Main prompt", placeholder="Main prompt will be use", lines=3 ) negative_prompt_ad_a_gui = gr.Textbox( label="Negative prompt", placeholder="Main negative prompt will be use", lines=3 ) strength_ad_a_gui = gr.Number( label="Strength:", value=0.35, step=0.01, minimum=0.01, maximum=1.0 ) face_detector_ad_a_gui = gr.Checkbox( label="Face detector", value=True ) person_detector_ad_a_gui = gr.Checkbox( label="Person detector", value=True ) hand_detector_ad_a_gui = gr.Checkbox( label="Hand detector", value=False ) mask_dilation_a_gui = gr.Number( label="Mask dilation:", value=4, minimum=1 ) mask_blur_a_gui = gr.Number( label="Mask blur:", value=4, minimum=1 ) mask_padding_a_gui = gr.Number( label="Mask padding:", value=32, minimum=1 ) with gr.Accordion( "Detailfix B", open=False, visible=True): # Adetailer B adetailer_active_b_gui = gr.Checkbox(label="Enable Adetailer B", value=False) prompt_ad_b_gui = gr.Textbox( label="Main prompt", placeholder="Main prompt will be use", lines=3 ) negative_prompt_ad_b_gui = gr.Textbox( label="Negative prompt", placeholder="Main negative prompt will be use", lines=3 ) strength_ad_b_gui = gr.Number( label="Strength:", value=0.35, step=0.01, minimum=0.01, maximum=1.0 ) face_detector_ad_b_gui = gr.Checkbox( label="Face detector", value=True ) person_detector_ad_b_gui = gr.Checkbox( label="Person detector", value=True ) hand_detector_ad_b_gui = gr.Checkbox( label="Hand detector", value=False ) mask_dilation_b_gui = gr.Number( label="Mask dilation:", value=4, minimum=1 ) mask_blur_b_gui = gr.Number( label="Mask blur:", value=4, minimum=1 ) mask_padding_b_gui = gr.Number( label="Mask padding:", value=32, minimum=1 ) with gr.Accordion( "Other settings", open=False, visible=True): image_previews_gui = gr.Checkbox( value=True, label="Image Previews" ) hires_before_adetailer_gui = gr.Checkbox( value=False, label="Hires Before Adetailer" ) hires_after_adetailer_gui = gr.Checkbox( value=True, label="Hires After Adetailer" ) generator_in_cpu_gui = gr.Checkbox( value=False, label="Generator in CPU" ) with gr.Accordion( "More settings", open=False, visible=False): loop_generation_gui = gr.Slider( minimum=1, value=1, label="Loop Generation" ) retain_task_cache_gui = gr.Checkbox( value=False, label="Retain task model in cache" ) leave_progress_bar_gui = gr.Checkbox( value=True, label="Leave Progress Bar" ) disable_progress_bar_gui = gr.Checkbox( value=False, label="Disable Progress Bar" ) display_images_gui = gr.Checkbox( value=True, label="Display Images" ) save_generated_images_gui = gr.Checkbox( value=False, label="Save Generated Images" ) image_storage_location_gui = gr.Textbox( value="./images", label="Image Storage Location" ) retain_compel_previous_load_gui = gr.Checkbox( value=False, label="Retain Compel Previous Load" ) retain_detailfix_model_previous_load_gui = gr.Checkbox( value=False, label="Retain Detailfix Model Previous Load" ) retain_hires_model_previous_load_gui = gr.Checkbox( value=False, label="Retain Hires Model Previous Load" ) xformers_memory_efficient_attention_gui = gr.Checkbox( value=False, label="Xformers Memory Efficient Attention" ) # example and Help Section with gr.Accordion("Examples and help", open=False, visible=True): gr.Markdown( """### Help: - The current space runs on a ZERO GPU which is assigned for approximately 60 seconds; Therefore, \ if you submit expensive tasks, the operation may be canceled upon reaching the \ maximum allowed time with 'GPU TASK ABORTED'. - Distorted or strange images often result from high prompt weights, \ so it's best to use low weights and scales, and consider using Classic variants like 'Classic-original'. - For better results with Pony Diffusion, \ try using sampler DPM++ 1s or DPM2 with Compel or Classic prompt weights. """ ) gr.Markdown( """### The following examples perform specific tasks: 1. Generation with SDXL and upscale 2. Generation with SDXL 3. ControlNet Canny SDXL 4. Optical pattern (Optical illusion) SDXL 5. Convert an image to a coloring drawing 6. ControlNet OpenPose SD 1.5 - Different tasks can be performed, such as img2img or using the IP adapter, \ to preserve a person's appearance or a specific style based on an image. """ ) gr.Examples( examples=example_prompts, fn=sd_gen.generate_pipeline, inputs=[ prompt_gui, neg_prompt_gui, num_images_gui, steps_gui, cfg_gui, clip_skip_gui, seed_gui, lora1_gui, lora_scale_1_gui, lora2_gui, lora_scale_2_gui, lora3_gui, lora_scale_3_gui, lora4_gui, lora_scale_4_gui, lora5_gui, lora_scale_5_gui, sampler_gui, img_height_gui, img_width_gui, model_name_gui, vae_model_gui, task_gui, image_control, preprocessor_name_gui, preprocess_resolution_gui, image_resolution_gui, style_prompt_gui, style_json_gui, image_mask_gui, strength_gui, low_threshold_gui, high_threshold_gui, value_threshold_gui, distance_threshold_gui, control_net_output_scaling_gui, control_net_start_threshold_gui, control_net_stop_threshold_gui, active_textual_inversion_gui, prompt_syntax_gui, upscaler_model_path_gui, ], outputs=[result_images], cache_examples=False, ) with gr.Tab("Inpaint mask maker", render=True): def create_mask_now(img, invert): import numpy as np import time time.sleep(0.5) transparent_image = img["layers"][0] # Extract the alpha channel alpha_channel = np.array(transparent_image)[:, :, 3] # Create a binary mask by thresholding the alpha channel binary_mask = alpha_channel > 1 if invert: print("Invert") # Invert the binary mask so that the drawn shape is white and the rest is black binary_mask = np.invert(binary_mask) # Convert the binary mask to a 3-channel RGB mask rgb_mask = np.stack((binary_mask,) * 3, axis=-1) # Convert the mask to uint8 rgb_mask = rgb_mask.astype(np.uint8) * 255 return img["background"], rgb_mask with gr.Row(): with gr.Column(scale=2): # image_base = gr.ImageEditor(label="Base image", show_label=True, brush=gr.Brush(colors=["#000000"])) image_base = gr.ImageEditor( sources=[ "upload", "clipboard" ], # crop_size="1:1", # enable crop (or disable it) # transforms=["crop"], brush=gr.Brush( default_size="16", # or leave it as 'auto' color_mode="fixed", # 'fixed' hides the user swatches and colorpicker, 'defaults' shows it # default_color="black", # html names are supported colors=[ "rgba(0, 0, 0, 1)", # rgb(a) "rgba(0, 0, 0, 0.1)", "rgba(255, 255, 255, 0.1)", # "hsl(360, 120, 120)" # in fact any valid colorstring ] ), eraser=gr.Eraser(default_size="16") ) invert_mask = gr.Checkbox( value=False, label="Invert mask" ) btn = gr.Button("Create mask") with gr.Column(scale=1): img_source = gr.Image(interactive=False) img_result = gr.Image( label="Mask image", show_label=True, interactive=False ) btn_send = gr.Button("Send to the first tab") btn.click( create_mask_now, [image_base, invert_mask], [img_source, img_result] ) def send_img(img_source, img_result) -> tuple: return img_source, img_result btn_send.click( send_img, [img_source, img_result], [image_control, image_mask_gui] ) generate_button.click( fn=sd_gen.load_new_model, inputs=[ model_name_gui, vae_model_gui, task_gui ], outputs=[load_model_gui], queue=True, show_progress="minimal", ).success( fn=sd_gen.generate_pipeline, inputs=[ prompt_gui, neg_prompt_gui, num_images_gui, steps_gui, cfg_gui, clip_skip_gui, seed_gui, lora1_gui, lora_scale_1_gui, lora2_gui, lora_scale_2_gui, lora3_gui, lora_scale_3_gui, lora4_gui, lora_scale_4_gui, lora5_gui, lora_scale_5_gui, sampler_gui, img_height_gui, img_width_gui, model_name_gui, vae_model_gui, task_gui, image_control, preprocessor_name_gui, preprocess_resolution_gui, image_resolution_gui, style_prompt_gui, style_json_gui, image_mask_gui, strength_gui, low_threshold_gui, high_threshold_gui, value_threshold_gui, distance_threshold_gui, control_net_output_scaling_gui, control_net_start_threshold_gui, control_net_stop_threshold_gui, active_textual_inversion_gui, prompt_syntax_gui, upscaler_model_path_gui, upscaler_increases_size_gui, esrgan_tile_gui, esrgan_tile_overlap_gui, hires_steps_gui, hires_denoising_strength_gui, hires_sampler_gui, hires_prompt_gui, hires_negative_prompt_gui, hires_before_adetailer_gui, hires_after_adetailer_gui, loop_generation_gui, leave_progress_bar_gui, disable_progress_bar_gui, image_previews_gui, display_images_gui, save_generated_images_gui, image_storage_location_gui, retain_compel_previous_load_gui, retain_detailfix_model_previous_load_gui, retain_hires_model_previous_load_gui, t2i_adapter_preprocessor_gui, adapter_conditioning_scale_gui, adapter_conditioning_factor_gui, xformers_memory_efficient_attention_gui, free_u_gui, generator_in_cpu_gui, adetailer_inpaint_only_gui, adetailer_verbose_gui, adetailer_sampler_gui, adetailer_active_a_gui, prompt_ad_a_gui, negative_prompt_ad_a_gui, strength_ad_a_gui, face_detector_ad_a_gui, person_detector_ad_a_gui, hand_detector_ad_a_gui, mask_dilation_a_gui, mask_blur_a_gui, mask_padding_a_gui, adetailer_active_b_gui, prompt_ad_b_gui, negative_prompt_ad_b_gui, strength_ad_b_gui, face_detector_ad_b_gui, person_detector_ad_b_gui, hand_detector_ad_b_gui, mask_dilation_b_gui, mask_blur_b_gui, mask_padding_b_gui, retain_task_cache_gui, image_ip1, mask_ip1, model_ip1, mode_ip1, scale_ip1, image_ip2, mask_ip2, model_ip2, mode_ip2, scale_ip2, ], outputs=[ result_images, actual_task_info ], queue=True, show_progress="minimal", ) app.queue() app.launch( show_error=True, debug=True, )