Files changed (3) hide show
  1. README.md +1 -1
  2. app.py +9 -69
  3. requirements.txt +2 -4
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🔅
4
  colorFrom: gray
5
  colorTo: purple
6
  sdk: gradio
7
- sdk_version: 5.32.1
8
  app_file: app.py
9
  pinned: true
10
  license: apache-2.0
 
4
  colorFrom: gray
5
  colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.42.0
8
  app_file: app.py
9
  pinned: true
10
  license: apache-2.0
app.py CHANGED
@@ -169,55 +169,9 @@ def preview_image_and_mask(image, width, height, overlap_percentage, resize_opti
169
  return preview
170
 
171
  @spaces.GPU(duration=24)
172
- def infer(
173
- image,
174
- width,
175
- height,
176
- overlap_percentage,
177
- num_inference_steps,
178
- resize_option,
179
- custom_resize_percentage,
180
- prompt_input,
181
- alignment,
182
- overlap_left,
183
- overlap_right,
184
- overlap_top,
185
- overlap_bottom
186
- ):
187
- """
188
- Generate an outpainted image using Stable Diffusion XL with ControlNet guidance.
189
 
190
- This function performs intelligent image outpainting by expanding the input image
191
- according to the specified target dimensions and alignment, generating new content
192
- guided by a textual prompt. It uses a ControlNet-enabled diffusion pipeline to ensure
193
- coherent image extension.
194
-
195
- Args:
196
- image (PIL.Image): The input image to be outpainted.
197
- width (int): The target width of the output image.
198
- height (int): The target height of the output image.
199
- overlap_percentage (int): Percentage of overlap between original and outpainted regions for seamless blending.
200
- num_inference_steps (int): Number of inference steps for image generation. Higher values yield better results.
201
- resize_option (str): Predefined or custom percentage to resize the input image ("Full", "50%", "33%", "25%", or "Custom").
202
- custom_resize_percentage (int): Custom resize percentage if resize_option is "Custom".
203
- prompt_input (str): A text prompt describing desired content for the generated region.
204
- alignment (str): Alignment of the original image within the canvas ("Middle", "Left", "Right", "Top", "Bottom").
205
- overlap_left (bool): Whether to allow blending on the left edge.
206
- overlap_right (bool): Whether to allow blending on the right edge.
207
- overlap_top (bool): Whether to allow blending on the top edge.
208
- overlap_bottom (bool): Whether to allow blending on the bottom edge.
209
-
210
- Yields:
211
- Tuple[PIL.Image, PIL.Image]:
212
- - The intermediate ControlNet input image (showing the masked area).
213
- - The final generated image with the inpainted region.
214
- """
215
- background, mask = prepare_image_and_mask(
216
- image, width, height, overlap_percentage,
217
- resize_option, custom_resize_percentage, alignment,
218
- overlap_left, overlap_right, overlap_top, overlap_bottom
219
- )
220
-
221
  if not can_expand(background.width, background.height, width, height, alignment):
222
  alignment = "Middle"
223
 
@@ -248,7 +202,6 @@ def infer(
248
 
249
  yield background, cnet_image
250
 
251
-
252
  def clear_result():
253
  """Clears the result ImageSlider."""
254
  return gr.update(value=None)
@@ -421,47 +374,41 @@ with gr.Blocks(css=css) as demo:
421
  use_as_input_button.click(
422
  fn=use_output_as_input,
423
  inputs=[result],
424
- outputs=[input_image],
425
- show_api=False
426
  )
427
 
428
  target_ratio.change(
429
  fn=preload_presets,
430
  inputs=[target_ratio, width_slider, height_slider],
431
  outputs=[width_slider, height_slider, settings_panel],
432
- queue=False,
433
- show_api=False
434
  )
435
 
436
  width_slider.change(
437
  fn=select_the_right_preset,
438
  inputs=[width_slider, height_slider],
439
  outputs=[target_ratio],
440
- queue=False,
441
- show_api=False
442
  )
443
 
444
  height_slider.change(
445
  fn=select_the_right_preset,
446
  inputs=[width_slider, height_slider],
447
  outputs=[target_ratio],
448
- queue=False,
449
- show_api=False
450
  )
451
 
452
  resize_option.change(
453
  fn=toggle_custom_resize_slider,
454
  inputs=[resize_option],
455
  outputs=[custom_resize_percentage],
456
- queue=False,
457
- show_api=False
458
  )
459
 
460
  run_button.click( # Clear the result
461
  fn=clear_result,
462
  inputs=None,
463
  outputs=result,
464
- show_api=False
465
  ).then( # Generate the new image
466
  fn=infer,
467
  inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
@@ -472,36 +419,30 @@ with gr.Blocks(css=css) as demo:
472
  fn=lambda x, history: update_history(x[1], history),
473
  inputs=[result, history_gallery],
474
  outputs=history_gallery,
475
- show_api=False
476
  ).then( # Show the "Use as Input Image" button
477
  fn=lambda: gr.update(visible=True),
478
  inputs=None,
479
  outputs=use_as_input_button,
480
- show_api=False
481
  )
482
 
483
  prompt_input.submit( # Clear the result
484
  fn=clear_result,
485
  inputs=None,
486
  outputs=result,
487
- show_api=False
488
  ).then( # Generate the new image
489
  fn=infer,
490
  inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
491
  resize_option, custom_resize_percentage, prompt_input, alignment_dropdown,
492
  overlap_left, overlap_right, overlap_top, overlap_bottom],
493
  outputs=result,
494
- show_api=False
495
  ).then( # Update the history gallery
496
  fn=lambda x, history: update_history(x[1], history),
497
  inputs=[result, history_gallery],
498
  outputs=history_gallery,
499
- show_api=False
500
  ).then( # Show the "Use as Input Image" button
501
  fn=lambda: gr.update(visible=True),
502
  inputs=None,
503
  outputs=use_as_input_button,
504
- show_api=False
505
  )
506
 
507
  preview_button.click(
@@ -509,8 +450,7 @@ with gr.Blocks(css=css) as demo:
509
  inputs=[input_image, width_slider, height_slider, overlap_percentage, resize_option, custom_resize_percentage, alignment_dropdown,
510
  overlap_left, overlap_right, overlap_top, overlap_bottom],
511
  outputs=preview_image,
512
- queue=False,
513
- show_api=False
514
  )
515
 
516
- demo.queue(max_size=12).launch(share=False, show_error=True, mcp_server=True)
 
169
  return preview
170
 
171
  @spaces.GPU(duration=24)
172
+ def infer(image, width, height, overlap_percentage, num_inference_steps, resize_option, custom_resize_percentage, prompt_input, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
173
+ 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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  if not can_expand(background.width, background.height, width, height, alignment):
176
  alignment = "Middle"
177
 
 
202
 
203
  yield background, cnet_image
204
 
 
205
  def clear_result():
206
  """Clears the result ImageSlider."""
207
  return gr.update(value=None)
 
374
  use_as_input_button.click(
375
  fn=use_output_as_input,
376
  inputs=[result],
377
+ outputs=[input_image]
 
378
  )
379
 
380
  target_ratio.change(
381
  fn=preload_presets,
382
  inputs=[target_ratio, width_slider, height_slider],
383
  outputs=[width_slider, height_slider, settings_panel],
384
+ queue=False
 
385
  )
386
 
387
  width_slider.change(
388
  fn=select_the_right_preset,
389
  inputs=[width_slider, height_slider],
390
  outputs=[target_ratio],
391
+ queue=False
 
392
  )
393
 
394
  height_slider.change(
395
  fn=select_the_right_preset,
396
  inputs=[width_slider, height_slider],
397
  outputs=[target_ratio],
398
+ queue=False
 
399
  )
400
 
401
  resize_option.change(
402
  fn=toggle_custom_resize_slider,
403
  inputs=[resize_option],
404
  outputs=[custom_resize_percentage],
405
+ queue=False
 
406
  )
407
 
408
  run_button.click( # Clear the result
409
  fn=clear_result,
410
  inputs=None,
411
  outputs=result,
 
412
  ).then( # Generate the new image
413
  fn=infer,
414
  inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
 
419
  fn=lambda x, history: update_history(x[1], history),
420
  inputs=[result, history_gallery],
421
  outputs=history_gallery,
 
422
  ).then( # Show the "Use as Input Image" button
423
  fn=lambda: gr.update(visible=True),
424
  inputs=None,
425
  outputs=use_as_input_button,
 
426
  )
427
 
428
  prompt_input.submit( # Clear the result
429
  fn=clear_result,
430
  inputs=None,
431
  outputs=result,
 
432
  ).then( # Generate the new image
433
  fn=infer,
434
  inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
435
  resize_option, custom_resize_percentage, prompt_input, alignment_dropdown,
436
  overlap_left, overlap_right, overlap_top, overlap_bottom],
437
  outputs=result,
 
438
  ).then( # Update the history gallery
439
  fn=lambda x, history: update_history(x[1], history),
440
  inputs=[result, history_gallery],
441
  outputs=history_gallery,
 
442
  ).then( # Show the "Use as Input Image" button
443
  fn=lambda: gr.update(visible=True),
444
  inputs=None,
445
  outputs=use_as_input_button,
 
446
  )
447
 
448
  preview_button.click(
 
450
  inputs=[input_image, width_slider, height_slider, overlap_percentage, resize_option, custom_resize_percentage, alignment_dropdown,
451
  overlap_left, overlap_right, overlap_top, overlap_bottom],
452
  outputs=preview_image,
453
+ queue=False
 
454
  )
455
 
456
+ demo.queue(max_size=12).launch(share=False, show_error=True)
requirements.txt CHANGED
@@ -1,12 +1,10 @@
1
  torch==2.5.1
2
  spaces==0.30.4
3
- gradio[mcp]
4
  gradio-imageslider
5
  numpy==1.26.4
6
  transformers==4.45.0
7
  accelerate==0.33.0
8
- #diffusers==0.30.3
9
- diffusers==0.32.2
10
- huggingface-hub
11
  fastapi<0.113.0
12
  opencv-python
 
1
  torch==2.5.1
2
  spaces==0.30.4
3
+ gradio==4.42.0
4
  gradio-imageslider
5
  numpy==1.26.4
6
  transformers==4.45.0
7
  accelerate==0.33.0
8
+ diffusers==0.30.3
 
 
9
  fastapi<0.113.0
10
  opencv-python