OzzyGT's picture
OzzyGT HF Staff
fix
1fcbe69
raw
history blame
5.77 kB
import gradio as gr
import spaces
import torch
from diffusers import AutoencoderKL, ControlNetUnionModel, DiffusionPipeline, TCDScheduler
def callback_cfg_cutoff(pipeline, step_index, timestep, callback_kwargs):
if step_index == int(pipeline.num_timesteps * 0.2):
prompt_embeds = callback_kwargs["prompt_embeds"]
prompt_embeds = prompt_embeds[-1:]
add_text_embeds = callback_kwargs["add_text_embeds"]
add_text_embeds = add_text_embeds[-1:]
add_time_ids = callback_kwargs["add_time_ids"]
add_time_ids = add_time_ids[-1:]
control_image = callback_kwargs["control_image"]
control_image[0] = control_image[0][-1:]
control_type = callback_kwargs["control_type"]
control_type = control_type[-1:]
pipeline._guidance_scale = 0.0
callback_kwargs["prompt_embeds"] = prompt_embeds
callback_kwargs["add_text_embeds"] = add_text_embeds
callback_kwargs["add_time_ids"] = add_time_ids
callback_kwargs["control_image"] = control_image
callback_kwargs["control_type"] = control_type
return callback_kwargs
MODELS = {
"RealVisXL V5.0 Lightning": "SG161222/RealVisXL_V5.0_Lightning",
}
controlnet_model = ControlNetUnionModel.from_pretrained(
"OzzyGT/controlnet-union-promax-sdxl-1.0", variant="fp16", torch_dtype=torch.float16
)
controlnet_model.to(device="cuda", dtype=torch.float16)
vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16).to("cuda")
pipe = DiffusionPipeline.from_pretrained(
"SG161222/RealVisXL_V5.0_Lightning",
torch_dtype=torch.float16,
vae=vae,
controlnet=controlnet_model,
custom_pipeline="OzzyGT/custom_sdxl_cnet_union",
).to("cuda")
pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
@spaces.GPU(duration=24)
def fill_image(prompt, negative_prompt, image, model_selection, paste_back):
(
prompt_embeds,
negative_prompt_embeds,
pooled_prompt_embeds,
negative_pooled_prompt_embeds,
) = pipe.encode_prompt(prompt, device="cuda", negative_prompt=negative_prompt)
source = image["background"]
mask = image["layers"][0]
alpha_channel = mask.split()[3]
binary_mask = alpha_channel.point(lambda p: p > 0 and 255)
cnet_image = source.copy()
cnet_image.paste(0, (0, 0), binary_mask)
image = pipe(
prompt_embeds=prompt_embeds,
negative_prompt_embeds=negative_prompt_embeds,
pooled_prompt_embeds=pooled_prompt_embeds,
negative_pooled_prompt_embeds=negative_pooled_prompt_embeds,
control_image=[cnet_image],
controlnet_conditioning_scale=[1.0],
control_mode=[7],
num_inference_steps=8,
guidance_scale=1.5,
callback_on_step_end=callback_cfg_cutoff,
callback_on_step_end_tensor_inputs=[
"prompt_embeds",
"add_text_embeds",
"add_time_ids",
"control_image",
"control_type",
],
).images[0]
if paste_back:
image = image.convert("RGBA")
cnet_image.paste(image, (0, 0), binary_mask)
else:
cnet_image = image
yield source, cnet_image
def clear_result():
return gr.update(value=None)
title = """<h2 align="center">Diffusers Fast Inpaint</h2>
<div align="center">Draw the mask over the subject you want to erase or change and write what you want to inpaint it with.</div>
"""
with gr.Blocks() as demo:
gr.HTML(title)
with gr.Row():
with gr.Column():
prompt = gr.Textbox(
label="Prompt",
lines=1,
)
with gr.Column():
with gr.Row():
negative_prompt = gr.Textbox(
label="Negative Prompt",
lines=1,
)
with gr.Row():
with gr.Column():
run_button = gr.Button("Generate")
with gr.Column():
paste_back = gr.Checkbox(True, label="Paste back original")
with gr.Row():
input_image = gr.ImageMask(
type="pil",
label="Input Image",
crop_size=(1024, 1024),
canvas_size=(1024, 1024),
layers=False,
height=512,
)
result = gr.ImageSlider(
interactive=False,
label="Generated Image",
)
use_as_input_button = gr.Button("Use as Input Image", visible=False)
model_selection = gr.Dropdown(choices=list(MODELS.keys()), value="RealVisXL V5.0 Lightning", label="Model")
def use_output_as_input(output_image):
return gr.update(value=output_image[1])
use_as_input_button.click(fn=use_output_as_input, inputs=[result], outputs=[input_image])
run_button.click(
fn=clear_result,
inputs=None,
outputs=result,
).then(
fn=lambda: gr.update(visible=False),
inputs=None,
outputs=use_as_input_button,
).then(
fn=fill_image,
inputs=[prompt, negative_prompt, input_image, model_selection, paste_back],
outputs=result,
).then(
fn=lambda: gr.update(visible=True),
inputs=None,
outputs=use_as_input_button,
)
prompt.submit(
fn=clear_result,
inputs=None,
outputs=result,
).then(
fn=lambda: gr.update(visible=False),
inputs=None,
outputs=use_as_input_button,
).then(
fn=fill_image,
inputs=[prompt, negative_prompt, input_image, model_selection, paste_back],
outputs=result,
).then(
fn=lambda: gr.update(visible=True),
inputs=None,
outputs=use_as_input_button,
)
demo.queue(max_size=12).launch(share=False)