multimodalart HF Staff commited on
Commit
e3d141b
·
verified ·
1 Parent(s): 97e5c65

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -38
app.py CHANGED
@@ -15,6 +15,7 @@ import cv2
15
  import tempfile
16
  import os
17
 
 
18
  config_file = hf_hub_download(
19
  "xinsir/controlnet-union-sdxl-1.0",
20
  filename="config_promax.json",
@@ -169,39 +170,35 @@ def infer(image, width=1024, height=1024, overlap_width=18, num_inference_steps=
169
 
170
  yield background, cnet_image
171
 
172
- def clear_result():
173
- """Clears the result ImageSlider."""
174
- return gr.update(value=None)
175
-
176
- def preload_presets(target_ratio, ui_width, ui_height):
177
- """Updates the width and height sliders based on the selected aspect ratio."""
178
- if target_ratio == "9:16":
179
- changed_width = 720
180
- changed_height = 1280
181
- return changed_width, changed_height, gr.update(open=False)
182
- elif target_ratio == "16:9":
183
- changed_width = 1280
184
- changed_height = 720
185
- return changed_width, changed_height, gr.update(open=False)
186
- elif target_ratio == "1:1":
187
- changed_width = 1024
188
- changed_height = 1024
189
- return changed_width, changed_height, gr.update(open=False)
190
- elif target_ratio == "Custom":
191
- return ui_width, ui_height, gr.update(open=True)
192
-
193
- def select_the_right_preset(user_width, user_height):
194
- if user_width == 720 and user_height == 1280:
195
- return "9:16"
196
- elif user_width == 1280 and user_height == 720:
197
- return "16:9"
198
- elif user_width == 1024 and user_height == 1024:
199
- return "1:1"
200
- else:
201
- return "Custom"
202
 
203
- def toggle_custom_resize_slider(resize_option):
204
- return gr.update(visible=(resize_option == "Custom"))
205
 
206
  def create_video_from_images(image_list, fps=4):
207
  if not image_list:
@@ -222,28 +219,68 @@ def create_video_from_images(image_list, fps=4):
222
  return video_path
223
 
224
  @spaces.GPU(duration=70)
225
- def loop_outpainting(image, width=1024, height=1024, overlap_width=18, num_inference_steps=8, resize_option="custom", custom_resize_size=768, prompt_input=None, alignment="Middle", num_iterations=18, fps=6, progress=gr.Progress()):
 
 
 
226
  image_list = [image]
227
  current_image = image
228
 
229
  for _ in progress.tqdm(range(num_iterations), desc="Generating frames"):
230
  # Generate new image
231
- for step_result in infer(current_image, width, height, overlap_width, num_inference_steps, resize_option, custom_resize_size, prompt_input, alignment):
 
232
  pass # Process all steps
233
 
234
  new_image = step_result[1] # Get the final image from the last step
235
- image_list.append(new_image)
 
 
 
236
 
237
  # Use new image as input for next iteration
238
  current_image = new_image
239
 
240
- reverse_image_list = image_list[::-1]
241
  # Create video from image list
242
- video_path = create_video_from_images(reverse_image_list, fps)
243
  return video_path
244
 
245
  loop_outpainting.zerogpu = True
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  css = """
248
  .gradio-container {
249
  width: 1200px !important;
@@ -326,6 +363,8 @@ with gr.Blocks(css=css) as demo:
326
  with gr.Row():
327
  num_iterations = gr.Slider(label="Number of iterations", minimum=2, maximum=24, step=1, value=18)
328
  fps = gr.Slider(label="fps", minimum=1, maximum=24, value=8)
 
 
329
 
330
  with gr.Column():
331
  result = ImageSlider(
@@ -335,6 +374,7 @@ with gr.Blocks(css=css) as demo:
335
  )
336
  use_as_input_button = gr.Button("Use as Input Image", visible=False)
337
  video_output = gr.Video(label="Outpainting Video")
 
338
  gr.Examples(
339
  examples=["hide.png", "disaster.png"],
340
  fn=loop_outpainting,
@@ -342,6 +382,7 @@ with gr.Blocks(css=css) as demo:
342
  outputs=video_output,
343
  cache_examples="lazy"
344
  )
 
345
  def use_output_as_input(output_image):
346
  """Sets the generated output as the new input image."""
347
  return gr.update(value=output_image[1])
@@ -413,7 +454,8 @@ with gr.Blocks(css=css) as demo:
413
  loop_button.click(
414
  fn=loop_outpainting,
415
  inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
416
- resize_option, custom_resize_size, prompt_input, alignment_dropdown, num_iterations, fps],
 
417
  outputs=video_output,
418
  )
419
 
 
15
  import tempfile
16
  import os
17
 
18
+ # Load models and configurations
19
  config_file = hf_hub_download(
20
  "xinsir/controlnet-union-sdxl-1.0",
21
  filename="config_promax.json",
 
170
 
171
  yield background, cnet_image
172
 
173
+ def interpolate_frames(frame1, frame2, num_intermediate_frames):
174
+ """
175
+ Interpolate between two frames by gradually zooming out from frame2 to frame1.
176
+ """
177
+ frame1 = np.array(frame1)
178
+ frame2 = np.array(frame2)
179
+ h, w = frame1.shape[:2]
180
+ frames = []
181
+
182
+ for i in range(num_intermediate_frames + 2):
183
+ progress = i / (num_intermediate_frames + 1)
184
+ # Calculate the size of the inner frame
185
+ inner_h = int(h * (1 - progress))
186
+ inner_w = int(w * (1 - progress))
187
+
188
+ # Crop the center of frame2
189
+ start_y = (h - inner_h) // 2
190
+ start_x = (w - inner_w) // 2
191
+ cropped = frame2[start_y:start_y+inner_h, start_x:start_x+inner_w]
192
+
193
+ # Resize the cropped image to full size
194
+ interpolated = Image.fromarray(cropped).resize((w, h), Image.LANCZOS)
195
+ interpolated = np.array(interpolated)
196
+
197
+ # Blend with frame1
198
+ blended = (1 - progress) * frame1 + progress * interpolated
199
+ frames.append(Image.fromarray(blended.astype(np.uint8)))
 
 
 
200
 
201
+ return frames
 
202
 
203
  def create_video_from_images(image_list, fps=4):
204
  if not image_list:
 
219
  return video_path
220
 
221
  @spaces.GPU(duration=70)
222
+ def loop_outpainting(image, width=1024, height=1024, overlap_width=18, num_inference_steps=8,
223
+ resize_option="custom", custom_resize_size=768, prompt_input=None,
224
+ alignment="Middle", num_iterations=18, fps=6, num_interpolation_frames=5,
225
+ progress=gr.Progress()):
226
  image_list = [image]
227
  current_image = image
228
 
229
  for _ in progress.tqdm(range(num_iterations), desc="Generating frames"):
230
  # Generate new image
231
+ for step_result in infer(current_image, width, height, overlap_width, num_inference_steps,
232
+ resize_option, custom_resize_size, prompt_input, alignment):
233
  pass # Process all steps
234
 
235
  new_image = step_result[1] # Get the final image from the last step
236
+
237
+ # Interpolate between current_image and new_image
238
+ interpolated_frames = interpolate_frames(current_image, new_image, num_interpolation_frames)
239
+ image_list.extend(interpolated_frames)
240
 
241
  # Use new image as input for next iteration
242
  current_image = new_image
243
 
 
244
  # Create video from image list
245
+ video_path = create_video_from_images(image_list, fps)
246
  return video_path
247
 
248
  loop_outpainting.zerogpu = True
249
 
250
+ def clear_result():
251
+ """Clears the result ImageSlider."""
252
+ return gr.update(value=None)
253
+
254
+ def preload_presets(target_ratio, ui_width, ui_height):
255
+ """Updates the width and height sliders based on the selected aspect ratio."""
256
+ if target_ratio == "9:16":
257
+ changed_width = 720
258
+ changed_height = 1280
259
+ return changed_width, changed_height, gr.update(open=False)
260
+ elif target_ratio == "16:9":
261
+ changed_width = 1280
262
+ changed_height = 720
263
+ return changed_width, changed_height, gr.update(open=False)
264
+ elif target_ratio == "1:1":
265
+ changed_width = 1024
266
+ changed_height = 1024
267
+ return changed_width, changed_height, gr.update(open=False)
268
+ elif target_ratio == "Custom":
269
+ return ui_width, ui_height, gr.update(open=True)
270
+
271
+ def select_the_right_preset(user_width, user_height):
272
+ if user_width == 720 and user_height == 1280:
273
+ return "9:16"
274
+ elif user_width == 1280 and user_height == 720:
275
+ return "16:9"
276
+ elif user_width == 1024 and user_height == 1024:
277
+ return "1:1"
278
+ else:
279
+ return "Custom"
280
+
281
+ def toggle_custom_resize_slider(resize_option):
282
+ return gr.update(visible=(resize_option == "Custom"))
283
+
284
  css = """
285
  .gradio-container {
286
  width: 1200px !important;
 
363
  with gr.Row():
364
  num_iterations = gr.Slider(label="Number of iterations", minimum=2, maximum=24, step=1, value=18)
365
  fps = gr.Slider(label="fps", minimum=1, maximum=24, value=8)
366
+ with gr.Row():
367
+ num_interpolation_frames = gr.Slider(label="Interpolation frames", minimum=0, maximum=10, step=1, value=5)
368
 
369
  with gr.Column():
370
  result = ImageSlider(
 
374
  )
375
  use_as_input_button = gr.Button("Use as Input Image", visible=False)
376
  video_output = gr.Video(label="Outpainting Video")
377
+
378
  gr.Examples(
379
  examples=["hide.png", "disaster.png"],
380
  fn=loop_outpainting,
 
382
  outputs=video_output,
383
  cache_examples="lazy"
384
  )
385
+
386
  def use_output_as_input(output_image):
387
  """Sets the generated output as the new input image."""
388
  return gr.update(value=output_image[1])
 
454
  loop_button.click(
455
  fn=loop_outpainting,
456
  inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
457
+ resize_option, custom_resize_size, prompt_input, alignment_dropdown,
458
+ num_iterations, fps, num_interpolation_frames],
459
  outputs=video_output,
460
  )
461