Ashoka74 commited on
Commit
f5a3a91
โ€ข
1 Parent(s): 209524d

Update app_merged.py

Browse files
Files changed (1) hide show
  1. app_merged.py +331 -0
app_merged.py CHANGED
@@ -58,6 +58,18 @@ from depth_anything_v2.dpt import DepthAnythingV2
58
  import httpx
59
 
60
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  client = httpx.Client(timeout=httpx.Timeout(10.0)) # Set timeout to 10 seconds
62
  NUM_VIEWS = 6
63
  HEIGHT = 768
@@ -140,6 +152,13 @@ hf_hub_download(repo_id="black-forest-labs/FLUX.1-dev", filename="ae.safetensors
140
  hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="clip_l.safetensors", local_dir="models/text_encoders")
141
  t5_path = hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="t5xxl_fp16.safetensors", local_dir="models/text_encoders/t5")
142
 
 
 
 
 
 
 
 
143
 
144
  sd15_name = 'stablediffusionapi/realistic-vision-v51'
145
  tokenizer = CLIPTokenizer.from_pretrained(sd15_name, subfolder="tokenizer")
@@ -191,6 +210,183 @@ with torch.no_grad():
191
  unet_original_forward = unet.forward
192
 
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  def enable_efficient_attention():
195
  if XFORMERS_AVAILABLE:
196
  try:
@@ -1390,6 +1586,77 @@ with gr.Blocks() as app:
1390
 
1391
  with gr.Column():
1392
  result_gallery = gr.Gallery(height=832, object_fit='contain', label='Outputs')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
 
1394
  with gr.Row():
1395
  with gr.Group():
@@ -1451,6 +1718,70 @@ with gr.Blocks() as app:
1451
  example_quick_prompts.click(lambda x, y: ', '.join(y.split(', ')[:2] + [x[0]]), inputs=[example_quick_prompts, prompt], outputs=prompt, show_progress=False, queue=False)
1452
  example_quick_subjects.click(lambda x: x[0], inputs=example_quick_subjects, outputs=prompt, show_progress=False, queue=False)
1453
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1454
 
1455
  def convert_to_pil(image):
1456
  try:
 
58
  import httpx
59
 
60
 
61
+ import gradio as gr
62
+ import torch
63
+ from diffusers import FluxFillPipeline
64
+ from diffusers.utils import load_image
65
+ from PIL import Image, ImageDraw
66
+ import numpy as np
67
+ import spaces
68
+ from huggingface_hub import hf_hub_download
69
+
70
+
71
+
72
+
73
  client = httpx.Client(timeout=httpx.Timeout(10.0)) # Set timeout to 10 seconds
74
  NUM_VIEWS = 6
75
  HEIGHT = 768
 
152
  hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="clip_l.safetensors", local_dir="models/text_encoders")
153
  t5_path = hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="t5xxl_fp16.safetensors", local_dir="models/text_encoders/t5")
154
 
155
+ fill_pipe = FluxFillPipeline.from_pretrained(
156
+ "black-forest-labs/FLUX.1-Fill-dev",
157
+ torch_dtype=torch.bfloat16
158
+ ).to("cuda")
159
+
160
+
161
+
162
 
163
  sd15_name = 'stablediffusionapi/realistic-vision-v51'
164
  tokenizer = CLIPTokenizer.from_pretrained(sd15_name, subfolder="tokenizer")
 
210
  unet_original_forward = unet.forward
211
 
212
 
213
+ def can_expand(source_width, source_height, target_width, target_height, alignment):
214
+ if alignment in ("Left", "Right") and source_width >= target_width:
215
+ return False
216
+ if alignment in ("Top", "Bottom") and source_height >= target_height:
217
+ return False
218
+ return True
219
+
220
+ def prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
221
+ target_size = (width, height)
222
+
223
+ scale_factor = min(target_size[0] / image.width, target_size[1] / image.height)
224
+ new_width = int(image.width * scale_factor)
225
+ new_height = int(image.height * scale_factor)
226
+
227
+ source = image.resize((new_width, new_height), Image.LANCZOS)
228
+
229
+ if resize_option == "Full":
230
+ resize_percentage = 100
231
+ elif resize_option == "75%":
232
+ resize_percentage = 75
233
+ elif resize_option == "50%":
234
+ resize_percentage = 50
235
+ elif resize_option == "33%":
236
+ resize_percentage = 33
237
+ elif resize_option == "25%":
238
+ resize_percentage = 25
239
+ else: # Custom
240
+ resize_percentage = custom_resize_percentage
241
+
242
+ # Calculate new dimensions based on percentage
243
+ resize_factor = resize_percentage / 100
244
+ new_width = int(source.width * resize_factor)
245
+ new_height = int(source.height * resize_factor)
246
+
247
+ # Ensure minimum size of 64 pixels
248
+ new_width = max(new_width, 64)
249
+ new_height = max(new_height, 64)
250
+
251
+ # Resize the image
252
+ source = source.resize((new_width, new_height), Image.LANCZOS)
253
+
254
+ # Calculate the overlap in pixels based on the percentage
255
+ overlap_x = int(new_width * (overlap_percentage / 100))
256
+ overlap_y = int(new_height * (overlap_percentage / 100))
257
+
258
+ # Ensure minimum overlap of 1 pixel
259
+ overlap_x = max(overlap_x, 1)
260
+ overlap_y = max(overlap_y, 1)
261
+
262
+ # Calculate margins based on alignment
263
+ if alignment == "Middle":
264
+ margin_x = (target_size[0] - new_width) // 2
265
+ margin_y = (target_size[1] - new_height) // 2
266
+ elif alignment == "Left":
267
+ margin_x = 0
268
+ margin_y = (target_size[1] - new_height) // 2
269
+ elif alignment == "Right":
270
+ margin_x = target_size[0] - new_width
271
+ margin_y = (target_size[1] - new_height) // 2
272
+ elif alignment == "Top":
273
+ margin_x = (target_size[0] - new_width) // 2
274
+ margin_y = 0
275
+ elif alignment == "Bottom":
276
+ margin_x = (target_size[0] - new_width) // 2
277
+ margin_y = target_size[1] - new_height
278
+
279
+ # Adjust margins to eliminate gaps
280
+ margin_x = max(0, min(margin_x, target_size[0] - new_width))
281
+ margin_y = max(0, min(margin_y, target_size[1] - new_height))
282
+
283
+ # Create a new background image and paste the resized source image
284
+ background = Image.new('RGB', target_size, (255, 255, 255))
285
+ background.paste(source, (margin_x, margin_y))
286
+
287
+ # Create the mask
288
+ mask = Image.new('L', target_size, 255)
289
+ mask_draw = ImageDraw.Draw(mask)
290
+
291
+ # Calculate overlap areas
292
+ white_gaps_patch = 2
293
+
294
+ left_overlap = margin_x + overlap_x if overlap_left else margin_x + white_gaps_patch
295
+ right_overlap = margin_x + new_width - overlap_x if overlap_right else margin_x + new_width - white_gaps_patch
296
+ top_overlap = margin_y + overlap_y if overlap_top else margin_y + white_gaps_patch
297
+ bottom_overlap = margin_y + new_height - overlap_y if overlap_bottom else margin_y + new_height - white_gaps_patch
298
+
299
+ if alignment == "Left":
300
+ left_overlap = margin_x + overlap_x if overlap_left else margin_x
301
+ elif alignment == "Right":
302
+ right_overlap = margin_x + new_width - overlap_x if overlap_right else margin_x + new_width
303
+ elif alignment == "Top":
304
+ top_overlap = margin_y + overlap_y if overlap_top else margin_y
305
+ elif alignment == "Bottom":
306
+ bottom_overlap = margin_y + new_height - overlap_y if overlap_bottom else margin_y + new_height
307
+
308
+ # Draw the mask
309
+ mask_draw.rectangle([
310
+ (left_overlap, top_overlap),
311
+ (right_overlap, bottom_overlap)
312
+ ], fill=0)
313
+
314
+ return background, mask
315
+
316
+ @spaces.GPU
317
+ def inpaint(image, width, height, overlap_percentage, num_inference_steps, resize_option, custom_resize_percentage, prompt_input, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom, progress=gr.Progress(track_tqdm=True)):
318
+
319
+ background, mask = prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom)
320
+
321
+ if not can_expand(background.width, background.height, width, height, alignment):
322
+ alignment = "Middle"
323
+
324
+ cnet_image = background.copy()
325
+ cnet_image.paste(0, (0, 0), mask)
326
+
327
+ final_prompt = prompt_input
328
+
329
+ #generator = torch.Generator(device="cuda").manual_seed(42)
330
+
331
+ fill_result = fill_pipe(
332
+ prompt=final_prompt,
333
+ height=height,
334
+ width=width,
335
+ image=cnet_image,
336
+ mask_image=mask,
337
+ num_inference_steps=num_inference_steps,
338
+ guidance_scale=30,
339
+ ).images[0]
340
+
341
+ fill_result = result.convert("RGBA")
342
+ cnet_image.paste(result, (0, 0), mask)
343
+
344
+ return cnet_image, background
345
+
346
+ def preview_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
347
+ background, mask = prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom)
348
+
349
+ preview = background.copy().convert('RGBA')
350
+ red_overlay = Image.new('RGBA', background.size, (255, 0, 0, 64))
351
+ red_mask = Image.new('RGBA', background.size, (0, 0, 0, 0))
352
+ red_mask.paste(red_overlay, (0, 0), mask)
353
+ preview = Image.alpha_composite(preview, red_mask)
354
+
355
+ return preview
356
+
357
+ def clear_result():
358
+ return gr.update(value=None)
359
+
360
+ def preload_presets(target_ratio, ui_width, ui_height):
361
+ if target_ratio == "9:16":
362
+ return 720, 1280, gr.update()
363
+ elif target_ratio == "16:9":
364
+ return 1280, 720, gr.update()
365
+ elif target_ratio == "1:1":
366
+ return 1024, 1024, gr.update()
367
+ elif target_ratio == "Custom":
368
+ return ui_width, ui_height, gr.update(open=True)
369
+
370
+ def select_the_right_preset(user_width, user_height):
371
+ if user_width == 720 and user_height == 1280:
372
+ return "9:16"
373
+ elif user_width == 1280 and user_height == 720:
374
+ return "16:9"
375
+ elif user_width == 1024 and user_height == 1024:
376
+ return "1:1"
377
+ else:
378
+ return "Custom"
379
+
380
+ def toggle_custom_resize_slider(resize_option):
381
+ return gr.update(visible=(resize_option == "Custom"))
382
+
383
+ def update_history(new_image, history):
384
+ if history is None:
385
+ history = []
386
+ history.insert(0, new_image)
387
+ return history
388
+
389
+
390
  def enable_efficient_attention():
391
  if XFORMERS_AVAILABLE:
392
  try:
 
1586
 
1587
  with gr.Column():
1588
  result_gallery = gr.Gallery(height=832, object_fit='contain', label='Outputs')
1589
+ with gr.Group():
1590
+ gr.Markdown("Outpaint")
1591
+ with gr.Row():
1592
+ with gr.Column(scale=2):
1593
+ prompt_fill = gr.Textbox(label="Prompt (Optional)")
1594
+ with gr.Column(scale=1):
1595
+ fill_button = gr.Button("Generate")
1596
+ target_ratio = gr.Radio(
1597
+ label="Image Ratio",
1598
+ choices=["9:16", "16:9", "1:1", "Custom"],
1599
+ value="9:16",
1600
+ scale=3
1601
+ )
1602
+ alignment_dropdown = gr.Dropdown(
1603
+ choices=["Middle", "Left", "Right", "Top", "Bottom"],
1604
+ value="Middle",
1605
+ label="Alignment",
1606
+ )
1607
+ resize_option = gr.Radio(
1608
+ label="Resize input image",
1609
+ choices=["Full", "75%", "50%", "33%", "25%", "Custom"],
1610
+ value="75%"
1611
+ )
1612
+ custom_resize_percentage = gr.Slider(
1613
+ label="Custom resize (%)",
1614
+ minimum=1,
1615
+ maximum=100,
1616
+ step=1,
1617
+ value=50,
1618
+ visible=False
1619
+ )
1620
+
1621
+ fill_result = gr.Image(
1622
+ interactive=False,
1623
+ label="Generated Image",
1624
+ )
1625
+
1626
+ with gr.Accordion(label="Advanced settings", open=False) as settings_panel:
1627
+ with gr.Column():
1628
+ with gr.Row():
1629
+ width_slider = gr.Slider(
1630
+ label="Target Width",
1631
+ minimum=720,
1632
+ maximum=1536,
1633
+ step=8,
1634
+ value=720,
1635
+ )
1636
+ height_slider = gr.Slider(
1637
+ label="Target Height",
1638
+ minimum=720,
1639
+ maximum=1536,
1640
+ step=8,
1641
+ value=1280,
1642
+ )
1643
+
1644
+ num_inference_steps = gr.Slider(label="Steps", minimum=2, maximum=50, step=1, value=28)
1645
+ with gr.Group():
1646
+ overlap_percentage = gr.Slider(
1647
+ label="Mask overlap (%)",
1648
+ minimum=1,
1649
+ maximum=50,
1650
+ value=10,
1651
+ step=1
1652
+ )
1653
+ with gr.Row():
1654
+ overlap_top = gr.Checkbox(label="Overlap Top", value=True)
1655
+ overlap_right = gr.Checkbox(label="Overlap Right", value=True)
1656
+ with gr.Row():
1657
+ overlap_left = gr.Checkbox(label="Overlap Left", value=True)
1658
+ overlap_bottom = gr.Checkbox(label="Overlap Bottom", value=True)
1659
+
1660
 
1661
  with gr.Row():
1662
  with gr.Group():
 
1718
  example_quick_prompts.click(lambda x, y: ', '.join(y.split(', ')[:2] + [x[0]]), inputs=[example_quick_prompts, prompt], outputs=prompt, show_progress=False, queue=False)
1719
  example_quick_subjects.click(lambda x: x[0], inputs=example_quick_subjects, outputs=prompt, show_progress=False, queue=False)
1720
 
1721
+ # def use_output_as_input(output_image):
1722
+ # return output_image
1723
+
1724
+ # use_as_input_button.click(
1725
+ # fn=use_output_as_input,
1726
+ # inputs=[fill_result],
1727
+ # outputs=[input_image]
1728
+ # )
1729
+
1730
+ target_ratio.change(
1731
+ fn=preload_presets,
1732
+ inputs=[target_ratio, width_slider, height_slider],
1733
+ outputs=[width_slider, height_slider, settings_panel],
1734
+ queue=False
1735
+ )
1736
+
1737
+ width_slider.change(
1738
+ fn=select_the_right_preset,
1739
+ inputs=[width_slider, height_slider],
1740
+ outputs=[target_ratio],
1741
+ queue=False
1742
+ )
1743
+
1744
+ height_slider.change(
1745
+ fn=select_the_right_preset,
1746
+ inputs=[width_slider, height_slider],
1747
+ outputs=[target_ratio],
1748
+ queue=False
1749
+ )
1750
+
1751
+ resize_option.change(
1752
+ fn=toggle_custom_resize_slider,
1753
+ inputs=[resize_option],
1754
+ outputs=[custom_resize_percentage],
1755
+ queue=False
1756
+ )
1757
+
1758
+ fill_button.click(
1759
+ fn=clear_result,
1760
+ inputs=None,
1761
+ outputs=fill_result,
1762
+ ).then(
1763
+ fn=inpaint,
1764
+ inputs=[result_gallery, width_slider, height_slider, overlap_percentage, num_inference_steps,
1765
+ resize_option, custom_resize_percentage, prompt_fill, alignment_dropdown,
1766
+ overlap_left, overlap_right, overlap_top, overlap_bottom],
1767
+ outputs=[fill_result])
1768
+ # ).then(
1769
+ # fn=lambda: gr.update(visible=True),
1770
+ # inputs=None,
1771
+ # outputs=use_as_input_button,
1772
+ # )
1773
+
1774
+ prompt_fill.submit(
1775
+ fn=clear_result,
1776
+ inputs=None,
1777
+ outputs=fill_result,
1778
+ ).then(
1779
+ fn=inpaint,
1780
+ inputs=[result_gallery, width_slider, height_slider, overlap_percentage, num_inference_steps,
1781
+ resize_option, custom_resize_percentage, prompt_fill, alignment_dropdown,
1782
+ overlap_left, overlap_right, overlap_top, overlap_bottom],
1783
+ outputs=[fill_result])
1784
+
1785
 
1786
  def convert_to_pil(image):
1787
  try: