niggathug commited on
Commit
64766ab
1 Parent(s): 4568cf6

Upload 2 files

Browse files
Files changed (2) hide show
  1. .gitignore +1 -0
  2. app.py +251 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ gradiodemo/
app.py ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+
4
+ import gradio as gr
5
+ import numpy as np
6
+ import PIL.Image
7
+ import torch
8
+ import torchvision.transforms.functional as TF
9
+ from diffusers import (
10
+ AutoencoderKL,
11
+ EulerAncestralDiscreteScheduler,
12
+ StableDiffusionXLAdapterPipeline,
13
+ T2IAdapter,
14
+ )
15
+
16
+
17
+ style_list = [
18
+ {
19
+ "name": "(No style)",
20
+ "prompt": "{prompt}",
21
+ "negative_prompt": "",
22
+ },
23
+ {
24
+ "name": "Cinematic",
25
+ "prompt": "cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy",
26
+ "negative_prompt": "anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured",
27
+ },
28
+ {
29
+ "name": "3D Model",
30
+ "prompt": "professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting",
31
+ "negative_prompt": "ugly, deformed, noisy, low poly, blurry, painting",
32
+ },
33
+ {
34
+ "name": "Anime",
35
+ "prompt": "anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed",
36
+ "negative_prompt": "photo, deformed, black and white, realism, disfigured, low contrast",
37
+ },
38
+ {
39
+ "name": "Digital Art",
40
+ "prompt": "concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed",
41
+ "negative_prompt": "photo, photorealistic, realism, ugly",
42
+ },
43
+ {
44
+ "name": "Photographic",
45
+ "prompt": "cinematic photo {prompt} . 35mm photograph, film, bokeh, professional, 4k, highly detailed",
46
+ "negative_prompt": "drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly",
47
+ },
48
+ {
49
+ "name": "Pixel art",
50
+ "prompt": "pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics",
51
+ "negative_prompt": "sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic",
52
+ },
53
+ {
54
+ "name": "Fantasy art",
55
+ "prompt": "ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy",
56
+ "negative_prompt": "photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white",
57
+ },
58
+ {
59
+ "name": "Neonpunk",
60
+ "prompt": "neonpunk style {prompt} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional",
61
+ "negative_prompt": "painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured",
62
+ },
63
+ {
64
+ "name": "Manga",
65
+ "prompt": "manga style {prompt} . vibrant, high-energy, detailed, iconic, Japanese comic style",
66
+ "negative_prompt": "ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style",
67
+ },
68
+ ]
69
+
70
+ styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
71
+ STYLE_NAMES = list(styles.keys())
72
+ DEFAULT_STYLE_NAME = "(No style)"
73
+
74
+
75
+ def apply_style(style_name: str, positive: str, negative: str = "") -> tuple[str, str]:
76
+ p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
77
+ return p.replace("{prompt}", positive), n + negative
78
+
79
+
80
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
81
+ if torch.cuda.is_available():
82
+ model_id = "stabilityai/stable-diffusion-xl-base-1.0"
83
+ adapter = T2IAdapter.from_pretrained(
84
+ "TencentARC/t2i-adapter-sketch-sdxl-1.0", torch_dtype=torch.float16, variant="fp16"
85
+ )
86
+ scheduler = EulerAncestralDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
87
+ pipe = StableDiffusionXLAdapterPipeline.from_pretrained(
88
+ model_id,
89
+ vae=AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16),
90
+ adapter=adapter,
91
+ scheduler=scheduler,
92
+ torch_dtype=torch.float16,
93
+ variant="fp16",
94
+ )
95
+ pipe.to(device)
96
+ else:
97
+ pipe = None
98
+
99
+ MAX_SEED = np.iinfo(np.int32).max
100
+
101
+
102
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
103
+ if randomize_seed:
104
+ seed = random.randint(0, MAX_SEED)
105
+ return seed
106
+
107
+
108
+ def run(
109
+ image: PIL.Image.Image,
110
+ prompt: str,
111
+ negative_prompt: str,
112
+ style_name: str = DEFAULT_STYLE_NAME,
113
+ num_steps: int = 25,
114
+ guidance_scale: float = 5,
115
+ adapter_conditioning_scale: float = 0.8,
116
+ adapter_conditioning_factor: float = 0.8,
117
+ seed: int = 0,
118
+ progress=gr.Progress(track_tqdm=True),
119
+ ) -> PIL.Image.Image:
120
+ image = image.convert("RGB")
121
+ image = TF.to_tensor(image) > 0.5
122
+ image = TF.to_pil_image(image.to(torch.float32))
123
+
124
+ prompt, negative_prompt = apply_style(style_name, prompt, negative_prompt)
125
+
126
+ generator = torch.Generator(device=device).manual_seed(seed)
127
+ out = pipe(
128
+ prompt=prompt,
129
+ negative_prompt=negative_prompt,
130
+ image=image,
131
+ num_inference_steps=num_steps,
132
+ generator=generator,
133
+ guidance_scale=guidance_scale,
134
+ adapter_conditioning_scale=adapter_conditioning_scale,
135
+ adapter_conditioning_factor=adapter_conditioning_factor,
136
+ ).images[0]
137
+ return out
138
+
139
+
140
+ with gr.Blocks() as demo:
141
+ with gr.Row():
142
+ with gr.Column():
143
+ with gr.Group():
144
+ image = gr.Image(
145
+ source="canvas",
146
+ tool="sketch",
147
+ type="pil",
148
+ image_mode="L",
149
+ invert_colors=True,
150
+ shape=(1024, 1024),
151
+ brush_radius=4,
152
+ height=440,
153
+ )
154
+ prompt = gr.Textbox(label="Prompt")
155
+ style = gr.Dropdown(label="Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME)
156
+ run_button = gr.Button("Run")
157
+ with gr.Accordion("Advanced options", open=False):
158
+ negative_prompt = gr.Textbox(
159
+ label="Negative prompt",
160
+ value=" extra digit, fewer digits, cropped, worst quality, low quality, glitch, deformed, mutated, ugly, disfigured",
161
+ )
162
+ num_steps = gr.Slider(
163
+ label="Number of steps",
164
+ minimum=1,
165
+ maximum=50,
166
+ step=1,
167
+ value=25,
168
+ )
169
+ guidance_scale = gr.Slider(
170
+ label="Guidance scale",
171
+ minimum=0.1,
172
+ maximum=10.0,
173
+ step=0.1,
174
+ value=5,
175
+ )
176
+ adapter_conditioning_scale = gr.Slider(
177
+ label="Adapter conditioning scale",
178
+ minimum=0.5,
179
+ maximum=1,
180
+ step=0.1,
181
+ value=0.8,
182
+ )
183
+ adapter_conditioning_factor = gr.Slider(
184
+ label="Adapter conditioning factor",
185
+ info="Fraction of timesteps for which adapter should be applied",
186
+ minimum=0.5,
187
+ maximum=1,
188
+ step=0.1,
189
+ value=0.8,
190
+ )
191
+ seed = gr.Slider(
192
+ label="Seed",
193
+ minimum=0,
194
+ maximum=MAX_SEED,
195
+ step=1,
196
+ value=0,
197
+ )
198
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
199
+ with gr.Column():
200
+ result = gr.Image(label="Result", height=400)
201
+
202
+ inputs = [
203
+ image,
204
+ prompt,
205
+ negative_prompt,
206
+ style,
207
+ num_steps,
208
+ guidance_scale,
209
+ adapter_conditioning_scale,
210
+ adapter_conditioning_factor,
211
+ seed,
212
+ ]
213
+ prompt.submit(
214
+ fn=randomize_seed_fn,
215
+ inputs=[seed, randomize_seed],
216
+ outputs=seed,
217
+ queue=False,
218
+ api_name=False,
219
+ ).then(
220
+ fn=run,
221
+ inputs=inputs,
222
+ outputs=result,
223
+ api_name=False,
224
+ )
225
+ negative_prompt.submit(
226
+ fn=randomize_seed_fn,
227
+ inputs=[seed, randomize_seed],
228
+ outputs=seed,
229
+ queue=False,
230
+ api_name=False,
231
+ ).then(
232
+ fn=run,
233
+ inputs=inputs,
234
+ outputs=result,
235
+ api_name=False,
236
+ )
237
+ run_button.click(
238
+ fn=randomize_seed_fn,
239
+ inputs=[seed, randomize_seed],
240
+ outputs=seed,
241
+ queue=False,
242
+ api_name=False,
243
+ ).then(
244
+ fn=run,
245
+ inputs=inputs,
246
+ outputs=result,
247
+ api_name=False,
248
+ )
249
+
250
+
251
+ demo.queue(max_size=20).launch()