Deadmon commited on
Commit
d86b8bd
1 Parent(s): 9485def

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -116
app.py CHANGED
@@ -3,23 +3,15 @@ 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
-
10
  from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline, AutoencoderKL
11
  from diffusers import DDIMScheduler, EulerAncestralDiscreteScheduler
12
  from controlnet_aux import PidiNetDetector, HEDdetector
13
  from diffusers.utils import load_image
14
  from huggingface_hub import HfApi
15
  from pathlib import Path
16
- from PIL import Image, ImageOps
17
- import torch
18
- import numpy as np
19
- import cv2
20
- import os
21
- import random
22
- import spaces
23
  from gradio_imageslider import ImageSlider
24
 
25
  js_func = """
@@ -27,6 +19,7 @@ function refresh() {
27
  const url = new URL(window.location);
28
  }
29
  """
 
30
  def nms(x, t, s):
31
  x = cv2.GaussianBlur(x.astype(np.float32), (0, 0), s)
32
 
@@ -65,7 +58,7 @@ def HWC3(x):
65
  DESCRIPTION = ''''''
66
 
67
  if not torch.cuda.is_available():
68
- DESCRIPTION += ""
69
 
70
  style_list = [
71
  {
@@ -124,26 +117,17 @@ styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
124
  STYLE_NAMES = list(styles.keys())
125
  DEFAULT_STYLE_NAME = "(No style)"
126
 
127
-
128
- def apply_style(style_name: str, positive: str, negative: str = "") -> tuple[str, str]:
129
  p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
130
  return p.replace("{prompt}", positive), n + negative
131
 
132
-
133
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
134
 
135
  eulera_scheduler = EulerAncestralDiscreteScheduler.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="scheduler")
136
 
 
 
137
 
138
- controlnet = ControlNetModel.from_pretrained(
139
- "xinsir/controlnet-scribble-sdxl-1.0",
140
- torch_dtype=torch.float16
141
- )
142
- controlnet_canny = ControlNetModel.from_pretrained(
143
- "xinsir/controlnet-canny-sdxl-1.0",
144
- torch_dtype=torch.float16
145
- )
146
- # when test with other base model, you need to change the vae also.
147
  vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16)
148
 
149
  pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
@@ -154,7 +138,7 @@ pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
154
  scheduler=eulera_scheduler,
155
  )
156
  pipe.to(device)
157
- # Load model.
158
  pipe_canny = StableDiffusionXLControlNetPipeline.from_pretrained(
159
  "stabilityai/stable-diffusion-xl-base-1.0",
160
  controlnet=controlnet_canny,
@@ -163,60 +147,51 @@ pipe_canny = StableDiffusionXLControlNetPipeline.from_pretrained(
163
  torch_dtype=torch.float16,
164
  scheduler=eulera_scheduler,
165
  )
166
-
167
  pipe_canny.to(device)
168
 
169
  MAX_SEED = np.iinfo(np.int32).max
170
  processor = HEDdetector.from_pretrained('lllyasviel/Annotators')
171
- def nms(x, t, s):
172
- x = cv2.GaussianBlur(x.astype(np.float32), (0, 0), s)
173
-
174
- f1 = np.array([[0, 0, 0], [1, 1, 1], [0, 0, 0]], dtype=np.uint8)
175
- f2 = np.array([[0, 1, 0], [0, 1, 0], [0, 1, 0]], dtype=np.uint8)
176
- f3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.uint8)
177
- f4 = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]], dtype=np.uint8)
178
-
179
- y = np.zeros_like(x)
180
-
181
- for f in [f1, f2, f3, f4]:
182
- np.putmask(y, cv2.dilate(x, kernel=f) == x, x)
183
 
184
- z = np.zeros_like(y, dtype=np.uint8)
185
- z[y > t] = 255
186
- return z
187
-
188
- def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
189
  if randomize_seed:
190
  seed = random.randint(0, MAX_SEED)
191
  return seed
192
 
193
- @spaces.GPU
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  def run(
195
- image: dict,
196
- prompt: str,
197
- negative_prompt: str,
198
- style_name: str = DEFAULT_STYLE_NAME,
199
- num_steps: int = 25,
200
- guidance_scale: float = 5,
201
- controlnet_conditioning_scale: float = 1.0,
202
- seed: int = 0,
203
- use_hed: bool = False,
204
- use_canny: bool = False,
205
  progress=gr.Progress(track_tqdm=True),
206
- ) -> PIL.Image.Image:
207
- # Get the composite image from the EditorValue dict
208
  composite_image = image['composite']
209
  width, height = composite_image.size
210
-
211
- # Calculate new dimensions to fit within 1024x1024 while maintaining aspect ratio
212
  max_size = 1024
213
  ratio = min(max_size / width, max_size / height)
214
  new_width = int(width * ratio)
215
  new_height = int(height * ratio)
216
-
217
- # Resize the image
218
  resized_image = composite_image.resize((new_width, new_height), Image.LANCZOS)
219
-
220
  if use_canny:
221
  controlnet_img = np.array(resized_image)
222
  controlnet_img = cv2.Canny(controlnet_img, 100, 200)
@@ -234,11 +209,11 @@ def run(
234
  controlnet_img[controlnet_img > random_val] = 255
235
  controlnet_img[controlnet_img < 255] = 0
236
  image = Image.fromarray(controlnet_img)
237
-
238
  prompt, negative_prompt = apply_style(style_name, prompt, negative_prompt)
239
 
240
  generator = torch.Generator(device=device).manual_seed(seed)
241
-
242
  if use_canny:
243
  out = pipe_canny(
244
  prompt=prompt,
@@ -270,58 +245,50 @@ with gr.Blocks(css="style.css", js=js_func) as demo:
270
  gr.Markdown(DESCRIPTION, elem_id="description")
271
  gr.DuplicateButton(
272
  value="Duplicate Space for private use",
273
- elem_id="duplicate-button",
274
- visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
275
- )
276
-
277
- with gr.Row():
278
- with gr.Column():
279
- with gr.Group():
280
- image = gr.ImageEditor(type="pil", label="Sketch your image or upload one", width=512, height=512)
281
- prompt = gr.Textbox(label="Prompt")
282
- style = gr.Dropdown(label="Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME)
283
- use_hed = gr.Checkbox(label="use HED detector", value=False, info="check this box if you upload an image and want to turn it to a sketch")
284
- use_canny = gr.Checkbox(label="use Canny", value=False, info="check this to use ControlNet canny instead of scribble")
285
- run_button = gr.Button("Run")
286
- with gr.Accordion("Advanced options", open=False):
287
- negative_prompt = gr.Textbox(
288
- label="Negative prompt",
289
- value="longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality",
290
- )
291
- num_steps = gr.Slider(
292
- label="Number of steps",
293
- minimum=1,
294
- maximum=50,
295
- step=1,
296
- value=25,
297
- )
298
- guidance_scale = gr.Slider(
299
- label="Guidance scale",
300
- minimum=0.1,
301
- maximum=10.0,
302
- step=0.1,
303
- value=5,
304
- )
305
- controlnet_conditioning_scale = gr.Slider(
306
- label="controlnet conditioning scale",
307
- minimum=0.5,
308
- maximum=5.0,
309
- step=0.1,
310
- value=0.9,
311
- )
312
- seed = gr.Slider(
313
- label="Seed",
314
- minimum=0,
315
- maximum=MAX_SEED,
316
- step=1,
317
- value=0,
318
- )
319
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
320
-
321
- with gr.Column():
322
- with gr.Group():
323
- image_slider = ImageSlider(position=0.5)
324
-
325
 
326
  inputs = [
327
  image,
@@ -336,6 +303,7 @@ with gr.Blocks(css="style.css", js=js_func) as demo:
336
  use_canny
337
  ]
338
  outputs = [image_slider]
 
339
  run_button.click(
340
  fn=randomize_seed_fn,
341
  inputs=[seed, randomize_seed],
@@ -345,7 +313,5 @@ with gr.Blocks(css="style.css", js=js_func) as demo:
345
  ).then(lambda x: None, inputs=None, outputs=image_slider).then(
346
  fn=run, inputs=inputs, outputs=outputs
347
  )
348
-
349
-
350
 
351
- demo.queue().launch(show_error=True)
 
3
 
4
  import gradio as gr
5
  import numpy as np
6
+ from PIL import Image, ImageOps
7
  import torch
8
  import torchvision.transforms.functional as TF
 
9
  from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline, AutoencoderKL
10
  from diffusers import DDIMScheduler, EulerAncestralDiscreteScheduler
11
  from controlnet_aux import PidiNetDetector, HEDdetector
12
  from diffusers.utils import load_image
13
  from huggingface_hub import HfApi
14
  from pathlib import Path
 
 
 
 
 
 
 
15
  from gradio_imageslider import ImageSlider
16
 
17
  js_func = """
 
19
  const url = new URL(window.location);
20
  }
21
  """
22
+
23
  def nms(x, t, s):
24
  x = cv2.GaussianBlur(x.astype(np.float32), (0, 0), s)
25
 
 
58
  DESCRIPTION = ''''''
59
 
60
  if not torch.cuda.is_available():
61
+ DESCRIPTION += "GPU not available. Using CPU."
62
 
63
  style_list = [
64
  {
 
117
  STYLE_NAMES = list(styles.keys())
118
  DEFAULT_STYLE_NAME = "(No style)"
119
 
120
+ def apply_style(style_name, positive, negative=""):
 
121
  p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
122
  return p.replace("{prompt}", positive), n + negative
123
 
 
124
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
125
 
126
  eulera_scheduler = EulerAncestralDiscreteScheduler.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="scheduler")
127
 
128
+ controlnet = ControlNetModel.from_pretrained("xinsir/controlnet-scribble-sdxl-1.0", torch_dtype=torch.float16)
129
+ controlnet_canny = ControlNetModel.from_pretrained("xinsir/controlnet-canny-sdxl-1.0", torch_dtype=torch.float16)
130
 
 
 
 
 
 
 
 
 
 
131
  vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16)
132
 
133
  pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
 
138
  scheduler=eulera_scheduler,
139
  )
140
  pipe.to(device)
141
+
142
  pipe_canny = StableDiffusionXLControlNetPipeline.from_pretrained(
143
  "stabilityai/stable-diffusion-xl-base-1.0",
144
  controlnet=controlnet_canny,
 
147
  torch_dtype=torch.float16,
148
  scheduler=eulera_scheduler,
149
  )
 
150
  pipe_canny.to(device)
151
 
152
  MAX_SEED = np.iinfo(np.int32).max
153
  processor = HEDdetector.from_pretrained('lllyasviel/Annotators')
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ def randomize_seed_fn(seed, randomize_seed):
 
 
 
 
156
  if randomize_seed:
157
  seed = random.randint(0, MAX_SEED)
158
  return seed
159
 
160
+ @gr.annotations(
161
+ image=dict,
162
+ prompt=str,
163
+ negative_prompt=str,
164
+ style_name=str,
165
+ num_steps=int,
166
+ guidance_scale=float,
167
+ controlnet_conditioning_scale=float,
168
+ seed=int,
169
+ use_hed=bool,
170
+ use_canny=bool,
171
+ controlnet_img=Image,
172
+ out=Image,
173
+ )
174
  def run(
175
+ image,
176
+ prompt,
177
+ negative_prompt,
178
+ style_name=DEFAULT_STYLE_NAME,
179
+ num_steps=25,
180
+ guidance_scale=5,
181
+ controlnet_conditioning_scale=1.0,
182
+ seed=0,
183
+ use_hed=False,
184
+ use_canny=False,
185
  progress=gr.Progress(track_tqdm=True),
186
+ ):
 
187
  composite_image = image['composite']
188
  width, height = composite_image.size
 
 
189
  max_size = 1024
190
  ratio = min(max_size / width, max_size / height)
191
  new_width = int(width * ratio)
192
  new_height = int(height * ratio)
 
 
193
  resized_image = composite_image.resize((new_width, new_height), Image.LANCZOS)
194
+
195
  if use_canny:
196
  controlnet_img = np.array(resized_image)
197
  controlnet_img = cv2.Canny(controlnet_img, 100, 200)
 
209
  controlnet_img[controlnet_img > random_val] = 255
210
  controlnet_img[controlnet_img < 255] = 0
211
  image = Image.fromarray(controlnet_img)
212
+
213
  prompt, negative_prompt = apply_style(style_name, prompt, negative_prompt)
214
 
215
  generator = torch.Generator(device=device).manual_seed(seed)
216
+
217
  if use_canny:
218
  out = pipe_canny(
219
  prompt=prompt,
 
245
  gr.Markdown(DESCRIPTION, elem_id="description")
246
  gr.DuplicateButton(
247
  value="Duplicate Space for private use",
248
+ elem_Multiplier: gr.ImageEditor(type="pil", label="Sketch your image or upload one", width=512, height=512)
249
+ prompt: gr.Textbox(label="Prompt")
250
+ style: gr.Dropdown(label="Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME)
251
+ use_hed: gr.Checkbox(label="use HED detector", value=False, info="check this box if you upload an image and want to turn it to a sketch")
252
+ use_canny: gr.Checkbox(label="use Canny", value=False, info="check this to use ControlNet canny instead of scribble")
253
+ run_button: gr.Button("Run")
254
+ gr.Accordion("Advanced options", open=False):
255
+ negative_prompt: gr.Textbox(
256
+ label="Negative prompt",
257
+ value="longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality",
258
+ )
259
+ num_steps: gr.Slider(
260
+ label="Number of steps",
261
+ minimum=1,
262
+ maximum=50,
263
+ step=1,
264
+ value=25,
265
+ )
266
+ guidance_scale: gr.Slider(
267
+ label="Guidance scale",
268
+ minimum=0.1,
269
+ maximum=10.0,
270
+ step=0.1,
271
+ value=5,
272
+ )
273
+ controlnet_conditioning_scale: gr.Slider(
274
+ label="controlnet conditioning scale",
275
+ minimum=0.5,
276
+ maximum=5.0,
277
+ step=0.1,
278
+ value=0.9,
279
+ )
280
+ seed: gr.Slider(
281
+ label="Seed",
282
+ minimum=0,
283
+ maximum=MAX_SEED,
284
+ step=1,
285
+ value=0,
286
+ )
287
+ randomize_seed: gr.Checkbox(label="Randomize seed", value=True)
288
+
289
+ with gr.Column():
290
+ with gr.Group():
291
+ image_slider: ImageSlider(position=0.5)
 
 
 
 
 
 
 
 
292
 
293
  inputs = [
294
  image,
 
303
  use_canny
304
  ]
305
  outputs = [image_slider]
306
+
307
  run_button.click(
308
  fn=randomize_seed_fn,
309
  inputs=[seed, randomize_seed],
 
313
  ).then(lambda x: None, inputs=None, outputs=image_slider).then(
314
  fn=run, inputs=inputs, outputs=outputs
315
  )
 
 
316
 
317
+ demo.queue().launch(share=True, show_error=True)