ClumsyShadoww commited on
Commit
96cb557
·
verified ·
1 Parent(s): a327dd1
Files changed (1) hide show
  1. app.py +116 -0
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Waifu-Inpaint-XL Gradio App
3
+ ----------------------------
4
+ Free-GPU-friendly inpainting UI for ShinoharaHare/Waifu-Inpaint-XL.
5
+ Works as-is on: HF Spaces (ZeroGPU), Kaggle Notebooks, Google Colab.
6
+
7
+ Setup:
8
+ pip install -r requirements.txt
9
+ huggingface-cli login # needed once, model is gated
10
+
11
+ Run:
12
+ python app.py
13
+ """
14
+
15
+ import os
16
+ import torch
17
+ import gradio as gr
18
+ from diffusers import StableDiffusionXLInpaintPipeline
19
+ from PIL import Image
20
+
21
+ MODEL_ID = "ShinoharaHare/Waifu-Inpaint-XL"
22
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
23
+ DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
24
+
25
+ pipe = None # lazy-loaded so the UI opens instantly, model loads on first click
26
+
27
+
28
+ def load_pipeline():
29
+ global pipe
30
+ if pipe is None:
31
+ pipe = StableDiffusionXLInpaintPipeline.from_pretrained(
32
+ MODEL_ID,
33
+ torch_dtype=DTYPE,
34
+ use_safetensors=True,
35
+ )
36
+ pipe.to(DEVICE)
37
+ if DEVICE == "cuda":
38
+ pipe.enable_vae_slicing()
39
+ pipe.enable_attention_slicing()
40
+ return pipe
41
+
42
+
43
+ def run_inpaint(
44
+ editor_value, # gr.ImageEditor output: {"background":..., "layers":[...], "composite":...}
45
+ prompt,
46
+ negative_prompt,
47
+ steps,
48
+ guidance,
49
+ num_variations,
50
+ seed,
51
+ ):
52
+ if editor_value is None or editor_value.get("background") is None:
53
+ raise gr.Error("Upload an image first.")
54
+
55
+ base_image = editor_value["background"].convert("RGB")
56
+
57
+ # Build mask from the drawn layer (painted area = white = inpaint region)
58
+ if not editor_value.get("layers"):
59
+ raise gr.Error("Paint over the area you want to inpaint (use the brush tool).")
60
+ mask_layer = editor_value["layers"][0]
61
+ mask = mask_layer.split()[-1].convert("L") # alpha channel -> grayscale mask
62
+
63
+ p = load_pipeline()
64
+
65
+ results = []
66
+ base_seed = int(seed) if seed >= 0 else torch.seed()
67
+ for i in range(int(num_variations)):
68
+ gen = torch.Generator(device=DEVICE).manual_seed(base_seed + i)
69
+ out = p(
70
+ prompt=prompt,
71
+ negative_prompt=negative_prompt or None,
72
+ image=base_image,
73
+ mask_image=mask,
74
+ num_inference_steps=int(steps),
75
+ guidance_scale=float(guidance),
76
+ height=base_image.height,
77
+ width=base_image.width,
78
+ generator=gen,
79
+ ).images[0]
80
+ results.append(out)
81
+
82
+ return results
83
+
84
+
85
+ with gr.Blocks(title="Waifu-Inpaint-XL") as demo:
86
+ gr.Markdown("## Waifu-Inpaint-XL — paint a mask, describe the change, generate")
87
+
88
+ with gr.Row():
89
+ with gr.Column():
90
+ editor = gr.ImageEditor(
91
+ label="Upload image, then paint the mask (brush tool)",
92
+ type="pil",
93
+ brush=gr.Brush(colors=["#ffffff"], default_size=25),
94
+ )
95
+ prompt = gr.Textbox(label="Prompt", placeholder="orange striped sweater, red sparkle eyes")
96
+ negative_prompt = gr.Textbox(label="Negative prompt (optional)", value="blurry, low quality, extra limbs")
97
+ with gr.Row():
98
+ steps = gr.Slider(10, 50, value=28, step=1, label="Steps")
99
+ guidance = gr.Slider(1, 12, value=5.0, step=0.5, label="Guidance scale")
100
+ with gr.Row():
101
+ num_variations = gr.Slider(1, 6, value=1, step=1, label="Variations to generate")
102
+ seed = gr.Number(value=-1, label="Seed (-1 = random)")
103
+ run_btn = gr.Button("Generate", variant="primary")
104
+
105
+ with gr.Column():
106
+ gallery = gr.Gallery(label="Results", columns=3, height=500)
107
+
108
+ run_btn.click(
109
+ fn=run_inpaint,
110
+ inputs=[editor, prompt, negative_prompt, steps, guidance, num_variations, seed],
111
+ outputs=gallery,
112
+ )
113
+
114
+ if __name__ == "__main__":
115
+ # share=True gives you a public URL for free when running on Colab/Kaggle
116
+ demo.launch(share=os.environ.get("GRADIO_SHARE", "true").lower() == "true")