CoolFace
Apppublic

multimodalart/ctrl-x

sourceHugging Faceupdated 2y agoView on Hugging Face
8likes
app_ctrlx.py418 linesDownload Raw Back to root
1from argparse import ArgumentParser2 3from diffusers import DDIMScheduler, StableDiffusionXLImg2ImgPipeline4import gradio as gr5import torch6import yaml7 8from ctrl_x.pipelines.pipeline_sdxl import CtrlXStableDiffusionXLPipeline9from ctrl_x.utils import *10from ctrl_x.utils.sdxl import *11 12import spaces13 14 15parser = ArgumentParser()16parser.add_argument("-m", "--model", type=str, default=None)  # Optionally, load model checkpoint from single file17args = parser.parse_args()18 19torch.backends.cudnn.enabled = False  # Sometimes necessary to suppress CUDNN_STATUS_NOT_SUPPORTED20 21torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float3222 23model_id_or_path = "stabilityai/stable-diffusion-xl-base-1.0"24refiner_id_or_path = "stabilityai/stable-diffusion-xl-refiner-1.0"25device = "cuda" if torch.cuda.is_available() else "cpu"26#variant = "fp16" if device == "cuda" else "fp32"27 28scheduler = DDIMScheduler.from_config(model_id_or_path, subfolder="scheduler")  # TODO: Support other schedulers29if args.model is None:30    pipe = CtrlXStableDiffusionXLPipeline.from_pretrained(31        model_id_or_path, scheduler=scheduler, torch_dtype=torch_dtype, use_safetensors=True32    )33else:34    print(f"Using weights {args.model} for SDXL base model.")35    pipe = CtrlXStableDiffusionXLPipeline.from_single_file(args.model, scheduler=scheduler, torch_dtype=torch_dtype)36refiner = StableDiffusionXLImg2ImgPipeline.from_pretrained(37    refiner_id_or_path, scheduler=scheduler, text_encoder_2=pipe.text_encoder_2, vae=pipe.vae,38    torch_dtype=torch_dtype, use_safetensors=True,39)40 41if torch.cuda.is_available():42    pipe = pipe.to("cuda")43    refiner = refiner.to("cuda")44    45 46def get_control_config(structure_schedule, appearance_schedule):47    s = structure_schedule48    a = appearance_schedule49    50    control_config =\51f"""control_schedule:52    #       structure_conv   structure_attn   appearance_attn  conv/attn53    encoder:                                                # (num layers)54        0: [[             ], [             ], [             ]]  # 2/055        1: [[             ], [             ], [{a}, {a}     ]]  # 2/256        2: [[             ], [             ], [{a}, {a}     ]]  # 2/257    middle: [[            ], [             ], [             ]]  # 2/158    decoder:59        0: [[{s}          ], [{s}, {s}, {s}], [0.0, {a}, {a}]]  # 3/360        1: [[             ], [             ], [{a}, {a}     ]]  # 3/361        2: [[             ], [             ], [             ]]  # 3/062 63control_target:64    - [output_tensor]  # structure_conv   choices: {{hidden_states, output_tensor}}65    - [query, key]     # structure_attn   choices: {{query, key, value}}66    - [before]         # appearance_attn  choices: {{before, value, after}}67 68self_recurrence_schedule:69    - [0.1, 0.5, 2]  # format: [start, end, num_recurrence]"""70    71    return control_config72    73 74css = """75.config textarea {font-family: monospace; font-size: 80%; white-space: pre}76.mono {font-family: monospace}77"""78 79title = """80<div style="display: flex; align-items: center; justify-content: center;margin-bottom: -15px">81    <h1 style="margin-left: 12px;text-align: center;display: inline-block">82        Ctrl-X: Controlling Structure and Appearance for Text-To-Image Generation Without Guidance83    </h1>84    <h3 style="display: inline-block; margin-left: 10px; margin-top: 7.5px; font-weight: 500">85        SDXL v1.086    </h3>87</div>88<div style="display: flex; align-items: center; justify-content: center;margin-bottom: 25px">89    <h3 style="text-align: center">90        [<a href="https://genforce.github.io/ctrl-x/">Page</a>]91        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;92        [<a href="https://arxiv.org/abs/2406.07540">Paper</a>]93        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;94        [<a href="https://github.com/genforce/ctrl-x">Code</a>]95    </h3>96</div>97"""98description = """<div>99    <p>100        <b>Ctrl-X</b> is a simple training-free and guidance-free framework for text-to-image (T2I) generation with 101        structure and appearance control. Given structure and appearance images, Ctrl-X designs feedforward structure 102        control to enable structure alignment with the arbitrary structure image and semantic-aware appearance transfer 103        to facilitate the appearance transfer from the appearance image.104    </p>105    <p>106        Here are some notes and tips for this demo:107    </p>108    <ul>109        <li> On input images:110            <ul>111                <li>112                    If both the structure and appearance images are provided, then Ctrl-X does <i>structure and 113                    appearance</i> control.114                </li>115                <li>116                    If only the structure image is provided, then Ctrl-X does <i>structure-only</i> control and the 117                    appearance image is jointly generated with the output image.118                </li>119                <li>120                    Similarly, if only the appearance image is provided, then Ctrl-X does <i>appearance-only</i> 121                    control.122                </li>123            </ul>124        </li>125        <li> On prompts:126            <ul>127                <li>128                    Though the output prompt can affect the output image to a noticeable extent, the "accuracy" of the 129                    structure and appearance prompts are not impactful to the final image.130                </li>131                <li>132                    If the structure or appearance prompt is left blank, then it uses the (non-optional) output prompt 133                    by default.134                </li>135            </ul>136        </li>137        <li> On control schedules:138            <ul>139                <li>140                    When "Use advanced config" is <b>OFF</b>, the demo uses the structure guidance 141                    (<span class="mono">structure_conv</span> and <span class="mono">structure_attn</span> 142                    in the advanced config) and appearance guidance (<span class="mono">appearance_attn</span> in the 143                    advanced config) sliders to change the control schedules.144                </li>145                <li>146                    Otherwise, the demo uses "Advanced control config," which allows per-layer structure and 147                    appearance schedule control, along with self-recurrence control. <i>This should be used 148                    carefully</i>, and we recommend switching "Use advanced config" <b>OFF</b> in most cases. (For the 149                    examples provided at the bottom of the demo, the advanced config uses the default schedules that 150                    may not be the best settings for these examples.)151                </li>152            </ul>153        </li>154    </ul>155    <p>156        Have fun! :D157    </p>158</div>159"""160 161@spaces.GPU162def inference(163    structure_image,164    appearance_image,165    prompt,166    structure_prompt,167    appearance_prompt,168    positive_prompt="high quality",169    negative_prompt="ugly, blurry, dark, low res, unrealistic",170    guidance_scale=5.0,171    structure_guidance_scale=5.0,172    appearance_guidance_scale=5.0,173    num_inference_steps=28,174    eta=1.0,175    seed=42,176    width=1024,177    height=1024,178    structure_schedule=0.6,179    appearance_schedule=0.6,180    use_advanced_config=False,181    control_config="",182    progress=gr.Progress(track_tqdm=True)183):184    torch.manual_seed(seed)185    186    pipe.scheduler.set_timesteps(num_inference_steps, device=device)187    timesteps = pipe.scheduler.timesteps188    189    print(f"\nUsing the following control config (use_advanced_config={use_advanced_config}):")190    if not use_advanced_config:191        control_config = get_control_config(structure_schedule, appearance_schedule)192    print(control_config, end="\n\n")193    194    config = yaml.safe_load(control_config)195    register_control(196        model = pipe,197        timesteps = timesteps,198        control_schedule = config["control_schedule"],199        control_target = config["control_target"],200    )201    202    pipe.safety_checker = None203    pipe.requires_safety_checker = False204    205    self_recurrence_schedule = get_self_recurrence_schedule(config["self_recurrence_schedule"], num_inference_steps)206 207    pipe.set_progress_bar_config(desc="Ctrl-X inference")208    refiner.set_progress_bar_config(desc="Refiner")209    210    result, structure, appearance = pipe(211        prompt = prompt,212        structure_prompt = structure_prompt,213        appearance_prompt = appearance_prompt,214        structure_image = structure_image,215        appearance_image = appearance_image,216        num_inference_steps = num_inference_steps,217        negative_prompt = negative_prompt,218        positive_prompt = positive_prompt,219        height = height,220        width = width,221        guidance_scale = guidance_scale,222        structure_guidance_scale = structure_guidance_scale,223        appearance_guidance_scale = appearance_guidance_scale,224        eta = eta,225        output_type = "pil",226        return_dict = False,227        control_schedule = config["control_schedule"],228        self_recurrence_schedule = self_recurrence_schedule,229    )230    231    result_refiner = refiner(232        image = pipe.refiner_args["latents"],233        prompt = pipe.refiner_args["prompt"],234        negative_prompt = pipe.refiner_args["negative_prompt"],235        height = height,236        width = width,237        num_inference_steps = num_inference_steps,238        guidance_scale = guidance_scale,239        guidance_rescale = 0.7,240        num_images_per_prompt = 1,241        eta = eta,242        output_type = "pil",243    ).images244    del pipe.refiner_args245    246    return [result[0], result_refiner[0], structure[0], appearance[0]]247    248    249with gr.Blocks(theme=gr.themes.Default(), css=css, title="Ctrl-X (SDXL v1.0)") as app:250    gr.HTML(title)251    with gr.Accordion("Instructions", open=False):252        gr.HTML(description)253    with gr.Row():254        with gr.Column(scale=45):255            with gr.Group():256                kwargs = {}  # {"width": 400, "height": 400}257                with gr.Row():258                    structure_image = gr.Image(label="Upload structure image (optional)", type="pil", **kwargs)259                    appearance_image = gr.Image(label="Upload appearance image (optional)", type="pil", **kwargs)260                with gr.Row():261                    structure_prompt = gr.Textbox(label="Structure prompt (optional)", placeholder="Describes the structure image")262                    appearance_prompt = gr.Textbox(label="Appearance prompt (optional)", placeholder="Describes the style image")263                with gr.Row():264                    prompt = gr.Textbox(label="Output prompt", placeholder="Prompt which describes the output image")265                with gr.Row():266                    positive_prompt = gr.Textbox(label="Positive prompt", value="high quality", placeholder="")267                    negative_prompt = gr.Textbox(label="Negative prompt", value="ugly, blurry, dark, low res, unrealistic", placeholder="")268                with gr.Accordion("Advanced Options", open=False):269                    with gr.Row():270                        guidance_scale = gr.Slider(label="Target guidance scale", value=5.0, minimum=1, maximum=10)271                        structure_guidance_scale = gr.Slider(label="Structure guidance scale", value=5.0, minimum=1, maximum=10)272                        appearance_guidance_scale = gr.Slider(label="Appearance guidance scale", value=5.0, minimum=1, maximum=10)273                    with gr.Row():274                        num_inference_steps = gr.Slider(label="# inference steps", value=28, minimum=1, maximum=200, step=1)275                        eta = gr.Slider(label="Eta (noise)", value=1.0, minimum=0, maximum=1.0, step=0.01)276                        seed = gr.Slider(0, 2147483647, label="Seed", value=90095, step=1)277                    with gr.Row():278                        width = gr.Slider(label="Width", value=1024, minimum=256, maximum=2048, step=pipe.vae_scale_factor)279                        height = gr.Slider(label="Height", value=1024, minimum=256, maximum=2048, step=pipe.vae_scale_factor)280                    with gr.Row():281                        structure_schedule = gr.Slider(label="Structure schedule", value=0.6, minimum=0.0, maximum=1.0, step=0.01, scale=2)282                        appearance_schedule = gr.Slider(label="Appearance schedule", value=0.6, minimum=0.0, maximum=1.0, step=0.01, scale=2)283                        use_advanced_config = gr.Checkbox(label="Use advanced config", value=False, scale=1)284                    with gr.Row():285                        control_config = gr.Textbox(286                            label="Advanced control config", lines=20, value=get_control_config(0.6, 0.6), elem_classes=["config"], visible=False,287                        )288                        use_advanced_config.change(289                            fn=lambda value: gr.update(visible=value), inputs=use_advanced_config, outputs=control_config,290                        )291                with gr.Row():292                    generate = gr.Button(value="Run")293        294        with gr.Column(scale=55):295            with gr.Group():296                with gr.Row():297                    result_refiner = gr.Image(label="Output image w/ refiner", format="jpg", **kwargs)298                with gr.Row():299                    result = gr.Image(label="Output image", format="jpg", **kwargs)300                    structure_recon = gr.Image(label="Structure image", format="jpg", **kwargs)301                    appearance_recon = gr.Image(label="Style image", format="jpg", **kwargs)302                        303    inputs = [304        structure_image, appearance_image,305        prompt, structure_prompt, appearance_prompt,306        positive_prompt, negative_prompt,307        guidance_scale, structure_guidance_scale, appearance_guidance_scale,308        num_inference_steps, eta, seed,309        width, height,310        structure_schedule, appearance_schedule, use_advanced_config,311        control_config,312    ]313    outputs = [result, result_refiner, structure_recon, appearance_recon]314    315    generate.click(inference, inputs=inputs, outputs=outputs)316 317    examples = gr.Examples(318        [319            [320                "assets/images/horse__point_cloud.jpg",321                "assets/images/horse.jpg",322                "a photo of a horse standing on grass",323                "a 3D point cloud of a horse",324                "",325            ],326            [327                "assets/images/cat__mesh.jpg",328                "assets/images/tiger.jpg",329                "a photo of a tiger standing on snow",330                "a 3D mesh of a cat",331                "",332            ],333            [334                "assets/images/dog__sketch.jpg",335                "assets/images/squirrel.jpg",336                "a photo of a squirrel",337                "a sketch of a dog",338                "",339            ],340            [341                "assets/images/living_room__seg.jpg",342                "assets/images/van_gogh.jpg",343                "a Van Gogh painting of a living room",344                "a segmentation map of a living room",345                "",346            ],347            [348                "assets/images/bedroom__sketch.jpg",349                "assets/images/living_room_modern.jpg",350                "a sketch of a bedroom",351                "a photo of a modern bedroom during sunset",352                "",353            ],354            [355                "assets/images/running__pose.jpg",356                "assets/images/man_park.jpg",357                "a photo of a man running in a park",358                "a pose image of a person running",359                "",360            ],361            [362                "assets/images/fruit_bowl.jpg",363                "assets/images/grapes.jpg",364                "a photo of a bowl of grapes in the trees",365                "a photo of a bowl of fruits",366                "",367            ],368            [369                "assets/images/bear_avocado__spatext.jpg",370                None,371                "a realistic photo of a bear and an avocado in a forest",372                "a segmentation map of a bear and an avocado",373                "",374            ],375            [376                "assets/images/cat__point_cloud.jpg",377                None,378                "an embroidery of a white cat sitting on a rock under the night sky",379                "a 3D point cloud of a cat",380                "",381            ],382            [383                "assets/images/library__mesh.jpg",384                None,385                "a Polaroid photo of an old library, sunlight streaming in",386                "a 3D mesh of a library",387                "",388            ],389            [390                "assets/images/knight__humanoid.jpg",391                None,392                "a photo of a medieval soldier standing on a barren field, raining",393                "a 3D model of a person holding a sword and shield",394                "",395            ],396            [397                "assets/images/person__mesh.jpg",398                None,399                "a photo of a Karate man performing in a cyberpunk city at night",400                "a 3D mesh of a person",401                "",402            ],403        ],404        [405            structure_image,406            appearance_image,407            prompt,408            structure_prompt,409            appearance_prompt,410        ],411        examples_per_page=50,412        cache_examples="lazy",413        fn=inference,414        outputs=[result, result_refiner, structure_recon, appearance_recon]415    )416 417app.launch(debug=False, share=False)418