patrickvonplaten commited on
Commit
bb8619e
1 Parent(s): 01e0de2

allow two modes

Browse files
Files changed (1) hide show
  1. app.py +111 -43
app.py CHANGED
@@ -12,6 +12,9 @@ from diffusers import (
12
  ControlNetModel,
13
  DDIMScheduler,
14
  DPMSolverMultistepScheduler,
 
 
 
15
  )
16
 
17
  from PIL import Image
@@ -33,21 +36,17 @@ pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
33
  safety_checker=None,
34
  torch_dtype=torch.float16,
35
  ).to("cuda")
36
-
37
  pipe.enable_xformers_memory_efficient_attention()
38
- pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
39
- # pipe.enable_model_cpu_offload()
40
 
41
 
42
  sd_pipe = StableDiffusionPipeline.from_pretrained(
43
  "stabilityai/stable-diffusion-2-1",
44
  torch_dtype=torch.float16,
45
  safety_checker=None,
46
- ).to("cuda")
47
-
48
  sd_pipe.scheduler = DPMSolverMultistepScheduler.from_config(sd_pipe.scheduler.config)
49
  sd_pipe.enable_xformers_memory_efficient_attention()
50
- # sd_pipe.enable_model_cpu_offload()
51
 
52
 
53
  def resize_for_condition_image(input_image: Image.Image, resolution: int):
@@ -62,6 +61,16 @@ def resize_for_condition_image(input_image: Image.Image, resolution: int):
62
  return img
63
 
64
 
 
 
 
 
 
 
 
 
 
 
65
  def inference(
66
  qr_code_content: str,
67
  prompt: str,
@@ -72,6 +81,8 @@ def inference(
72
  seed: int = -1,
73
  init_image: Image.Image | None = None,
74
  qrcode_image: Image.Image | None = None,
 
 
75
  ):
76
  if prompt is None or prompt == "":
77
  raise gr.Error("Prompt is required")
@@ -79,24 +90,9 @@ def inference(
79
  if qrcode_image is None and qr_code_content == "":
80
  raise gr.Error("QR Code Image or QR Code Content is required")
81
 
82
- generator = torch.manual_seed(seed) if seed != -1 else torch.Generator()
83
-
84
- # hack due to gradio examples
85
- if init_image is None or init_image.size == (1, 1):
86
- print("Generating random image from prompt using Stable Diffusion")
87
- # generate image from prompt
88
- out = sd_pipe(
89
- prompt=prompt,
90
- negative_prompt=negative_prompt,
91
- generator=generator,
92
- num_inference_steps=25,
93
- num_images_per_prompt=1,
94
- ) # type: ignore
95
 
96
- init_image = out.images[0]
97
- else:
98
- print("Using provided init image")
99
- init_image = resize_for_condition_image(init_image, 768)
100
 
101
  if qr_code_content != "" or qrcode_image.size == (1, 1):
102
  print("Generating QR Code from content")
@@ -115,10 +111,29 @@ def inference(
115
  print("Using QR Code Image")
116
  qrcode_image = resize_for_condition_image(qrcode_image, 768)
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  out = pipe(
119
  prompt=prompt,
120
  negative_prompt=negative_prompt,
121
- image=init_image,
122
  control_image=qrcode_image, # type: ignore
123
  width=768, # type: ignore
124
  height=768, # type: ignore
@@ -136,6 +151,22 @@ with gr.Blocks() as blocks:
136
  """
137
  # QR Code AI Art Generator
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
140
 
141
  <a href="https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator?duplicate=true" style="display: inline-block;margin-top: .5em;margin-right: .25em;" target="_blank">
@@ -150,43 +181,55 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
150
  info="QR Code Content or URL",
151
  value="",
152
  )
 
 
 
 
 
 
153
  prompt = gr.Textbox(
154
  label="Prompt",
155
- info="Prompt is required. If init image is not provided, then it will be generated from prompt using Stable Diffusion 2.1",
156
  )
157
  negative_prompt = gr.Textbox(
158
  label="Negative Prompt",
159
  value="ugly, disfigured, low quality, blurry, nsfw",
160
  )
161
- with gr.Accordion(label="Init Images (Optional)", open=False):
162
- init_image = gr.Image(label="Init Image (Optional)", type="pil")
163
 
164
- qr_code_image = gr.Image(
165
- label="QR Code Image (Optional)",
166
- type="pil",
167
- )
 
 
 
 
 
 
168
 
169
  with gr.Accordion(
170
  label="Params: The generated QR Code functionality is largely influenced by the parameters detailed below",
171
- open=False,
172
  ):
173
- guidance_scale = gr.Slider(
174
- minimum=0.0,
175
- maximum=50.0,
176
- step=0.01,
177
- value=10.0,
178
- label="Guidance Scale",
179
- )
180
  controlnet_conditioning_scale = gr.Slider(
181
  minimum=0.0,
182
  maximum=5.0,
183
  step=0.01,
184
- value=2.0,
185
  label="Controlnet Conditioning Scale",
186
  )
187
  strength = gr.Slider(
188
- minimum=0.0, maximum=1.0, step=0.01, value=0.8, label="Strength"
 
 
 
 
 
 
 
189
  )
 
190
  seed = gr.Slider(
191
  minimum=-1,
192
  maximum=9999999999,
@@ -211,12 +254,27 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
211
  seed,
212
  init_image,
213
  qr_code_image,
 
 
214
  ],
215
  outputs=[result_image],
216
  )
217
 
218
  gr.Examples(
219
  examples=[
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  [
221
  "https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator",
222
  "billboard amidst the bustling skyline of New York City, with iconic landmarks subtly featured in the background.",
@@ -227,6 +285,8 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
227
  2313123,
228
  "./examples/hack.png",
229
  "./examples/hack.png",
 
 
230
  ],
231
  [
232
  "https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator",
@@ -238,6 +298,8 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
238
  1423585430,
239
  "./examples/hack.png",
240
  "./examples/hack.png",
 
 
241
  ],
242
  [
243
  "https://huggingface.co",
@@ -249,6 +311,8 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
249
  2702246671,
250
  "./examples/hack.png",
251
  "./examples/hack.png",
 
 
252
  ],
253
  [
254
  "",
@@ -260,6 +324,8 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
260
  2313123,
261
  "./examples/init.jpeg",
262
  "./examples/qrcode.png",
 
 
263
  ],
264
  ],
265
  fn=inference,
@@ -273,10 +339,12 @@ model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
273
  seed,
274
  init_image,
275
  qr_code_image,
 
 
276
  ],
277
  outputs=[result_image],
278
  cache_examples=True,
279
- )
280
 
281
  blocks.queue(concurrency_count=1, max_size=20)
282
- blocks.launch()
 
12
  ControlNetModel,
13
  DDIMScheduler,
14
  DPMSolverMultistepScheduler,
15
+ DEISMultistepScheduler,
16
+ HeunDiscreteScheduler,
17
+ EulerDiscreteScheduler,
18
  )
19
 
20
  from PIL import Image
 
36
  safety_checker=None,
37
  torch_dtype=torch.float16,
38
  ).to("cuda")
 
39
  pipe.enable_xformers_memory_efficient_attention()
 
 
40
 
41
 
42
  sd_pipe = StableDiffusionPipeline.from_pretrained(
43
  "stabilityai/stable-diffusion-2-1",
44
  torch_dtype=torch.float16,
45
  safety_checker=None,
46
+ )
 
47
  sd_pipe.scheduler = DPMSolverMultistepScheduler.from_config(sd_pipe.scheduler.config)
48
  sd_pipe.enable_xformers_memory_efficient_attention()
49
+ sd_pipe.enable_model_cpu_offload()
50
 
51
 
52
  def resize_for_condition_image(input_image: Image.Image, resolution: int):
 
61
  return img
62
 
63
 
64
+ SAMPLER_MAP = {
65
+ "DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),
66
+ "DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),
67
+ "Heun": lambda config: HeunDiscreteScheduler.from_config(config),
68
+ "Euler": lambda config: EulerDiscreteScheduler.from_config(config),
69
+ "DDIM": lambda config: DDIMScheduler.from_config(config),
70
+ "DEIS": lambda config: DEISMultistepScheduler.from_config(config),
71
+ }
72
+
73
+
74
  def inference(
75
  qr_code_content: str,
76
  prompt: str,
 
81
  seed: int = -1,
82
  init_image: Image.Image | None = None,
83
  qrcode_image: Image.Image | None = None,
84
+ use_qr_code_as_init_image = True,
85
+ sampler = "DPM++ Karras SDE",
86
  ):
87
  if prompt is None or prompt == "":
88
  raise gr.Error("Prompt is required")
 
90
  if qrcode_image is None and qr_code_content == "":
91
  raise gr.Error("QR Code Image or QR Code Content is required")
92
 
93
+ pipe.scheduler = SAMPLER_MAP[sampler](pipe.scheduler.config)
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ generator = torch.manual_seed(seed) if seed != -1 else torch.Generator()
 
 
 
96
 
97
  if qr_code_content != "" or qrcode_image.size == (1, 1):
98
  print("Generating QR Code from content")
 
111
  print("Using QR Code Image")
112
  qrcode_image = resize_for_condition_image(qrcode_image, 768)
113
 
114
+ # hack due to gradio examples
115
+ if use_qr_code_as_init_image:
116
+ init_image = qrcode_image
117
+ elif init_image is None or init_image.size == (1, 1):
118
+ print("Generating random image from prompt using Stable Diffusion")
119
+ # generate image from prompt
120
+ out = sd_pipe(
121
+ prompt=prompt,
122
+ negative_prompt=negative_prompt,
123
+ generator=generator,
124
+ num_inference_steps=25,
125
+ num_images_per_prompt=1,
126
+ ) # type: ignore
127
+
128
+ init_image = out.images[0]
129
+ else:
130
+ print("Using provided init image")
131
+ init_image = resize_for_condition_image(init_image, 768)
132
+
133
  out = pipe(
134
  prompt=prompt,
135
  negative_prompt=negative_prompt,
136
+ image=qrcode_image,
137
  control_image=qrcode_image, # type: ignore
138
  width=768, # type: ignore
139
  height=768, # type: ignore
 
151
  """
152
  # QR Code AI Art Generator
153
 
154
+ ## 💡 How to generate beautiful QR codes
155
+
156
+ There are two modes to generate beautiful QR codes:
157
+
158
+ 1. **Blend-in mode**. Use the QR code image as the initial image **and** the control image.
159
+ When using the QR code as both the init and control image, you can get QR Codes that blend in **very** naturally with your provided prompt.
160
+ The strength parameter defines how much noise is added to your QR code and the noisy QR code is then guided towards both your prompt and the QR code image via Controlnet.
161
+ Make sure to leave the radio *Use QR code as init image* checked and use a high strength value (between 0.8 and 0.95) and choose a lower conditioning scale (between 0.7 and 1.3).
162
+ This mode arguably achieves the asthetically most appealing images, but also requires more tuning of the controlnet conditioning scale and the strength value. If the generated image
163
+ looks way to much like the original QR code, make sure to gently increase the *strength* value and reduce the *conditioning* scale. Also check out the examples below.
164
+
165
+ 2. **Condition-only mode**. Use the QR code image **only** as the control image and denoise from a provided initial image.
166
+ When providing an initial image or letting SD 2.1 generate the initial image, you have much more freedom to decide how the generated QR code can look like depending on your provided image.
167
+ This mode allows you to stongly steer the generated QR code into a style, landscape, motive that you provided before-hand. This mode tends to generate QR codes that
168
+ are less *"blend-in"* with the QR code itself. Make sure to choose high controlnet conditioning scales between 2.0 and 3.0 and lower strength values between 0.5 and 0.7. Also check examples below.
169
+
170
  model: https://huggingface.co/DionTimmer/controlnet_qrcode-control_v1p_sd15
171
 
172
  <a href="https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator?duplicate=true" style="display: inline-block;margin-top: .5em;margin-right: .25em;" target="_blank">
 
181
  info="QR Code Content or URL",
182
  value="",
183
  )
184
+ with gr.Accordion(label="QR Code Image (Optional)", open=False):
185
+ qr_code_image = gr.Image(
186
+ label="QR Code Image (Optional). Leave blank to automatically generate QR code",
187
+ type="pil",
188
+ )
189
+
190
  prompt = gr.Textbox(
191
  label="Prompt",
192
+ info="Prompt that guides the generation towards",
193
  )
194
  negative_prompt = gr.Textbox(
195
  label="Negative Prompt",
196
  value="ugly, disfigured, low quality, blurry, nsfw",
197
  )
198
+ use_qr_code_as_init_image = gr.Checkbox(label="Use QR code as init image", value=True, interactive=True, info="Whether init image should be QR code. Unclick to pass init image or generate init image with Stable Diffusion 2.1")
 
199
 
200
+ with gr.Accordion(label="Init Images (Optional)", open=False, visible=False) as init_image_acc:
201
+ init_image = gr.Image(label="Init Image (Optional). Leave blank to generate image with SD 2.1", type="pil")
202
+
203
+ def change_view(qr_code_as_image: bool):
204
+ if not qr_code_as_image:
205
+ return {init_image_acc: gr.update(visible=True)}
206
+ else:
207
+ return {init_image_acc: gr.update(visible=False)}
208
+
209
+ use_qr_code_as_init_image.change(change_view, inputs=[use_qr_code_as_init_image], outputs=[init_image_acc])
210
 
211
  with gr.Accordion(
212
  label="Params: The generated QR Code functionality is largely influenced by the parameters detailed below",
213
+ open=True,
214
  ):
 
 
 
 
 
 
 
215
  controlnet_conditioning_scale = gr.Slider(
216
  minimum=0.0,
217
  maximum=5.0,
218
  step=0.01,
219
+ value=1.1,
220
  label="Controlnet Conditioning Scale",
221
  )
222
  strength = gr.Slider(
223
+ minimum=0.0, maximum=1.0, step=0.01, value=0.9, label="Strength"
224
+ )
225
+ guidance_scale = gr.Slider(
226
+ minimum=0.0,
227
+ maximum=50.0,
228
+ step=0.25,
229
+ value=7.5,
230
+ label="Guidance Scale",
231
  )
232
+ sampler = gr.Dropdown(choices=list(SAMPLER_MAP.keys()), value="DPM++ Karras SDE")
233
  seed = gr.Slider(
234
  minimum=-1,
235
  maximum=9999999999,
 
254
  seed,
255
  init_image,
256
  qr_code_image,
257
+ use_qr_code_as_init_image,
258
+ sampler,
259
  ],
260
  outputs=[result_image],
261
  )
262
 
263
  gr.Examples(
264
  examples=[
265
+ [
266
+ "https://huggingface.co/",
267
+ "A sky view of a colorful lakes and rivers flowing through the desert",
268
+ "ugly, disfigured, low quality, blurry, nsfw",
269
+ 7.5,
270
+ 1.1,
271
+ 0.9,
272
+ 5392011833,
273
+ None,
274
+ None,
275
+ True,
276
+ "DPM++ Karras SDE",
277
+ ],
278
  [
279
  "https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator",
280
  "billboard amidst the bustling skyline of New York City, with iconic landmarks subtly featured in the background.",
 
285
  2313123,
286
  "./examples/hack.png",
287
  "./examples/hack.png",
288
+ False,
289
+ "DDIM",
290
  ],
291
  [
292
  "https://huggingface.co/spaces/huggingface-projects/QR-code-AI-art-generator",
 
298
  1423585430,
299
  "./examples/hack.png",
300
  "./examples/hack.png",
301
+ False,
302
+ "DDIM",
303
  ],
304
  [
305
  "https://huggingface.co",
 
311
  2702246671,
312
  "./examples/hack.png",
313
  "./examples/hack.png",
314
+ False,
315
+ "DDIM",
316
  ],
317
  [
318
  "",
 
324
  2313123,
325
  "./examples/init.jpeg",
326
  "./examples/qrcode.png",
327
+ False,
328
+ "DDIM",
329
  ],
330
  ],
331
  fn=inference,
 
339
  seed,
340
  init_image,
341
  qr_code_image,
342
+ use_qr_code_as_init_image,
343
+ sampler,
344
  ],
345
  outputs=[result_image],
346
  cache_examples=True,
347
+ )
348
 
349
  blocks.queue(concurrency_count=1, max_size=20)
350
+ blocks.launch(share=True)