Pusheen commited on
Commit
e22bbc6
1 Parent(s): af37dce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +556 -0
app.py CHANGED
@@ -0,0 +1,556 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import os
2
+ # os.environ["CUDA_VISIBLE_DEVICES"]="4"
3
+ import gradio as gr
4
+ import torch
5
+ from transformers import CLIPTextModel, CLIPTokenizer
6
+ from diffusers import AutoencoderKL, LMSDiscreteScheduler
7
+ from my_model import unet_2d_condition
8
+ import json
9
+ import numpy as np
10
+ from PIL import Image, ImageDraw, ImageFont
11
+ from functools import partial
12
+ import math
13
+ from utils import compute_ca_loss
14
+ from gradio import processing_utils
15
+ from typing import Optional
16
+
17
+ import warnings
18
+
19
+ import sys
20
+
21
+ sys.tracebacklimit = 0
22
+
23
+ class Blocks(gr.Blocks):
24
+
25
+ def __init__(
26
+ self,
27
+ theme: str = "default",
28
+ analytics_enabled: Optional[bool] = None,
29
+ mode: str = "blocks",
30
+ title: str = "Gradio",
31
+ css: Optional[str] = None,
32
+ **kwargs,
33
+ ):
34
+ self.extra_configs = {
35
+ 'thumbnail': kwargs.pop('thumbnail', ''),
36
+ 'url': kwargs.pop('url', 'https://gradio.app/'),
37
+ 'creator': kwargs.pop('creator', '@teamGradio'),
38
+ }
39
+
40
+ super(Blocks, self).__init__(theme, analytics_enabled, mode, title, css, **kwargs)
41
+ warnings.filterwarnings("ignore")
42
+
43
+ def get_config_file(self):
44
+ config = super(Blocks, self).get_config_file()
45
+
46
+ for k, v in self.extra_configs.items():
47
+ config[k] = v
48
+
49
+ return config
50
+
51
+ def draw_box(boxes=[], texts=[], img=None):
52
+ if len(boxes) == 0 and img is None:
53
+ return None
54
+
55
+ if img is None:
56
+ img = Image.new('RGB', (512, 512), (255, 255, 255))
57
+ colors = ["red", "olive", "blue", "green", "orange", "brown", "cyan", "purple"]
58
+ draw = ImageDraw.Draw(img)
59
+ font = ImageFont.truetype("DejaVuSansMono.ttf", size=18)
60
+ print(boxes)
61
+ for bid, box in enumerate(boxes):
62
+ draw.rectangle([box[0], box[1], box[2], box[3]], outline=colors[bid % len(colors)], width=4)
63
+ anno_text = texts[bid]
64
+ draw.rectangle(
65
+ [box[0], box[3] - int(font.size * 1.2), box[0] + int((len(anno_text) + 0.8) * font.size * 0.6), box[3]],
66
+ outline=colors[bid % len(colors)], fill=colors[bid % len(colors)], width=4)
67
+ draw.text([box[0] + int(font.size * 0.2), box[3] - int(font.size * 1.2)], anno_text, font=font,
68
+ fill=(255, 255, 255))
69
+ return img
70
+
71
+ '''
72
+ inference model
73
+ '''
74
+
75
+ def inference(device, unet, vae, tokenizer, text_encoder, prompt, bboxes, object_positions, batch_size, loss_scale, loss_threshold, max_iter, max_index_step, rand_seed, guidance_scale):
76
+ uncond_input = tokenizer(
77
+ [""] * 1, padding="max_length", max_length=tokenizer.model_max_length, return_tensors="pt"
78
+ )
79
+ uncond_embeddings = text_encoder(uncond_input.input_ids.to(device))[0]
80
+
81
+ input_ids = tokenizer(
82
+ prompt,
83
+ padding="max_length",
84
+ truncation=True,
85
+ max_length=tokenizer.model_max_length,
86
+ return_tensors="pt",
87
+ ).input_ids[0].unsqueeze(0).to(device)
88
+ # text_embeddings = text_encoder(input_ids)[0]
89
+ text_embeddings = torch.cat([uncond_embeddings, text_encoder(input_ids)[0]])
90
+ # text_embeddings[1, 1, :] = text_embeddings[1, 2, :]
91
+ generator = torch.manual_seed(rand_seed) # Seed generator to create the inital latent noise
92
+
93
+ latents = torch.randn(
94
+ (batch_size, 4, 64, 64),
95
+ generator=generator,
96
+ ).to(device)
97
+
98
+ noise_scheduler = LMSDiscreteScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", num_train_timesteps=1000)
99
+
100
+ # generator = torch.Generator("cuda").manual_seed(1024)
101
+ noise_scheduler.set_timesteps(51)
102
+
103
+ latents = latents * noise_scheduler.init_noise_sigma
104
+
105
+ loss = torch.tensor(10000)
106
+
107
+ for index, t in enumerate(noise_scheduler.timesteps):
108
+ iteration = 0
109
+
110
+ while loss.item() / loss_scale > loss_threshold and iteration < max_iter and index < max_index_step:
111
+ latents = latents.requires_grad_(True)
112
+
113
+ # latent_model_input = torch.cat([latents] * 2)
114
+ latent_model_input = latents
115
+
116
+ latent_model_input = noise_scheduler.scale_model_input(latent_model_input, t)
117
+ noise_pred, attn_map_integrated_up, attn_map_integrated_mid, attn_map_integrated_down = \
118
+ unet(latent_model_input, t, encoder_hidden_states=text_encoder(input_ids)[0])
119
+
120
+ # update latents with guidence from gaussian blob
121
+
122
+ loss = compute_ca_loss(attn_map_integrated_mid, attn_map_integrated_up, bboxes=bboxes,
123
+ object_positions=object_positions) * loss_scale
124
+
125
+ print(loss.item() / loss_scale)
126
+
127
+ grad_cond = torch.autograd.grad(loss.requires_grad_(True), [latents])[0]
128
+
129
+ latents = latents - grad_cond * noise_scheduler.sigmas[index] ** 2
130
+ iteration += 1
131
+ torch.cuda.empty_cache()
132
+ torch.cuda.empty_cache()
133
+
134
+
135
+ with torch.no_grad():
136
+
137
+ latent_model_input = torch.cat([latents] * 2)
138
+
139
+ latent_model_input = noise_scheduler.scale_model_input(latent_model_input, t)
140
+ noise_pred, attn_map_integrated_up, attn_map_integrated_mid, attn_map_integrated_down = \
141
+ unet(latent_model_input, t, encoder_hidden_states=text_embeddings)
142
+
143
+ noise_pred = noise_pred.sample
144
+
145
+ # perform classifier-free guidance
146
+ noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
147
+ noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
148
+
149
+ latents = noise_scheduler.step(noise_pred, t, latents).prev_sample
150
+ torch.cuda.empty_cache()
151
+ # Decode image
152
+ with torch.no_grad():
153
+ # print("decode image")
154
+ latents = 1 / 0.18215 * latents
155
+ image = vae.decode(latents).sample
156
+ image = (image / 2 + 0.5).clamp(0, 1)
157
+ image = image.detach().cpu().permute(0, 2, 3, 1).numpy()
158
+ images = (image * 255).round().astype("uint8")
159
+ pil_images = [Image.fromarray(image) for image in images]
160
+ return pil_images
161
+
162
+ def get_concat(ims):
163
+ if len(ims) == 1:
164
+ n_col = 1
165
+ else:
166
+ n_col = 2
167
+ n_row = math.ceil(len(ims) / 2)
168
+ dst = Image.new('RGB', (ims[0].width * n_col, ims[0].height * n_row), color="white")
169
+ for i, im in enumerate(ims):
170
+ row_id = i // n_col
171
+ col_id = i % n_col
172
+ dst.paste(im, (im.width * col_id, im.height * row_id))
173
+ return dst
174
+
175
+
176
+ def generate(unet, vae, tokenizer, text_encoder, language_instruction, grounding_texts, sketch_pad,
177
+ loss_threshold, guidance_scale, batch_size, rand_seed, max_step, loss_scale, max_iter,
178
+ state):
179
+ if 'boxes' not in state:
180
+ state['boxes'] = []
181
+ boxes = state['boxes']
182
+ grounding_texts = [x.strip() for x in grounding_texts.split(';')]
183
+ # assert len(boxes) == len(grounding_texts)
184
+ if len(boxes) != len(grounding_texts):
185
+ if len(boxes) < len(grounding_texts):
186
+ raise ValueError("""The number of boxes should be equal to the number of grounding objects.
187
+ Number of boxes drawn: {}, number of grounding tokens: {}.
188
+ Please draw boxes accordingly on the sketch pad.""".format(len(boxes), len(grounding_texts)))
189
+ grounding_texts = grounding_texts + [""] * (len(boxes) - len(grounding_texts))
190
+
191
+ boxes = (np.asarray(boxes) / 512).tolist()
192
+ boxes = [[box] for box in boxes]
193
+ grounding_instruction = json.dumps({obj: box for obj, box in zip(grounding_texts, boxes)})
194
+ language_instruction_list = language_instruction.strip('.').split(' ')
195
+ object_positions = []
196
+ for obj in grounding_texts:
197
+ obj_position = []
198
+ for word in obj.split(' '):
199
+ obj_first_index = language_instruction_list.index(word) + 1
200
+ obj_position.append(obj_first_index)
201
+ object_positions.append(obj_position)
202
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
203
+
204
+ gen_images = inference(device, unet, vae, tokenizer, text_encoder, language_instruction, boxes, object_positions, batch_size, loss_scale, loss_threshold, max_iter, max_step, rand_seed, guidance_scale)
205
+
206
+ blank_samples = batch_size % 2 if batch_size > 1 else 0
207
+ gen_images = [gr.Image.update(value=x, visible=True) for i, x in enumerate(gen_images)] \
208
+ + [gr.Image.update(value=None, visible=True) for _ in range(blank_samples)] \
209
+ + [gr.Image.update(value=None, visible=False) for _ in range(4 - batch_size - blank_samples)]
210
+
211
+ return gen_images + [state]
212
+
213
+
214
+ def binarize(x):
215
+ return (x != 0).astype('uint8') * 255
216
+
217
+
218
+ def sized_center_crop(img, cropx, cropy):
219
+ y, x = img.shape[:2]
220
+ startx = x // 2 - (cropx // 2)
221
+ starty = y // 2 - (cropy // 2)
222
+ return img[starty:starty + cropy, startx:startx + cropx]
223
+
224
+
225
+ def sized_center_fill(img, fill, cropx, cropy):
226
+ y, x = img.shape[:2]
227
+ startx = x // 2 - (cropx // 2)
228
+ starty = y // 2 - (cropy // 2)
229
+ img[starty:starty + cropy, startx:startx + cropx] = fill
230
+ return img
231
+
232
+
233
+ def sized_center_mask(img, cropx, cropy):
234
+ y, x = img.shape[:2]
235
+ startx = x // 2 - (cropx // 2)
236
+ starty = y // 2 - (cropy // 2)
237
+ center_region = img[starty:starty + cropy, startx:startx + cropx].copy()
238
+ img = (img * 0.2).astype('uint8')
239
+ img[starty:starty + cropy, startx:startx + cropx] = center_region
240
+ return img
241
+
242
+
243
+ def center_crop(img, HW=None, tgt_size=(512, 512)):
244
+ if HW is None:
245
+ H, W = img.shape[:2]
246
+ HW = min(H, W)
247
+ img = sized_center_crop(img, HW, HW)
248
+ img = Image.fromarray(img)
249
+ img = img.resize(tgt_size)
250
+ return np.array(img)
251
+
252
+
253
+ def draw(input, grounding_texts, new_image_trigger, state):
254
+ if type(input) == dict:
255
+ image = input['image']
256
+ mask = input['mask']
257
+ else:
258
+ mask = input
259
+ if mask.ndim == 3:
260
+ mask = 255 - mask[..., 0]
261
+
262
+ image_scale = 1.0
263
+
264
+ mask = binarize(mask)
265
+
266
+ if type(mask) != np.ndarray:
267
+ mask = np.array(mask)
268
+
269
+ if mask.sum() == 0:
270
+ state = {}
271
+
272
+ image = None
273
+
274
+ if 'boxes' not in state:
275
+ state['boxes'] = []
276
+
277
+ if 'masks' not in state or len(state['masks']) == 0:
278
+ state['masks'] = []
279
+ last_mask = np.zeros_like(mask)
280
+ else:
281
+ last_mask = state['masks'][-1]
282
+
283
+ if type(mask) == np.ndarray and mask.size > 1:
284
+ diff_mask = mask - last_mask
285
+ else:
286
+ diff_mask = np.zeros([])
287
+
288
+ if diff_mask.sum() > 0:
289
+ x1x2 = np.where(diff_mask.max(0) != 0)[0]
290
+ y1y2 = np.where(diff_mask.max(1) != 0)[0]
291
+ y1, y2 = y1y2.min(), y1y2.max()
292
+ x1, x2 = x1x2.min(), x1x2.max()
293
+
294
+ if (x2 - x1 > 5) and (y2 - y1 > 5):
295
+ state['masks'].append(mask.copy())
296
+ state['boxes'].append((x1, y1, x2, y2))
297
+
298
+ grounding_texts = [x.strip() for x in grounding_texts.split(';')]
299
+ grounding_texts = [x for x in grounding_texts if len(x) > 0]
300
+ if len(grounding_texts) < len(state['boxes']):
301
+ grounding_texts += [f'Obj. {bid + 1}' for bid in range(len(grounding_texts), len(state['boxes']))]
302
+ box_image = draw_box(state['boxes'], grounding_texts, image)
303
+
304
+ return [box_image, new_image_trigger, image_scale, state]
305
+
306
+
307
+ def clear(task, sketch_pad_trigger, batch_size, state, switch_task=False):
308
+ if task != 'Grounded Inpainting':
309
+ sketch_pad_trigger = sketch_pad_trigger + 1
310
+ blank_samples = batch_size % 2 if batch_size > 1 else 0
311
+ out_images = [gr.Image.update(value=None, visible=True) for i in range(batch_size)]
312
+ # state = {}
313
+ return [None, sketch_pad_trigger, None, 1.0] + out_images + [{}]
314
+
315
+
316
+ def main():
317
+
318
+ css = """
319
+ #img2img_image, #img2img_image > .fixed-height, #img2img_image > .fixed-height > div, #img2img_image > .fixed-height > div > img
320
+ {
321
+ height: var(--height) !important;
322
+ max-height: var(--height) !important;
323
+ min-height: var(--height) !important;
324
+ }
325
+ #paper-info a {
326
+ color:#008AD7;
327
+ text-decoration: none;
328
+ }
329
+ #paper-info a:hover {
330
+ cursor: pointer;
331
+ text-decoration: none;
332
+ }
333
+
334
+ .tooltip {
335
+ color: #555;
336
+ position: relative;
337
+ display: inline-block;
338
+ cursor: pointer;
339
+ }
340
+
341
+ .tooltip .tooltiptext {
342
+ visibility: hidden;
343
+ width: 400px;
344
+ background-color: #555;
345
+ color: #fff;
346
+ text-align: center;
347
+ padding: 5px;
348
+ border-radius: 5px;
349
+ position: absolute;
350
+ z-index: 1; /* Set z-index to 1 */
351
+ left: 10px;
352
+ top: 100%;
353
+ opacity: 0;
354
+ transition: opacity 0.3s;
355
+ }
356
+
357
+ .tooltip:hover .tooltiptext {
358
+ visibility: visible;
359
+ opacity: 1;
360
+ z-index: 9999; /* Set a high z-index value when hovering */
361
+ }
362
+
363
+
364
+ """
365
+
366
+ rescale_js = """
367
+ function(x) {
368
+ const root = document.querySelector('gradio-app').shadowRoot || document.querySelector('gradio-app');
369
+ let image_scale = parseFloat(root.querySelector('#image_scale input').value) || 1.0;
370
+ const image_width = root.querySelector('#img2img_image').clientWidth;
371
+ const target_height = parseInt(image_width * image_scale);
372
+ document.body.style.setProperty('--height', `${target_height}px`);
373
+ root.querySelectorAll('button.justify-center.rounded')[0].style.display='none';
374
+ root.querySelectorAll('button.justify-center.rounded')[1].style.display='none';
375
+ return x;
376
+ }
377
+ """
378
+ with open('./conf/unet/config.json') as f:
379
+ unet_config = json.load(f)
380
+
381
+ sd_path = "runwayml/stable-diffusion-v1-5"
382
+ unet = unet_2d_condition.UNet2DConditionModel(**unet_config).from_pretrained(sd_path,
383
+ subfolder="unet")
384
+ tokenizer = CLIPTokenizer.from_pretrained(sd_path, subfolder="tokenizer")
385
+ text_encoder = CLIPTextModel.from_pretrained(sd_path, subfolder="text_encoder")
386
+ vae = AutoencoderKL.from_pretrained(sd_path, subfolder="vae")
387
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
388
+ unet.to(device)
389
+ text_encoder.to(device)
390
+ vae.to(device)
391
+
392
+ with Blocks(
393
+ css=css,
394
+ analytics_enabled=False,
395
+ title="LoCo: Locally Constrained Training-free Layout-to-Image Generation",
396
+ ) as demo:
397
+ description = """<p style="text-align: center; font-weight: bold;">
398
+ <span style="font-size: 28px">LoCo: Locally Constrained Training-free Layout-to-Image Generation</span>
399
+ <br>
400
+ <span style="font-size: 18px" id="paper-info">
401
+ [<a href=" " target="_blank">Project Page</a>]
402
+ [<a href=" " target="_blank">Paper</a>]
403
+ [<a href=" " target="_blank">GitHub</a>]
404
+ </span>
405
+ </p>
406
+ """
407
+ gr.HTML(description)
408
+ with gr.Column():
409
+ language_instruction = gr.Textbox(
410
+ label="Text Prompt",
411
+ )
412
+ grounding_instruction = gr.Textbox(
413
+ label="Grounding instruction (Separated by semicolon)",
414
+ )
415
+ sketch_pad_trigger = gr.Number(value=0, visible=False)
416
+ sketch_pad_resize_trigger = gr.Number(value=0, visible=False)
417
+ init_white_trigger = gr.Number(value=0, visible=False)
418
+ image_scale = gr.Number(value=0, elem_id="image_scale", visible=False)
419
+ new_image_trigger = gr.Number(value=0, visible=False)
420
+
421
+
422
+ with gr.Row():
423
+ sketch_pad = gr.Paint(label="Sketch Pad", elem_id="img2img_image", source='canvas', shape=(512, 512))
424
+ # sketch_pad = gr.Image(source='canvas', tool='sketch', size=(512, 512))
425
+ out_imagebox = gr.Image(type="pil", label="Parsed Sketch Pad")
426
+ out_gen_1 = gr.Image(type="pil", visible=True, label="Generated Image")
427
+
428
+ with gr.Row():
429
+ clear_btn = gr.Button(value='Clear')
430
+ gen_btn = gr.Button(value='Generate')
431
+
432
+ with gr.Accordion("Advanced Options", open=False):
433
+ with gr.Column():
434
+ description = """<div class="tooltip">Loss Scale Factor &#9432
435
+ <span class="tooltiptext">The scale factor of the backward guidance loss. The larger it is, the better control we get while it sometimes losses fidelity. </span>
436
+ </div>
437
+ <div class="tooltip">Guidance Scale &#9432
438
+ <span class="tooltiptext">The scale factor of classifier-free guidance. </span>
439
+ </div>
440
+ <div class="tooltip" >Max Iteration per Step &#9432
441
+ <span class="tooltiptext">The max iterations of backward guidance in each diffusion inference process.</span>
442
+ </div>
443
+ <div class="tooltip" >Loss Threshold &#9432
444
+ <span class="tooltiptext">The threshold of loss. If the loss computed by cross-attention map is smaller then the threshold, the backward guidance is stopped. </span>
445
+ </div>
446
+ <div class="tooltip" >Max Step of Backward Guidance &#9432
447
+ <span class="tooltiptext">The max steps of backward guidance in diffusion inference process.</span>
448
+ </div>
449
+ """
450
+ gr.HTML(description)
451
+ Loss_scale = gr.Slider(minimum=0, maximum=500, step=5, value=30,label="Loss Scale Factor")
452
+ guidance_scale = gr.Slider(minimum=0, maximum=50, step=0.5, value=7.5, label="Guidance Scale")
453
+ batch_size = gr.Slider(minimum=1, maximum=4, step=1, value=1, label="Number of Samples", visible=False)
454
+ max_iter = gr.Slider(minimum=0, maximum=10, step=1, value=5, label="Max Iteration per Step")
455
+ loss_threshold = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.2, label="Loss Threshold")
456
+ max_step = gr.Slider(minimum=0, maximum=50, step=1, value=10, label="Max Step of Backward Guidance")
457
+ rand_seed = gr.Slider(minimum=0, maximum=1000, step=1, value=445, label="Random Seed")
458
+
459
+ state = gr.State({})
460
+
461
+
462
+ class Controller:
463
+ def __init__(self):
464
+ self.calls = 0
465
+ self.tracks = 0
466
+ self.resizes = 0
467
+ self.scales = 0
468
+
469
+ def init_white(self, init_white_trigger):
470
+ self.calls += 1
471
+ return np.ones((512, 512), dtype='uint8') * 255, 1.0, init_white_trigger + 1
472
+
473
+ def change_n_samples(self, n_samples):
474
+ blank_samples = n_samples % 2 if n_samples > 1 else 0
475
+ return [gr.Image.update(visible=True) for _ in range(n_samples + blank_samples)] \
476
+ + [gr.Image.update(visible=False) for _ in range(4 - n_samples - blank_samples)]
477
+
478
+
479
+ controller = Controller()
480
+ demo.load(
481
+ lambda x: x + 1,
482
+ inputs=sketch_pad_trigger,
483
+ outputs=sketch_pad_trigger,
484
+ queue=False)
485
+ sketch_pad.edit(
486
+ draw,
487
+ inputs=[sketch_pad, grounding_instruction, sketch_pad_resize_trigger, state],
488
+ outputs=[out_imagebox, sketch_pad_resize_trigger, image_scale, state],
489
+ queue=False,
490
+ )
491
+ grounding_instruction.change(
492
+ draw,
493
+ inputs=[sketch_pad, grounding_instruction, sketch_pad_resize_trigger, state],
494
+ outputs=[out_imagebox, sketch_pad_resize_trigger, image_scale, state],
495
+ queue=False,
496
+ )
497
+ clear_btn.click(
498
+ clear,
499
+ inputs=[sketch_pad_trigger, sketch_pad_trigger, batch_size, state],
500
+ outputs=[sketch_pad, sketch_pad_trigger, out_imagebox, image_scale, out_gen_1, state],
501
+ queue=False)
502
+
503
+ sketch_pad_trigger.change(
504
+ controller.init_white,
505
+ inputs=[init_white_trigger],
506
+ outputs=[sketch_pad, image_scale, init_white_trigger],
507
+ queue=False)
508
+
509
+ gen_btn.click(
510
+ fn=partial(generate, unet, vae, tokenizer, text_encoder),
511
+ inputs=[
512
+ language_instruction, grounding_instruction, sketch_pad,
513
+ loss_threshold, guidance_scale, batch_size, rand_seed,
514
+ max_step,
515
+ Loss_scale, max_iter,
516
+ state,
517
+ ],
518
+ outputs=[out_gen_1, state],
519
+ queue=True
520
+ )
521
+ sketch_pad_resize_trigger.change(
522
+ None,
523
+ None,
524
+ sketch_pad_resize_trigger,
525
+ _js=rescale_js,
526
+ queue=False)
527
+ init_white_trigger.change(
528
+ None,
529
+ None,
530
+ init_white_trigger,
531
+ _js=rescale_js,
532
+ queue=False)
533
+
534
+ with gr.Column():
535
+ gr.Examples(
536
+ examples=[
537
+ [
538
+ # "images/input.png",
539
+ "A hello kitty toy is playing with a purple ball.",
540
+ "hello kitty;ball",
541
+ "images/hello_kitty_results.png"
542
+ ],
543
+ ],
544
+ inputs=[language_instruction, grounding_instruction, out_gen_1],
545
+ outputs=None,
546
+ fn=None,
547
+ cache_examples=False,
548
+ )
549
+ description = """<p> The source codes of the demo are modified based on the <a href="https://huggingface.co/spaces/gligen/demo/tree/main">GlIGen</a>. Thanks! </p>"""
550
+ gr.HTML(description)
551
+
552
+ demo.queue(concurrency_count=1, api_open=False)
553
+ demo.launch(share=False, show_api=False, show_error=True)
554
+
555
+ if __name__ == '__main__':
556
+ main()