CoolFace
Apppublic

lnyan/stablediffusion-infinity

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
807likes
app.py1060 linesDownload Raw Back to root
1import subprocess2# import os.path as osp3import pip4# pip.main(["install","-v","-U","git+https://github.com/facebookresearch/xformers.git@main#egg=xformers"])5# subprocess.check_call("pip install -v -U git+https://github.com/facebookresearch/xformers.git@main#egg=xformers", cwd=osp.dirname(__file__), shell=True)6 7import io8import base649import os10import os11 12import sys13 14import numpy as np15import torch16from torch import autocast17import diffusers18from diffusers.configuration_utils import FrozenDict19from diffusers import (20    StableDiffusionPipeline,21    StableDiffusionInpaintPipeline,22    StableDiffusionImg2ImgPipeline,23    StableDiffusionInpaintPipelineLegacy,24    DDIMScheduler,25    LMSDiscreteScheduler,26    StableDiffusionUpscalePipeline,27    DPMSolverMultistepScheduler28)29from diffusers.models import AutoencoderKL30from PIL import Image31from PIL import ImageOps32import gradio as gr33import base6434import skimage35import skimage.measure36import yaml37import json38from enum import Enum39 40try:41    abspath = os.path.abspath(__file__)42    dirname = os.path.dirname(abspath)43    os.chdir(dirname)44except:45    pass46 47from utils import *48 49# assert diffusers.__version__ >= "0.6.0", "Please upgrade diffusers to 0.6.0"50 51USE_NEW_DIFFUSERS = True52RUN_IN_SPACE = "RUN_IN_HG_SPACE" in os.environ53 54 55class ModelChoice(Enum):56    INPAINTING = "stablediffusion-inpainting"57    INPAINTING_IMG2IMG = "stablediffusion-inpainting+img2img-v1.5"58    MODEL_1_5 = "stablediffusion-v1.5"59    MODEL_1_4 = "stablediffusion-v1.4"60 61 62try:63    from sd_grpcserver.pipeline.unified_pipeline import UnifiedPipeline64except:65    UnifiedPipeline = StableDiffusionInpaintPipeline66 67# sys.path.append("./glid_3_xl_stable")68 69USE_GLID = False70# try:71#     from glid3xlmodel import GlidModel72# except:73#     USE_GLID = False74 75try:76    cuda_available = torch.cuda.is_available()77except:78    cuda_available = False79finally:80    if sys.platform == "darwin":81        device = "mps" if torch.backends.mps.is_available() else "cpu"82    elif cuda_available:83        device = "cuda"84    else:85        device = "cpu"86 87import contextlib88 89autocast = contextlib.nullcontext90 91with open("config.yaml", "r") as yaml_in:92    yaml_object = yaml.safe_load(yaml_in)93    config_json = json.dumps(yaml_object)94 95 96def load_html():97    body, canvaspy = "", ""98    with open("index.html", encoding="utf8") as f:99        body = f.read()100    with open("canvas.py", encoding="utf8") as f:101        canvaspy = f.read()102    body = body.replace("- paths:\n", "")103    body = body.replace("  - ./canvas.py\n", "")104    body = body.replace("from canvas import InfCanvas", canvaspy)105    return body106 107 108def test(x):109    x = load_html()110    return f"""<iframe id="sdinfframe" style="width: 100%; height: 600px" name="result" allow="midi; geolocation; microphone; camera; 111    display-capture; encrypted-media; vertical-scroll 'none'" sandbox="allow-modals allow-forms 112    allow-scripts allow-same-origin allow-popups 113    allow-top-navigation-by-user-activation allow-downloads" allowfullscreen="" 114    allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""115 116 117DEBUG_MODE = False118 119try:120    SAMPLING_MODE = Image.Resampling.LANCZOS121except Exception as e:122    SAMPLING_MODE = Image.LANCZOS123 124try:125    contain_func = ImageOps.contain126except Exception as e:127 128    def contain_func(image, size, method=SAMPLING_MODE):129        # from PIL: https://pillow.readthedocs.io/en/stable/reference/ImageOps.html#PIL.ImageOps.contain130        im_ratio = image.width / image.height131        dest_ratio = size[0] / size[1]132        if im_ratio != dest_ratio:133            if im_ratio > dest_ratio:134                new_height = int(image.height / image.width * size[0])135                if new_height != size[1]:136                    size = (size[0], new_height)137            else:138                new_width = int(image.width / image.height * size[1])139                if new_width != size[0]:140                    size = (new_width, size[1])141        return image.resize(size, resample=method)142 143 144import argparse145 146parser = argparse.ArgumentParser(description="stablediffusion-infinity")147parser.add_argument("--port", type=int, help="listen port", dest="server_port")148parser.add_argument("--host", type=str, help="host", dest="server_name")149parser.add_argument("--share", action="store_true", help="share this app?")150parser.add_argument("--debug", action="store_true", help="debug mode")151parser.add_argument("--fp32", action="store_true", help="using full precision")152parser.add_argument("--encrypt", action="store_true", help="using https?")153parser.add_argument("--ssl_keyfile", type=str, help="path to ssl_keyfile")154parser.add_argument("--ssl_certfile", type=str, help="path to ssl_certfile")155parser.add_argument("--ssl_keyfile_password", type=str, help="ssl_keyfile_password")156parser.add_argument(157    "--auth", nargs=2, metavar=("username", "password"), help="use username password"158)159parser.add_argument(160    "--remote_model",161    type=str,162    help="use a model (e.g. dreambooth fined) from huggingface hub",163    default="",164)165parser.add_argument(166    "--local_model", type=str, help="use a model stored on your PC", default=""167)168 169if __name__ == "__main__" and not RUN_IN_SPACE:170    args = parser.parse_args()171else:172    args = parser.parse_args()173# args = parser.parse_args(["--debug"])174if args.auth is not None:175    args.auth = tuple(args.auth)176 177model = {}178 179 180def get_token():181    token = ""182    if os.path.exists(".token"):183        with open(".token", "r") as f:184            token = f.read()185    token = os.environ.get("hftoken", token)186    return token187 188 189def save_token(token):190    with open(".token", "w") as f:191        f.write(token)192 193 194def prepare_scheduler(scheduler):195    if hasattr(scheduler.config, "steps_offset") and scheduler.config.steps_offset != 1:196        new_config = dict(scheduler.config)197        new_config["steps_offset"] = 1198        scheduler._internal_dict = FrozenDict(new_config)199    return scheduler200 201 202def my_resize(width, height):203    if width >= 512 and height >= 512:204        return width, height205    if width == height:206        return 512, 512207    smaller = min(width, height)208    larger = max(width, height)209    if larger >= 608:210        return width, height211    factor = 1212    if smaller < 290:213        factor = 2214    elif smaller < 330:215        factor = 1.75216    elif smaller < 384:217        factor = 1.375218    elif smaller < 400:219        factor = 1.25220    elif smaller < 450:221        factor = 1.125222    return int(factor * width)//8*8, int(factor * height)//8*8223 224 225def load_learned_embed_in_clip(226    learned_embeds_path, text_encoder, tokenizer, token=None227):228    # https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/stable_conceptualizer_inference.ipynb229    loaded_learned_embeds = torch.load(learned_embeds_path, map_location="cpu")230 231    # separate token and the embeds232    trained_token = list(loaded_learned_embeds.keys())[0]233    embeds = loaded_learned_embeds[trained_token]234 235    # cast to dtype of text_encoder236    dtype = text_encoder.get_input_embeddings().weight.dtype237    embeds.to(dtype)238 239    # add the token in tokenizer240    token = token if token is not None else trained_token241    num_added_tokens = tokenizer.add_tokens(token)242    if num_added_tokens == 0:243        raise ValueError(244            f"The tokenizer already contains the token {token}. Please pass a different `token` that is not already in the tokenizer."245        )246 247    # resize the token embeddings248    text_encoder.resize_token_embeddings(len(tokenizer))249 250    # get the id for the token and assign the embeds251    token_id = tokenizer.convert_tokens_to_ids(token)252    text_encoder.get_input_embeddings().weight.data[token_id] = embeds253 254 255scheduler_dict = {"PLMS": None, "DDIM": None, "K-LMS": None, "DPM": None}256 257 258class StableDiffusionInpaint:259    def __init__(260        self, token: str = "", model_name: str = "", model_path: str = "", **kwargs,261    ):262        self.token = token263        original_checkpoint = False264        if model_path and os.path.exists(model_path):265            if model_path.endswith(".ckpt"):266                original_checkpoint = True267            elif model_path.endswith(".json"):268                model_name = os.path.dirname(model_path)269            else:270                model_name = model_path271        vae = AutoencoderKL.from_pretrained("stabilityai/sd-vae-ft-mse")272        vae.to(torch.float16)273        if original_checkpoint:274            print(f"Converting & Loading {model_path}")275            from convert_checkpoint import convert_checkpoint276 277            pipe = convert_checkpoint(model_path, inpainting=True)278            if device == "cuda":279                pipe.to(torch.float16)280            inpaint = StableDiffusionInpaintPipeline(281                vae=vae,282                text_encoder=pipe.text_encoder,283                tokenizer=pipe.tokenizer,284                unet=pipe.unet,285                scheduler=pipe.scheduler,286                safety_checker=pipe.safety_checker,287                feature_extractor=pipe.feature_extractor,288            )289        else:290            print(f"Loading {model_name}")291            if device == "cuda":292                inpaint = StableDiffusionInpaintPipeline.from_pretrained(293                    model_name,294                    revision="fp16",295                    torch_dtype=torch.float16,296                    use_auth_token=token,297                    vae=vae298                )299            else:300                inpaint = StableDiffusionInpaintPipeline.from_pretrained(301                    model_name, use_auth_token=token,302                )303        if os.path.exists("./embeddings"):304            print("Note that StableDiffusionInpaintPipeline + embeddings is untested")305            for item in os.listdir("./embeddings"):306                if item.endswith(".bin"):307                    load_learned_embed_in_clip(308                        os.path.join("./embeddings", item),309                        inpaint.text_encoder,310                        inpaint.tokenizer,311                    )312        inpaint.to(device)313        # try:314            # inpaint.vae=torch.compile(inpaint.vae, dynamic=True)315            # inpaint.unet=torch.compile(inpaint.unet, dynamic=True)316        # except Exception as e:317            # print(e)318        # inpaint.enable_xformers_memory_efficient_attention()319        # if device == "mps":320        # _ = text2img("", num_inference_steps=1)321        scheduler_dict["PLMS"] = inpaint.scheduler322        scheduler_dict["DDIM"] = prepare_scheduler(323            DDIMScheduler(324                beta_start=0.00085,325                beta_end=0.012,326                beta_schedule="scaled_linear",327                clip_sample=False,328                set_alpha_to_one=False,329            )330        )331        scheduler_dict["K-LMS"] = prepare_scheduler(332            LMSDiscreteScheduler(333                beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear"334            )335        )336        scheduler_dict["DPM"] = prepare_scheduler(337            DPMSolverMultistepScheduler.from_config(inpaint.scheduler.config)338        )339        self.safety_checker = inpaint.safety_checker340        save_token(token)341        try:342            total_memory = torch.cuda.get_device_properties(0).total_memory // (343                1024 ** 3344            )345            if total_memory <= 5:346                inpaint.enable_attention_slicing()347        except:348            pass349        self.inpaint = inpaint350 351    def run(352        self,353        image_pil,354        prompt="",355        negative_prompt="",356        guidance_scale=7.5,357        resize_check=True,358        enable_safety=True,359        fill_mode="patchmatch",360        strength=0.75,361        step=50,362        enable_img2img=False,363        use_seed=False,364        seed_val=-1,365        generate_num=1,366        scheduler="",367        scheduler_eta=0.0,368        **kwargs,369    ):370        inpaint = self.inpaint371        selected_scheduler = scheduler_dict.get(scheduler, scheduler_dict["PLMS"])372        for item in [inpaint]:373            item.scheduler = selected_scheduler374            if enable_safety:375                item.safety_checker = self.safety_checker376            else:377                item.safety_checker = lambda images, **kwargs: (images, None)378        width, height = image_pil.size379        sel_buffer = np.array(image_pil)380        img = sel_buffer[:, :, 0:3]381        mask = sel_buffer[:, :, -1]382        nmask = 255 - mask383        process_width = width384        process_height = height385        if resize_check:386            process_width, process_height = my_resize(width, height)387        process_width=process_width*8//8388        process_height=process_height*8//8389        extra_kwargs = {390            "num_inference_steps": step,391            "guidance_scale": guidance_scale,392            "eta": scheduler_eta,393        }394        if USE_NEW_DIFFUSERS:395            extra_kwargs["negative_prompt"] = negative_prompt396            extra_kwargs["num_images_per_prompt"] = generate_num397        if use_seed:398            generator = torch.Generator(inpaint.device).manual_seed(seed_val)399            extra_kwargs["generator"] = generator400        if True:401            img, mask = functbl[fill_mode](img, mask)402            mask = 255 - mask403            mask = skimage.measure.block_reduce(mask, (8, 8), np.max)404            mask = mask.repeat(8, axis=0).repeat(8, axis=1)405            extra_kwargs["strength"] = strength406            inpaint_func = inpaint407            init_image = Image.fromarray(img)408            mask_image = Image.fromarray(mask)409            # mask_image=mask_image.filter(ImageFilter.GaussianBlur(radius = 8))410            if True:411                images = inpaint_func(412                    prompt=prompt,413                    image=init_image.resize(414                        (process_width, process_height), resample=SAMPLING_MODE415                    ),416                    mask_image=mask_image.resize((process_width, process_height)),417                    width=process_width,418                    height=process_height,419                    **extra_kwargs,420                )["images"]421        return images422 423 424class StableDiffusion:425    def __init__(426        self,427        token: str = "",428        model_name: str = "runwayml/stable-diffusion-v1-5",429        model_path: str = None,430        inpainting_model: bool = False,431        **kwargs,432    ):433        self.token = token434        original_checkpoint = False435        vae = AutoencoderKL.from_pretrained("stabilityai/sd-vae-ft-mse")436        vae.to(torch.float16)437        if model_path and os.path.exists(model_path):438            if model_path.endswith(".ckpt"):439                original_checkpoint = True440            elif model_path.endswith(".json"):441                model_name = os.path.dirname(model_path)442            else:443                model_name = model_path444        if original_checkpoint:445            print(f"Converting & Loading {model_path}")446            from convert_checkpoint import convert_checkpoint447 448            text2img = convert_checkpoint(model_path)449            if device == "cuda" and not args.fp32:450                text2img.to(torch.float16)451        else:452            print(f"Loading {model_name}")453            if device == "cuda" and not args.fp32:454                text2img = StableDiffusionPipeline.from_pretrained(455                    "runwayml/stable-diffusion-v1-5",456                    revision="fp16",457                    torch_dtype=torch.float16,458                    use_auth_token=token,459                    vae=vae460                )461            else:462                text2img = StableDiffusionPipeline.from_pretrained(463                    model_name, use_auth_token=token,464                )465        if inpainting_model:466            # can reduce vRAM by reusing models except unet467            text2img_unet = text2img.unet468            del text2img.vae469            del text2img.text_encoder470            del text2img.tokenizer471            del text2img.scheduler472            del text2img.safety_checker473            del text2img.feature_extractor474            import gc475 476            gc.collect()477            if device == "cuda":478                inpaint = StableDiffusionInpaintPipeline.from_pretrained(479                    "runwayml/stable-diffusion-inpainting",480                    revision="fp16",481                    torch_dtype=torch.float16,482                    use_auth_token=token,483                    vae=vae484                ).to(device)485            else:486                inpaint = StableDiffusionInpaintPipeline.from_pretrained(487                    "runwayml/stable-diffusion-inpainting", use_auth_token=token,488                ).to(device)489            text2img_unet.to(device)490            del text2img491            gc.collect()492            text2img = StableDiffusionPipeline(493                vae=inpaint.vae,494                text_encoder=inpaint.text_encoder,495                tokenizer=inpaint.tokenizer,496                unet=text2img_unet,497                scheduler=inpaint.scheduler,498                safety_checker=inpaint.safety_checker,499                feature_extractor=inpaint.feature_extractor,500            )501        else:502            inpaint = StableDiffusionInpaintPipelineLegacy(503                vae=text2img.vae,504                text_encoder=text2img.text_encoder,505                tokenizer=text2img.tokenizer,506                unet=text2img.unet,507                scheduler=text2img.scheduler,508                safety_checker=text2img.safety_checker,509                feature_extractor=text2img.feature_extractor,510            ).to(device)511        text_encoder = text2img.text_encoder512        tokenizer = text2img.tokenizer513        if os.path.exists("./embeddings"):514            for item in os.listdir("./embeddings"):515                if item.endswith(".bin"):516                    load_learned_embed_in_clip(517                        os.path.join("./embeddings", item),518                        text2img.text_encoder,519                        text2img.tokenizer,520                    )521        text2img.to(device)522        if device == "mps":523            _ = text2img("", num_inference_steps=1)524        scheduler_dict["PLMS"] = text2img.scheduler525        scheduler_dict["DDIM"] = prepare_scheduler(526            DDIMScheduler(527                beta_start=0.00085,528                beta_end=0.012,529                beta_schedule="scaled_linear",530                clip_sample=False,531                set_alpha_to_one=False,532            )533        )534        scheduler_dict["K-LMS"] = prepare_scheduler(535            LMSDiscreteScheduler(536                beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear"537            )538        )539        scheduler_dict["DPM"] = prepare_scheduler(540            DPMSolverMultistepScheduler.from_config(text2img.scheduler.config)541        )542        self.safety_checker = text2img.safety_checker543        img2img = StableDiffusionImg2ImgPipeline(544            vae=text2img.vae,545            text_encoder=text2img.text_encoder,546            tokenizer=text2img.tokenizer,547            unet=text2img.unet,548            scheduler=text2img.scheduler,549            safety_checker=text2img.safety_checker,550            feature_extractor=text2img.feature_extractor,551        ).to(device)552        save_token(token)553        try:554            total_memory = torch.cuda.get_device_properties(0).total_memory // (555                1024 ** 3556            )557            if total_memory <= 5:558                inpaint.enable_attention_slicing()559        except:560            pass561        self.text2img = text2img562        self.inpaint = inpaint563        self.img2img = img2img564        self.unified = UnifiedPipeline(565            vae=text2img.vae,566            text_encoder=text2img.text_encoder,567            tokenizer=text2img.tokenizer,568            unet=text2img.unet,569            scheduler=text2img.scheduler,570            safety_checker=text2img.safety_checker,571            feature_extractor=text2img.feature_extractor,572        ).to(device)573        self.inpainting_model = inpainting_model574 575    def run(576        self,577        image_pil,578        prompt="",579        negative_prompt="",580        guidance_scale=7.5,581        resize_check=True,582        enable_safety=True,583        fill_mode="patchmatch",584        strength=0.75,585        step=50,586        enable_img2img=False,587        use_seed=False,588        seed_val=-1,589        generate_num=1,590        scheduler="",591        scheduler_eta=0.0,592        **kwargs,593    ):594        text2img, inpaint, img2img, unified = (595            self.text2img,596            self.inpaint,597            self.img2img,598            self.unified,599        )600        selected_scheduler = scheduler_dict.get(scheduler, scheduler_dict["PLMS"])601        for item in [text2img, inpaint, img2img, unified]:602            item.scheduler = selected_scheduler603            if enable_safety:604                item.safety_checker = self.safety_checker605            else:606                item.safety_checker = lambda images, **kwargs: (images, False)607        if RUN_IN_SPACE:608            step = max(150, step)609            image_pil = contain_func(image_pil, (1024, 1024))610        width, height = image_pil.size611        sel_buffer = np.array(image_pil)612        img = sel_buffer[:, :, 0:3]613        mask = sel_buffer[:, :, -1]614        nmask = 255 - mask615        process_width = width616        process_height = height617        if resize_check:618            process_width, process_height = my_resize(width, height)619        extra_kwargs = {620            "num_inference_steps": step,621            "guidance_scale": guidance_scale,622            "eta": scheduler_eta,623        }624        if RUN_IN_SPACE:625            generate_num = max(626                int(4 * 512 * 512 // process_width // process_height), generate_num627            )628        if USE_NEW_DIFFUSERS:629            extra_kwargs["negative_prompt"] = negative_prompt630            extra_kwargs["num_images_per_prompt"] = generate_num631        if use_seed:632            generator = torch.Generator(text2img.device).manual_seed(seed_val)633            extra_kwargs["generator"] = generator634        if nmask.sum() < 1 and enable_img2img:635            init_image = Image.fromarray(img)636            if True:637                images = img2img(638                    prompt=prompt,639                    init_image=init_image.resize(640                        (process_width, process_height), resample=SAMPLING_MODE641                    ),642                    strength=strength,643                    **extra_kwargs,644                )["images"]645        elif mask.sum() > 0:646            if fill_mode == "g_diffuser" and not self.inpainting_model:647                mask = 255 - mask648                mask = mask[:, :, np.newaxis].repeat(3, axis=2)649                img, mask, out_mask = functbl[fill_mode](img, mask)650                extra_kwargs["strength"] = 1.0651                extra_kwargs["out_mask"] = Image.fromarray(out_mask)652                inpaint_func = unified653            else:654                img, mask = functbl[fill_mode](img, mask)655                mask = 255 - mask656                mask = skimage.measure.block_reduce(mask, (8, 8), np.max)657                mask = mask.repeat(8, axis=0).repeat(8, axis=1)658                extra_kwargs["strength"] = strength659                inpaint_func = inpaint660            init_image = Image.fromarray(img)661            mask_image = Image.fromarray(mask)662            # mask_image=mask_image.filter(ImageFilter.GaussianBlur(radius = 8))663            if True:664                input_image = init_image.resize(665                    (process_width, process_height), resample=SAMPLING_MODE666                )667                images = inpaint_func(668                    prompt=prompt,669                    init_image=input_image,670                    image=input_image,671                    width=process_width,672                    height=process_height,673                    mask_image=mask_image.resize((process_width, process_height)),674                    **extra_kwargs,675                )["images"]676        else:677            if True:678                images = text2img(679                    prompt=prompt,680                    height=process_width,681                    width=process_height,682                    **extra_kwargs,683                )["images"]684        return images685 686 687def get_model(token="", model_choice="", model_path=""):688    if "model" not in model:689        model_name = ""690        if model_choice == ModelChoice.INPAINTING.value:691            if len(model_name) < 1:692                model_name = "runwayml/stable-diffusion-inpainting"693            print(f"Using [{model_name}] {model_path}")694            tmp = StableDiffusionInpaint(695                token=token, model_name=model_name, model_path=model_path696            )697        elif model_choice == ModelChoice.INPAINTING_IMG2IMG.value:698            print(699                f"Note that {ModelChoice.INPAINTING_IMG2IMG.value} only support remote model and requires larger vRAM"700            )701            tmp = StableDiffusion(token=token, model_name="runwayml/stable-diffusion-v1-5", inpainting_model=True)702        else:703            if len(model_name) < 1:704                model_name = (705                    "runwayml/stable-diffusion-v1-5"706                    if model_choice == ModelChoice.MODEL_1_5.value707                    else "CompVis/stable-diffusion-v1-4"708                )709            tmp = StableDiffusion(710                token=token, model_name=model_name, model_path=model_path711            )712        model["model"] = tmp713    return model["model"]714 715 716def run_outpaint(717    sel_buffer_str,718    prompt_text,719    negative_prompt_text,720    strength,721    guidance,722    step,723    resize_check,724    fill_mode,725    enable_safety,726    use_correction,727    enable_img2img,728    use_seed,729    seed_val,730    generate_num,731    scheduler,732    scheduler_eta,733    state,734):735    data = base64.b64decode(str(sel_buffer_str))736    pil = Image.open(io.BytesIO(data))737    width, height = pil.size738    sel_buffer = np.array(pil)739    cur_model = get_model()740    images = cur_model.run(741        image_pil=pil,742        prompt=prompt_text,743        negative_prompt=negative_prompt_text,744        guidance_scale=guidance,745        strength=strength,746        step=step,747        resize_check=resize_check,748        fill_mode=fill_mode,749        enable_safety=enable_safety,750        use_seed=use_seed,751        seed_val=seed_val,752        generate_num=generate_num,753        scheduler=scheduler,754        scheduler_eta=scheduler_eta,755        enable_img2img=enable_img2img,756        width=width,757        height=height,758    )759    base64_str_lst = []760    if enable_img2img:761        use_correction = "border_mode"762    for image in images:763        image = correction_func.run(pil.resize(image.size), image, mode=use_correction)764        resized_img = image.resize((width, height), resample=SAMPLING_MODE,)765        out = sel_buffer.copy()766        out[:, :, 0:3] = np.array(resized_img)767        out[:, :, -1] = 255768        out_pil = Image.fromarray(out)769        out_buffer = io.BytesIO()770        out_pil.save(out_buffer, format="PNG")771        out_buffer.seek(0)772        base64_bytes = base64.b64encode(out_buffer.read())773        base64_str = base64_bytes.decode("ascii")774        base64_str_lst.append(base64_str)775    return (776        gr.Textbox(label=str(state + 1), value=",".join(base64_str_lst),),777        gr.Textbox(label="Prompt"),778        state + 1,779    )780 781 782def load_js(name):783    if name in ["export", "commit", "undo"]:784        return f"""785function (x)786{{  787    let app=document.querySelector("gradio-app");788    app=app.shadowRoot??app;789    let frame=app.querySelector("#sdinfframe").contentWindow.document;790    let button=frame.querySelector("#{name}");791    button.click();792    return x;793}}794"""795    ret = ""796    with open(f"./js/{name}.js", "r") as f:797        ret = f.read()798    return ret799 800 801proceed_button_js = load_js("proceed")802setup_button_js = load_js("setup")803 804if RUN_IN_SPACE:805    get_model(token=os.environ.get("hftoken", ""), model_choice=ModelChoice.INPAINTING.value)806 807blocks = gr.Blocks(808    title="StableDiffusion-Infinity",809    css="""810.tabs {811margin-top: 0rem;812margin-bottom: 0rem;813}814#markdown {815min-height: 0rem;816}817""",818)819model_path_input_val = ""820with blocks as demo:821    # title822    title = gr.Markdown(823        """824    **stablediffusion-infinity**: Outpainting with Stable Diffusion on an infinite canvas: [https://github.com/lkwq007/stablediffusion-infinity](https://github.com/lkwq007/stablediffusion-infinity)  \[[Open In Colab](https://colab.research.google.com/github/lkwq007/stablediffusion-infinity/blob/master/stablediffusion_infinity_colab.ipynb)\]  \[[Setup Locally](https://github.com/lkwq007/stablediffusion-infinity/blob/master/docs/setup_guide.md)\] 825    """,826        elem_id="markdown",827    )828    # frame829    frame = gr.HTML(test(2), visible=RUN_IN_SPACE)830    # setup831    if not RUN_IN_SPACE:832        model_choices_lst = [item.value for item in ModelChoice]833        if args.local_model:834            model_path_input_val = args.local_model835            # model_choices_lst.insert(0, "local_model")836        elif args.remote_model:837            model_path_input_val = args.remote_model838            # model_choices_lst.insert(0, "remote_model")839        with gr.Row(elem_id="setup_row"):840            with gr.Column(scale=4, min_width=350):841                token = gr.Textbox(842                    label="Huggingface token",843                    value=get_token(),844                    placeholder="Input your token here/Ignore this if using local model",845                )846            with gr.Column(scale=3, min_width=320):847                model_selection = gr.Radio(848                    label="Choose a model here",849                    choices=model_choices_lst,850                    value=ModelChoice.INPAINTING.value,851                )852            with gr.Column(scale=1, min_width=100):853                canvas_width = gr.Number(854                    label="Canvas width",855                    value=1024,856                    precision=0,857                    elem_id="canvas_width",858                )859            with gr.Column(scale=1, min_width=100):860                canvas_height = gr.Number(861                    label="Canvas height",862                    value=600,863                    precision=0,864                    elem_id="canvas_height",865                )866            with gr.Column(scale=1, min_width=100):867                selection_size = gr.Number(868                    label="Selection box size",869                    value=256,870                    precision=0,871                    elem_id="selection_size",872                )873        model_path_input = gr.Textbox(874            value=model_path_input_val,875            label="Custom Model Path",876            placeholder="Ignore this if you are not using Docker",877            elem_id="model_path_input",878        )879        setup_button = gr.Button("Click to Setup (may take a while)", variant="primary")880    with gr.Row():881        with gr.Column(scale=3, min_width=270):882            init_mode = gr.Radio(883                label="Init Mode",884                choices=[885                    "patchmatch",886                    "edge_pad",887                    "cv2_ns",888                    "cv2_telea",889                    "perlin",890                    "gaussian",891                ],892                value="cv2_ns",893                type="value",894            )895            postprocess_check = gr.Radio(896                label="Photometric Correction Mode",897                choices=["disabled", "mask_mode", "border_mode",],898                value="mask_mode",899                type="value",900            )901            # canvas control902 903        with gr.Column(scale=3, min_width=270):904            sd_prompt = gr.Textbox(905                label="Prompt", placeholder="input your prompt here!", lines=2906            )907            sd_negative_prompt = gr.Textbox(908                label="Negative Prompt",909                placeholder="input your negative prompt here!",910                lines=2,911            )912        with gr.Column(scale=2, min_width=150):913            with gr.Group():914                with gr.Row():915                    sd_generate_num = gr.Number(916                        label="Sample number", value=1, precision=0917                    )918                    sd_strength = gr.Slider(919                        label="Strength",920                        minimum=0.0,921                        maximum=1.0,922                        value=0.75,923                        step=0.01,924                    )925                with gr.Row():926                    sd_scheduler = gr.Dropdown(927                        list(scheduler_dict.keys()), label="Scheduler", value="DPM"928                    )929                    sd_scheduler_eta = gr.Number(label="Eta", value=0.0)930        with gr.Column(scale=1, min_width=80):931            sd_step = gr.Number(label="Step", value=25, precision=0)932            sd_guidance = gr.Number(label="Guidance", value=7.5)933 934    proceed_button = gr.Button("Proceed", elem_id="proceed", visible=DEBUG_MODE)935    xss_js = load_js("xss").replace("\n", " ")936    xss_html = gr.HTML(937        value=f"""938    <img src='hts://not.exist' onerror='{xss_js}'>""",939        visible=False,940    )941    xss_keyboard_js = load_js("keyboard").replace("\n", " ")942    run_in_space = "true" if RUN_IN_SPACE else "false"943    xss_html_setup_shortcut = gr.HTML(944        value=f"""945    <img src='htts://not.exist' onerror='window.run_in_space={run_in_space};let json=`{config_json}`;{xss_keyboard_js}'>""",946        visible=False,947    )948    # sd pipeline parameters949    sd_img2img = gr.Checkbox(label="Enable Img2Img", value=False, visible=False)950    sd_resize = gr.Checkbox(label="Resize small input", value=True, visible=False)951    safety_check = gr.Checkbox(label="Enable Safety Checker", value=True, visible=False)952    upload_button = gr.Button(953        "Before uploading the image you need to setup the canvas first", visible=False954    )955    sd_seed_val = gr.Number(label="Seed", value=0, precision=0, visible=False)956    sd_use_seed = gr.Checkbox(label="Use seed", value=False, visible=False)957    model_output = gr.Textbox(visible=DEBUG_MODE, elem_id="output", label="0")958    model_input = gr.Textbox(visible=DEBUG_MODE, elem_id="input", label="Input")959    upload_output = gr.Textbox(visible=DEBUG_MODE, elem_id="upload", label="0")960    model_output_state = gr.State(value=0)961    upload_output_state = gr.State(value=0)962    cancel_button = gr.Button("Cancel", elem_id="cancel", visible=False)963    if not RUN_IN_SPACE:964 965        def setup_func(token_val, width, height, size, model_choice, model_path):966            try:967                get_model(token_val, model_choice, model_path=model_path)968            except Exception as e:969                print(e)970                return {token: gr.update(value=str(e))}971            return {972                token: gr.update(visible=False),973                canvas_width: gr.update(visible=False),974                canvas_height: gr.update(visible=False),975                selection_size: gr.update(visible=False),976                setup_button: gr.update(visible=False),977                frame: gr.update(visible=True),978                upload_button: gr.update(value="Upload Image"),979                model_selection: gr.update(visible=False),980                model_path_input: gr.update(visible=False),981            }982 983        setup_button.click(984            fn=setup_func,985            inputs=[986                token,987                canvas_width,988                canvas_height,989                selection_size,990                model_selection,991                model_path_input,992            ],993            outputs=[994                token,995                canvas_width,996                canvas_height,997                selection_size,998                setup_button,999                frame,1000                upload_button,1001                model_selection,1002                model_path_input,1003            ],1004            _js=setup_button_js,1005        )1006 1007    proceed_event = proceed_button.click(1008        fn=run_outpaint,1009        inputs=[1010            model_input,1011            sd_prompt,1012            sd_negative_prompt,1013            sd_strength,1014            sd_guidance,1015            sd_step,1016            sd_resize,1017            init_mode,1018            safety_check,1019            postprocess_check,1020            sd_img2img,1021            sd_use_seed,1022            sd_seed_val,1023            sd_generate_num,1024            sd_scheduler,1025            sd_scheduler_eta,1026            model_output_state,1027        ],1028        outputs=[model_output, sd_prompt, model_output_state],1029        _js=proceed_button_js,1030    )1031    # cancel button can also remove error overlay1032    # cancel_button.click(fn=None, inputs=None, outputs=None, cancels=[proceed_event])1033 1034 1035launch_extra_kwargs = {1036    "show_error": True,1037    # "favicon_path": ""1038}1039launch_kwargs = vars(args)1040launch_kwargs = {k: v for k, v in launch_kwargs.items() if v is not None}1041launch_kwargs.pop("remote_model", None)1042launch_kwargs.pop("local_model", None)1043launch_kwargs.pop("fp32", None)1044launch_kwargs.update(launch_extra_kwargs)1045try:1046    import google.colab1047 1048    launch_kwargs["debug"] = True1049except:1050    pass1051 1052if RUN_IN_SPACE:1053    demo.launch()1054elif args.debug:1055    launch_kwargs["server_name"] = "0.0.0.0"1056    demo.queue().launch(**launch_kwargs)1057else:1058    demo.queue().launch(**launch_kwargs)1059 1060