aexyb commited on
Commit
a19633b
·
verified ·
1 Parent(s): 99c8f86

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +542 -0
app.py ADDED
@@ -0,0 +1,542 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ import uuid
4
+ import json
5
+ import gradio as gr
6
+ import numpy as np
7
+ from PIL import Image
8
+ import spaces
9
+ import torch
10
+ from diffusers import DiffusionPipeline, StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
11
+ from typing import Tuple
12
+
13
+ #BaseConditions--
14
+ bad_words = json.loads(os.getenv('BAD_WORDS', "[]"))
15
+ bad_words_negative = json.loads(os.getenv('BAD_WORDS_NEGATIVE', "[]"))
16
+ default_negative = os.getenv("default_negative","")
17
+
18
+ def check_text(prompt, negative=""):
19
+ for i in bad_words:
20
+ if i in prompt:
21
+ return True
22
+ for i in bad_words_negative:
23
+ if i in negative:
24
+ return True
25
+ return False
26
+
27
+ #Quality/Style-----------------------------------------------------------------------------------------------------------------------------------------------------------Quality/Style
28
+
29
+ style_list = [
30
+ {
31
+ "name": "3840 x 2160",
32
+ "prompt": "hyper-realistic 8K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
33
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
34
+ },
35
+ {
36
+ "name": "2560 x 1440",
37
+ "prompt": "hyper-realistic 4K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
38
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
39
+ },
40
+
41
+ {
42
+ "name": "HD+",
43
+ "prompt": "hyper-realistic 2K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
44
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
45
+ },
46
+
47
+ {
48
+ "name": "Style Zero",
49
+ "prompt": "{prompt}",
50
+ "negative_prompt": "",
51
+ },
52
+
53
+ ]
54
+
55
+ #Clgstyle--------------------------------------------------------------------------------------------------------------------------------------------------------------Clgstyle
56
+
57
+ collage_style_list = [
58
+ {
59
+ "name": "Hi-Res",
60
+ "prompt": "hyper-realistic 8K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
61
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
62
+ },
63
+ {
64
+ "name": "B & W",
65
+ "prompt": "black and white collage of {prompt}. monochromatic, timeless, classic, dramatic contrast",
66
+ "negative_prompt": "colorful, vibrant, bright, flashy",
67
+ },
68
+ {
69
+ "name": "Polaroid",
70
+ "prompt": "collage of polaroid photos featuring {prompt}. vintage style, high contrast, nostalgic, instant film aesthetic",
71
+ "negative_prompt": "digital, modern, low quality, blurry",
72
+ },
73
+ {
74
+ "name": "Watercolor",
75
+ "prompt": "watercolor collage of {prompt}. soft edges, translucent colors, painterly effects",
76
+ "negative_prompt": "digital, sharp lines, solid colors",
77
+ },
78
+ {
79
+ "name": "Cinematic",
80
+ "prompt": "cinematic collage of {prompt}. film stills, movie posters, dramatic lighting",
81
+ "negative_prompt": "static, lifeless, mundane",
82
+ },
83
+ {
84
+ "name": "Nostalgic",
85
+ "prompt": "nostalgic collage of {prompt}. retro imagery, vintage objects, sentimental journey",
86
+ "negative_prompt": "contemporary, futuristic, forward-looking",
87
+ },
88
+ {
89
+ "name": "Vintage",
90
+ "prompt": "vintage collage of {prompt}. aged paper, sepia tones, retro imagery, antique vibes",
91
+ "negative_prompt": "modern, contemporary, futuristic, high-tech",
92
+ },
93
+ {
94
+ "name": "Scrapbook",
95
+ "prompt": "scrapbook style collage of {prompt}. mixed media, hand-cut elements, textures, paper, stickers, doodles",
96
+ "negative_prompt": "clean, digital, modern, low quality",
97
+ },
98
+ {
99
+ "name": "NeoNGlow",
100
+ "prompt": "neon glow collage of {prompt}. vibrant colors, glowing effects, futuristic vibes",
101
+ "negative_prompt": "dull, muted colors, vintage, retro",
102
+ },
103
+ {
104
+ "name": "Geometric",
105
+ "prompt": "geometric collage of {prompt}. abstract shapes, colorful, sharp edges, modern design, high quality",
106
+ "negative_prompt": "blurry, low quality, traditional, dull",
107
+ },
108
+ {
109
+ "name": "Thematic",
110
+ "prompt": "thematic collage of {prompt}. cohesive theme, well-organized, matching colors, creative layout",
111
+ "negative_prompt": "random, messy, unorganized, clashing colors",
112
+ },
113
+
114
+ #DuoTones by Canva --------------------------------------------------------------------------------------------------------------- Alters only the i++ Part / not Zero Tones
115
+
116
+ {
117
+ "name": "Cherry",
118
+ "prompt": "Duotone style Cherry tone applied to {prompt}",
119
+ "negative_prompt": "",
120
+ },
121
+ {
122
+ "name": "Fuchsia",
123
+ "prompt": "Duotone style Fuchsia tone applied to {prompt}",
124
+ "negative_prompt": "",
125
+ },
126
+ {
127
+ "name": "Pop",
128
+ "prompt": "Duotone style Pop tone applied to {prompt}",
129
+ "negative_prompt": "",
130
+ },
131
+ {
132
+ "name": "Violet",
133
+ "prompt": "Duotone style Violet applied to {prompt}",
134
+ "negative_prompt": "",
135
+ },
136
+ {
137
+ "name": "Sea Blue",
138
+ "prompt": "Duotone style Sea Blue applied to {prompt}",
139
+ "negative_prompt": "",
140
+ },
141
+ {
142
+ "name": "Sea Green",
143
+ "prompt": "Duotone style Sea Green applied to {prompt}",
144
+ "negative_prompt": "",
145
+ },
146
+ {
147
+ "name": "Mustard",
148
+ "prompt": "Duotone style Mustard applied to {prompt}",
149
+ "negative_prompt": "",
150
+ },
151
+ {
152
+ "name": "Amber",
153
+ "prompt": "Duotone style Amber applied to {prompt}",
154
+ "negative_prompt": "",
155
+ },
156
+ {
157
+ "name": "Pomelo",
158
+ "prompt": "Duotone style Pomelo applied to {prompt}",
159
+ "negative_prompt": "",
160
+ },
161
+ {
162
+ "name": "Peppermint",
163
+ "prompt": "Duotone style Peppermint applied to {prompt}",
164
+ "negative_prompt": "",
165
+ },
166
+ {
167
+ "name": "Mystic",
168
+ "prompt": "Duotone style Mystic tone applied to {prompt}",
169
+ "negative_prompt": "",
170
+ },
171
+ {
172
+ "name": "Pastel",
173
+ "prompt": "Duotone style Pastel applied to {prompt}",
174
+ "negative_prompt": "",
175
+ },
176
+ {
177
+ "name": "Coral",
178
+ "prompt": "Duotone style Coral applied to {prompt}",
179
+ "negative_prompt": "",
180
+ },
181
+ {
182
+ "name": "No Style",
183
+ "prompt": "{prompt}",
184
+ "negative_prompt": "",
185
+ },
186
+
187
+ ]
188
+
189
+ #filters------------------------------------------------------------------------------------------------------------------------------------------------filters
190
+
191
+ filters = {
192
+ "Vivid": {
193
+ "prompt": "extra vivid {prompt}",
194
+ "negative_prompt": "washed out, dull"
195
+ },
196
+ "Playa": {
197
+ "prompt": "{prompt} set in a vast playa",
198
+ "negative_prompt": "forest, mountains"
199
+ },
200
+ "Desert": {
201
+ "prompt": "{prompt} set in a desert landscape",
202
+ "negative_prompt": "ocean, city"
203
+ },
204
+ "West": {
205
+ "prompt": "{prompt} with a western theme",
206
+ "negative_prompt": "eastern, modern"
207
+ },
208
+ "Blush": {
209
+ "prompt": "{prompt} with a soft blush color palette",
210
+ "negative_prompt": "harsh colors, neon"
211
+ },
212
+ "Minimalist": {
213
+ "prompt": "{prompt} with a minimalist design",
214
+ "negative_prompt": "cluttered, ornate"
215
+ },
216
+
217
+ "Zero filter": {
218
+ "prompt": "{prompt}",
219
+ "negative_prompt": ""
220
+ },
221
+
222
+
223
+ }
224
+
225
+ styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
226
+ collage_styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in collage_style_list}
227
+ filter_styles = {k: (v["prompt"], v["negative_prompt"]) for k, v in filters.items()}
228
+
229
+ STYLE_NAMES = list(styles.keys())
230
+ COLLAGE_STYLE_NAMES = list(collage_styles.keys())
231
+ FILTER_NAMES = list(filters.keys())
232
+ DEFAULT_STYLE_NAME = "3840 x 2160"
233
+ DEFAULT_COLLAGE_STYLE_NAME = "Hi-Res"
234
+ DEFAULT_FILTER_NAME = "Zero filter"
235
+
236
+ def apply_style(style_name: str, positive: str, negative: str = "") -> Tuple[str, str]:
237
+ if style_name in styles:
238
+ p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
239
+ elif style_name in collage_styles:
240
+ p, n = collage_styles.get(style_name, collage_styles[DEFAULT_COLLAGE_STYLE_NAME])
241
+ elif style_name in filter_styles:
242
+ p, n = filter_styles.get(style_name, filter_styles[DEFAULT_FILTER_NAME])
243
+ else:
244
+ p, n = styles[DEFAULT_STYLE_NAME]
245
+
246
+ if not negative:
247
+ negative = ""
248
+ return p.replace("{prompt}", positive), n + negative
249
+
250
+
251
+
252
+ DESCRIPTION = """## Diffusion 🏞️
253
+ """
254
+
255
+ MAX_SEED = np.iinfo(np.int32).max
256
+ CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES", "0") == "1"
257
+ MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "2048"))
258
+ USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE", "0") == "1"
259
+ ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD", "0") == "1"
260
+
261
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
262
+ #Compile
263
+ if torch.cuda.is_available():
264
+ pipe = StableDiffusionXLPipeline.from_pretrained(
265
+ "SG161222/RealVisXL_V4.0_Lightning", #(or) use --- SG161222/RealVisXL_V4.0 / SG161222/RealVisXL_V4.0_Lightning --- for better results.
266
+ torch_dtype=torch.float16,
267
+ use_safetensors=True,
268
+ add_watermarker=False,
269
+ variant="fp16"
270
+ ).to(device)
271
+
272
+ if ENABLE_CPU_OFFLOAD:
273
+ pipe.enable_model_cpu_offload()
274
+ else:
275
+ pipe.to(device)
276
+ print("Loaded on Device!")
277
+
278
+ if USE_TORCH_COMPILE:
279
+ pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
280
+ print("Model Compiled!")
281
+
282
+ def save_image(img, path):
283
+ img.save(path)
284
+ #seeding
285
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
286
+ if randomize_seed:
287
+ seed = random.randint(0, MAX_SEED)
288
+ return seed
289
+
290
+
291
+ @spaces.GPU(enable_queue=True)
292
+ def generate(
293
+ prompt: str,
294
+ negative_prompt: str = "",
295
+ use_negative_prompt: bool = False,
296
+ style: str = DEFAULT_STYLE_NAME,
297
+ collage_style: str = DEFAULT_COLLAGE_STYLE_NAME,
298
+ filter_name: str = DEFAULT_FILTER_NAME,
299
+ grid_size: str = "2x2",
300
+ seed: int = 0,
301
+ width: int = 1024,
302
+ height: int = 1024,
303
+ guidance_scale: float = 3,
304
+ randomize_seed: bool = False,
305
+ use_resolution_binning: bool = True,
306
+ progress=gr.Progress(track_tqdm=True),
307
+ ):
308
+ if check_text(prompt, negative_prompt):
309
+ raise ValueError("Prompt contains restricted words.")
310
+
311
+ if collage_style != "No Style":
312
+ prompt, negative_prompt = apply_style(collage_style, prompt, negative_prompt)
313
+ elif filter_name != "No Filter":
314
+ prompt, negative_prompt = apply_style(filter_name, prompt, negative_prompt)
315
+ else:
316
+ prompt, negative_prompt = apply_style(style, prompt, negative_prompt)
317
+
318
+ seed = int(randomize_seed_fn(seed, randomize_seed))
319
+ generator = torch.Generator().manual_seed(seed)
320
+
321
+ if not use_negative_prompt:
322
+ negative_prompt = "" # type: ignore
323
+ negative_prompt += default_negative
324
+
325
+ grid_sizes = {
326
+ "2x1": (2, 1),
327
+ "1x2": (1, 2),
328
+ "2x2": (2, 2),
329
+ "2x3": (2, 3),
330
+ "3x2": (3, 2),
331
+ "1x1": (1, 1)
332
+ }
333
+
334
+ grid_size_x, grid_size_y = grid_sizes.get(grid_size, (2, 2))
335
+ num_images = grid_size_x * grid_size_y
336
+
337
+ options = {
338
+ "prompt": prompt,
339
+ "negative_prompt": negative_prompt,
340
+ "width": width,
341
+ "height": height,
342
+ "guidance_scale": guidance_scale,
343
+ "num_inference_steps": 20,
344
+ "generator": generator,
345
+ "num_images_per_prompt": num_images,
346
+ "use_resolution_binning": use_resolution_binning,
347
+ "output_type": "pil",
348
+ }
349
+
350
+ torch.cuda.empty_cache() # Clear GPU memory
351
+ images = pipe(**options).images
352
+
353
+ grid_img = Image.new('RGB', (width * grid_size_x, height * grid_size_y))
354
+
355
+ for i, img in enumerate(images[:num_images]):
356
+ grid_img.paste(img, (i % grid_size_x * width, i // grid_size_x * height))
357
+
358
+ unique_name = str(uuid.uuid4()) + ".png"
359
+ save_image(grid_img, unique_name)
360
+ return [unique_name], seed
361
+
362
+
363
+
364
+
365
+ examples = [
366
+
367
+ "Chocolate dripping from a donut against a yellow background, in the style of brocore, hyper-realistic oil --ar 2:3 --q 2 --s 750 --v 5 --ar 2:3 --q 2 --s 750 --v 5",
368
+ "3d image, cute girl, in the style of Pixar --ar 1:2 --stylize 750, 4K resolution highlights, Sharp focus, octane render, ray tracing, Ultra-High-Definition, 8k, UHD, HDR, (Masterpiece:1.5), (best quality:1.5)",
369
+ "Cold coffee in a cup bokeh --ar 85:128 --v 6.0 --style raw5, 4K, Photo-Realistic",
370
+ "Food photography of a milk shake with flying strawberrys against a pink background, professionally studio shot with cinematic lighting. The image is in the style of a professional studio shot --ar 85:128 --v 6.0 --style raw"
371
+
372
+ ]
373
+
374
+ css = '''
375
+ .gradio-container{max-width: 600px !important}
376
+ h1{text-align:center}
377
+ '''
378
+
379
+ with gr.Blocks(css=css, theme="bethecloud/storj_theme") as demo:
380
+ gr.Markdown(DESCRIPTION)
381
+ gr.DuplicateButton(
382
+ value="Duplicate Space for private use",
383
+ elem_id="duplicate-button",
384
+ visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
385
+ )
386
+ with gr.Group():
387
+ with gr.Row():
388
+ prompt = gr.Text(
389
+ label="Prompt",
390
+ show_label=False,
391
+ max_lines=1,
392
+ placeholder="Enter your prompt",
393
+ container=False,
394
+ )
395
+ run_button = gr.Button("Run")
396
+ result = gr.Gallery(label="Grid", columns=1, preview=True)
397
+
398
+
399
+ with gr.Row(visible=True):
400
+ grid_size_selection = gr.Dropdown(
401
+ choices=["2x1", "1x2", "2x2", "2x3", "3x2", "1x1"],
402
+ value="1x1",
403
+ label="Grid Size"
404
+ )
405
+
406
+ with gr.Row(visible=True):
407
+ filter_selection = gr.Radio(
408
+ show_label=True,
409
+ container=True,
410
+ interactive=True,
411
+ choices=FILTER_NAMES,
412
+ value=DEFAULT_FILTER_NAME,
413
+ label="Filter Type",
414
+ )
415
+
416
+ with gr.Row(visible=True):
417
+ collage_style_selection = gr.Radio(
418
+ show_label=True,
419
+ container=True,
420
+ interactive=True,
421
+ choices=COLLAGE_STYLE_NAMES,
422
+ value=DEFAULT_COLLAGE_STYLE_NAME,
423
+ label="Collage Template + Duotone Canvas",
424
+ )
425
+
426
+ with gr.Row(visible=True):
427
+ style_selection = gr.Radio(
428
+ show_label=True,
429
+ container=True,
430
+ interactive=True,
431
+ choices=STYLE_NAMES,
432
+ value=DEFAULT_STYLE_NAME,
433
+ label="Quality Style",
434
+ )
435
+
436
+ with gr.Accordion("Advanced options", open=False):
437
+ use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=True, visible=True)
438
+ negative_prompt = gr.Text(
439
+ label="Negative prompt",
440
+ max_lines=1,
441
+ placeholder="Enter a negative prompt",
442
+ value="(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers:1.4), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation",
443
+ visible=True,
444
+ )
445
+ with gr.Row():
446
+ num_inference_steps = gr.Slider(
447
+ label="Steps",
448
+ minimum=10,
449
+ maximum=30,
450
+ step=1,
451
+ value=15,
452
+ )
453
+ with gr.Row():
454
+ num_images_per_prompt = gr.Slider(
455
+ label="Images",
456
+ minimum=1,
457
+ maximum=5,
458
+ step=1,
459
+ value=2,
460
+ )
461
+ seed = gr.Slider(
462
+ label="Seed",
463
+ minimum=0,
464
+ maximum=MAX_SEED,
465
+ step=1,
466
+ value=0,
467
+ visible=True
468
+ )
469
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
470
+
471
+ with gr.Row(visible=True):
472
+ width = gr.Slider(
473
+ label="Width",
474
+ minimum=512,
475
+ maximum=2048,
476
+ step=64,
477
+ value=1024,
478
+ )
479
+ height = gr.Slider(
480
+ label="Height",
481
+ minimum=512,
482
+ maximum=2048,
483
+ step=64,
484
+ value=1024,
485
+ )
486
+
487
+ with gr.Row():
488
+ guidance_scale = gr.Slider(
489
+ label="Guidance Scale",
490
+ minimum=0.1,
491
+ maximum=20.0,
492
+ step=0.1,
493
+ value=6,
494
+ )
495
+
496
+ gr.Examples(
497
+ examples=examples,
498
+ inputs=prompt,
499
+ outputs=[result, seed],
500
+ fn=generate,
501
+ #cache_examples=True,
502
+ cache_examples=CACHE_EXAMPLES,
503
+ )
504
+
505
+ use_negative_prompt.change(
506
+ fn=lambda x: gr.update(visible=x),
507
+ inputs=use_negative_prompt,
508
+ outputs=negative_prompt,
509
+ api_name=False,
510
+ )
511
+
512
+ gr.on(
513
+ triggers=[
514
+ prompt.submit,
515
+ negative_prompt.submit,
516
+ run_button.click,
517
+ ],
518
+ fn=generate,
519
+ inputs=[
520
+ prompt,
521
+ negative_prompt,
522
+ use_negative_prompt,
523
+ style_selection,
524
+ collage_style_selection,
525
+ filter_selection,
526
+ grid_size_selection,
527
+ seed,
528
+ width,
529
+ height,
530
+ guidance_scale,
531
+ randomize_seed,
532
+ ],
533
+ outputs=[result, seed],
534
+ api_name="run",
535
+ )
536
+
537
+ gr.Markdown("### Duotone Canvas")
538
+ predefined_gallery = gr.Gallery(label="Duotone Canvas", columns=3, show_label=False, value=load_predefined_images1())
539
+
540
+
541
+ if __name__ == "__main__":
542
+ demo.queue(max_size=40).launch()