tedlasai commited on
Commit
5af6596
·
1 Parent(s): 9a4a4a1

autoplay:

Browse files
Files changed (1) hide show
  1. app.py +34 -13
app.py CHANGED
@@ -1,4 +1,3 @@
1
- import os
2
  import spaces
3
  from pathlib import Path
4
  import argparse
@@ -21,7 +20,8 @@ pipe, device = load_model(args)
21
  OUTPUT_DIR = Path("/tmp/output_stacks")
22
  OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
23
 
24
- NUM_FRAMES = 9 # frame_0.png ... frame_8.png
 
25
 
26
  @spaces.GPU(timeout=300, duration=80)
27
  def generate_vstack_from_image(image: Image.Image, input_focal_position: int, num_inference_steps: int):
@@ -35,20 +35,14 @@ def generate_vstack_from_image(image: Image.Image, input_focal_position: int, nu
35
  batch = convert_to_batch(image, input_focal_position=input_focal_position)
36
  output_frames, focal_stack_num = inference_on_image(args, batch, pipe, device)
37
 
38
- write_output(
39
- OUTPUT_DIR,
40
- output_frames,
41
- focal_stack_num,
42
- batch["icc_profile"],
43
- )
44
 
45
- # Show first frame immediately
46
  first_frame = OUTPUT_DIR / "frame_0.png"
47
  if not first_frame.exists():
48
  raise gr.Error("frame_0.png not found in output_dir")
49
 
50
- return str(first_frame)
51
-
52
 
53
  def show_frame(idx: int):
54
  path = OUTPUT_DIR / f"frame_{idx}.png"
@@ -56,12 +50,25 @@ def show_frame(idx: int):
56
  return None
57
  return str(path)
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  with gr.Blocks(css="footer {visibility: hidden}") as demo:
61
  gr.Markdown(
62
  """
63
  # 🖼️ ➜ 🎬 Generate Focal Stacks from a Single Image
64
- Generate a focal stack and scrub through frames using the slider.
65
  """
66
  )
67
 
@@ -83,8 +90,11 @@ with gr.Blocks(css="footer {visibility: hidden}") as demo:
83
  maximum=25,
84
  step=1,
85
  value=25,
 
86
  )
87
 
 
 
88
  generate_btn = gr.Button("Generate stack", variant="primary")
89
 
90
  with gr.Column():
@@ -98,17 +108,28 @@ with gr.Blocks(css="footer {visibility: hidden}") as demo:
98
  label="Focal plane",
99
  )
100
 
 
101
  generate_btn.click(
102
  fn=generate_vstack_from_image,
103
  inputs=[image_in, input_focal_position, num_inference_steps],
104
- outputs=frame_view,
 
105
  )
106
 
 
107
  frame_slider.change(
108
  fn=show_frame,
109
  inputs=frame_slider,
110
  outputs=frame_view,
111
  )
112
 
 
 
 
 
 
 
 
 
113
  if __name__ == "__main__":
114
  demo.launch()
 
 
1
  import spaces
2
  from pathlib import Path
3
  import argparse
 
20
  OUTPUT_DIR = Path("/tmp/output_stacks")
21
  OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
22
 
23
+ NUM_FRAMES = 9 # frame_0.png ... frame_8.png
24
+ LOOP_MS = 300 # autoplay speed (ms)
25
 
26
  @spaces.GPU(timeout=300, duration=80)
27
  def generate_vstack_from_image(image: Image.Image, input_focal_position: int, num_inference_steps: int):
 
35
  batch = convert_to_batch(image, input_focal_position=input_focal_position)
36
  output_frames, focal_stack_num = inference_on_image(args, batch, pipe, device)
37
 
38
+ write_output(OUTPUT_DIR, output_frames, focal_stack_num, batch["icc_profile"])
 
 
 
 
 
39
 
 
40
  first_frame = OUTPUT_DIR / "frame_0.png"
41
  if not first_frame.exists():
42
  raise gr.Error("frame_0.png not found in output_dir")
43
 
44
+ # show first frame + reset slider to 0
45
+ return str(first_frame), gr.update(value=0)
46
 
47
  def show_frame(idx: int):
48
  path = OUTPUT_DIR / f"frame_{idx}.png"
 
50
  return None
51
  return str(path)
52
 
53
+ def advance_frame(idx: int, autoplay: bool):
54
+ # If autoplay is off, don't change anything.
55
+ if not autoplay:
56
+ # keep slider value, keep image (returning None keeps the current image)
57
+ return gr.update(value=int(idx)), gr.update()
58
+
59
+ next_idx = (int(idx) + 1) % NUM_FRAMES
60
+ next_path = OUTPUT_DIR / f"frame_{next_idx}.png"
61
+ if not next_path.exists():
62
+ # If frames aren't ready yet, hold.
63
+ return gr.update(value=int(idx)), gr.update()
64
+
65
+ return gr.update(value=next_idx), str(next_path)
66
 
67
  with gr.Blocks(css="footer {visibility: hidden}") as demo:
68
  gr.Markdown(
69
  """
70
  # 🖼️ ➜ 🎬 Generate Focal Stacks from a Single Image
71
+ Generate a focal stack and scrub through frames using the slider. Toggle autoplay to loop.
72
  """
73
  )
74
 
 
90
  maximum=25,
91
  step=1,
92
  value=25,
93
+ info="More steps = better quality but slower",
94
  )
95
 
96
+ autoplay = gr.Checkbox(value=True, label="Autoplay")
97
+
98
  generate_btn = gr.Button("Generate stack", variant="primary")
99
 
100
  with gr.Column():
 
108
  label="Focal plane",
109
  )
110
 
111
+ # Generate outputs + reset slider
112
  generate_btn.click(
113
  fn=generate_vstack_from_image,
114
  inputs=[image_in, input_focal_position, num_inference_steps],
115
+ outputs=[frame_view, frame_slider],
116
+ api_name="predict",
117
  )
118
 
119
+ # Manual scrubbing
120
  frame_slider.change(
121
  fn=show_frame,
122
  inputs=frame_slider,
123
  outputs=frame_view,
124
  )
125
 
126
+ # Autoplay loop (can be toggled off via checkbox)
127
+ timer = gr.Timer(LOOP_MS)
128
+ timer.tick(
129
+ fn=advance_frame,
130
+ inputs=[frame_slider, autoplay],
131
+ outputs=[frame_slider, frame_view],
132
+ )
133
+
134
  if __name__ == "__main__":
135
  demo.launch()