Does it work for you?

#6
by federic29 - opened
README.md CHANGED
@@ -4,10 +4,10 @@ emoji: 👨‍🎨
4
  colorFrom: blue
5
  colorTo: red
6
  sdk: gradio
7
- sdk_version: 6.6.0
8
  app_file: web-demos/hugging_face/app.py
9
  pinned: false
10
  license: apache-2.0
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
4
  colorFrom: blue
5
  colorTo: red
6
  sdk: gradio
7
+ sdk_version: 3.50.2
8
  app_file: web-demos/hugging_face/app.py
9
  pinned: false
10
  license: apache-2.0
11
  ---
12
 
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
requirements.txt CHANGED
@@ -6,6 +6,8 @@ numpy
6
  scipy
7
  matplotlib
8
  scikit-image
 
 
9
  imageio-ffmpeg
10
  pyyaml
11
  requests
@@ -17,9 +19,14 @@ gitpython
17
  git+https://github.com/cheind/py-thin-plate-spline
18
  hickle
19
  tensorboard
 
20
  git+https://github.com/facebookresearch/segment-anything.git
 
21
  opencv-python
 
 
 
22
  openmim
23
  tqdm
24
  psutil
25
- omegaconf
 
6
  scipy
7
  matplotlib
8
  scikit-image
9
+ torch>=1.7.1
10
+ torchvision>=0.8.2
11
  imageio-ffmpeg
12
  pyyaml
13
  requests
 
19
  git+https://github.com/cheind/py-thin-plate-spline
20
  hickle
21
  tensorboard
22
+ numpy
23
  git+https://github.com/facebookresearch/segment-anything.git
24
+ gradio
25
  opencv-python
26
+ matplotlib
27
+ pyyaml
28
+ av
29
  openmim
30
  tqdm
31
  psutil
32
+ omegaconf
web-demos/hugging_face/app.py CHANGED
@@ -12,8 +12,6 @@ import torch
12
  import torchvision
13
  import numpy as np
14
  import gradio as gr
15
- import spaces
16
- import av
17
 
18
  from tools.painter import mask_painter
19
  from track_anything import TrackingAnything
@@ -62,7 +60,6 @@ def get_prompt(click_state, click_input):
62
  return prompt
63
 
64
  # extract frames from upload video
65
- @spaces.GPU
66
  def get_frames_from_video(video_input, video_state):
67
  """
68
  Args:
@@ -139,7 +136,6 @@ def get_frames_from_video(video_input, video_state):
139
  gr.update(visible=True, value=operation_log), gr.update(visible=status_ok, value=operation_log)
140
 
141
  # get the select frame from gradio slider
142
- @spaces.GPU
143
  def select_template(image_selection_slider, video_state, interactive_state, mask_dropdown):
144
 
145
  # images = video_state[1]
@@ -163,25 +159,6 @@ def get_end_number(track_pause_number_slider, video_state, interactive_state):
163
  return video_state["painted_images"][track_pause_number_slider],interactive_state, operation_log, operation_log
164
 
165
  # use sam to get the mask
166
- @spaces.GPU
167
- def _sam_refine_gpu(video_state, point_prompt, click_state, interactive_state, coordinate):
168
- # prompt for sam model
169
- model.samcontroler.sam_controler.reset_image()
170
- model.samcontroler.sam_controler.set_image(video_state["origin_images"][video_state["select_frame_number"]])
171
- prompt = get_prompt(click_state=click_state, click_input=coordinate)
172
-
173
- mask, logit, painted_image = model.first_frame_click(
174
- image=video_state["origin_images"][video_state["select_frame_number"]],
175
- points=np.array(prompt["input_point"]),
176
- labels=np.array(prompt["input_label"]),
177
- multimask=prompt["multimask_output"],
178
- )
179
- video_state["masks"][video_state["select_frame_number"]] = mask
180
- video_state["logits"][video_state["select_frame_number"]] = logit
181
- video_state["painted_images"][video_state["select_frame_number"]] = painted_image
182
- return painted_image, video_state, interactive_state
183
-
184
-
185
  def sam_refine(video_state, point_prompt, click_state, interactive_state, evt:gr.SelectData):
186
  """
187
  Args:
@@ -189,18 +166,27 @@ def sam_refine(video_state, point_prompt, click_state, interactive_state, evt:gr
189
  point_prompt: flag for positive or negative button click
190
  click_state: [[points], [labels]]
191
  """
192
- # Extract the click coordinate here (outside @spaces.GPU) because
193
- # gr.SelectData does not pickle across the ZeroGPU fork boundary.
194
  if point_prompt == "Positive":
195
  coordinate = "[[{},{},1]]".format(evt.index[0], evt.index[1])
196
  interactive_state["positive_click_times"] += 1
197
  else:
198
  coordinate = "[[{},{},0]]".format(evt.index[0], evt.index[1])
199
  interactive_state["negative_click_times"] += 1
 
 
 
 
 
200
 
201
- painted_image, video_state, interactive_state = _sam_refine_gpu(
202
- video_state, point_prompt, click_state, interactive_state, coordinate
203
- )
 
 
 
 
 
 
204
 
205
  operation_log = [("[Must Do]", "Add mask"), (": add the current displayed mask for video segmentation.\n", None),
206
  ("[Optional]", "Remove mask"), (": remove all added masks.\n", None),
@@ -245,20 +231,6 @@ def show_mask(video_state, interactive_state, mask_dropdown):
245
  return select_frame, operation_log, operation_log
246
 
247
  # tracking vos
248
- def _tracking_duration(video_state, interactive_state, mask_dropdown):
249
- try:
250
- origin = video_state.get("origin_images") if isinstance(video_state, dict) else None
251
- start = video_state.get("select_frame_number", 0) if isinstance(video_state, dict) else 0
252
- end = interactive_state.get("track_end_number") if isinstance(interactive_state, dict) else None
253
- total = len(origin) if origin is not None else 60
254
- n = (end if end else total) - start
255
- n = max(1, int(n))
256
- except Exception:
257
- n = 60
258
- return min(300, max(60, int(0.4 * n + 30)))
259
-
260
-
261
- @spaces.GPU(duration=_tracking_duration)
262
  def vos_tracking_video(video_state, interactive_state, mask_dropdown):
263
  operation_log = [("",""), ("Tracking finished! Try to click the Inpainting button to get the inpainting result.","Normal")]
264
  model.cutie.clear_memory()
@@ -319,18 +291,7 @@ def vos_tracking_video(video_state, interactive_state, mask_dropdown):
319
  #### shanggao code for mask save
320
  return video_output, video_state, interactive_state, operation_log, operation_log
321
 
322
- # inpaint
323
- def _inpaint_duration(video_state, resize_ratio_number, dilate_radius_number, raft_iter_number, subvideo_length_number, neighbor_length_number, ref_stride_number, mask_dropdown):
324
- try:
325
- origin = video_state.get("origin_images") if isinstance(video_state, dict) else None
326
- n = len(origin) if origin is not None else 60
327
- ratio = float(resize_ratio_number) if resize_ratio_number else 1.0
328
- except Exception:
329
- n, ratio = 60, 1.0
330
- return min(420, max(90, int(n * ratio * 1.3 + 45)))
331
-
332
-
333
- @spaces.GPU(duration=_inpaint_duration)
334
  def inpaint_video(video_state, resize_ratio_number, dilate_radius_number, raft_iter_number, subvideo_length_number, neighbor_length_number, ref_stride_number, mask_dropdown):
335
  operation_log = [("",""), ("Inpainting finished!","Normal")]
336
 
@@ -368,42 +329,16 @@ def inpaint_video(video_state, resize_ratio_number, dilate_radius_number, raft_i
368
  def generate_video_from_frames(frames, output_path, fps=30):
369
  """
370
  Generates a video from a list of frames.
371
-
372
  Args:
373
  frames (list of numpy arrays): The frames to include in the video.
374
  output_path (str): The path to save the generated video.
375
  fps (int, optional): The frame rate of the output video. Defaults to 30.
376
  """
377
- frames = np.asarray(frames)
378
- if frames.ndim != 4:
379
- raise ValueError(f"Expected frames of shape (T, H, W, 3); got {frames.shape}")
380
  if not os.path.exists(os.path.dirname(output_path)):
381
  os.makedirs(os.path.dirname(output_path))
382
-
383
- # torchvision.io.write_video was removed in newer torchvision; encode via PyAV.
384
- height, width = frames.shape[1], frames.shape[2]
385
- # libx264 requires even dimensions.
386
- pad_h = height % 2
387
- pad_w = width % 2
388
- if pad_h or pad_w:
389
- frames = np.pad(frames, ((0, 0), (0, pad_h), (0, pad_w), (0, 0)), mode="edge")
390
- height += pad_h
391
- width += pad_w
392
-
393
- container = av.open(output_path, mode="w")
394
- try:
395
- stream = container.add_stream("libx264", rate=int(round(fps)) or 1)
396
- stream.width = width
397
- stream.height = height
398
- stream.pix_fmt = "yuv420p"
399
- for img in frames:
400
- frame = av.VideoFrame.from_ndarray(np.ascontiguousarray(img.astype(np.uint8)), format="rgb24")
401
- for packet in stream.encode(frame):
402
- container.mux(packet)
403
- for packet in stream.encode():
404
- container.mux(packet)
405
- finally:
406
- container.close()
407
  return output_path
408
 
409
  def restart():
@@ -619,7 +554,7 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as iface:
619
  visible=False,
620
  min_width=100,
621
  scale=1,)
622
- with gr.Row(elem_classes="mask_button_group"):
623
  Add_mask_button = gr.Button(value="Add mask", interactive=True, visible=False, elem_classes="add_button")
624
  remove_mask_button = gr.Button(value="Remove mask", interactive=True, visible=False, elem_classes="remove_button")
625
  clear_button_click = gr.Button(value="Clear clicks", interactive=True, visible=False, elem_classes="clear_button")
@@ -741,5 +676,5 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as iface:
741
  )
742
  gr.Markdown(article)
743
 
744
- iface.queue()
745
  iface.launch(debug=True)
 
12
  import torchvision
13
  import numpy as np
14
  import gradio as gr
 
 
15
 
16
  from tools.painter import mask_painter
17
  from track_anything import TrackingAnything
 
60
  return prompt
61
 
62
  # extract frames from upload video
 
63
  def get_frames_from_video(video_input, video_state):
64
  """
65
  Args:
 
136
  gr.update(visible=True, value=operation_log), gr.update(visible=status_ok, value=operation_log)
137
 
138
  # get the select frame from gradio slider
 
139
  def select_template(image_selection_slider, video_state, interactive_state, mask_dropdown):
140
 
141
  # images = video_state[1]
 
159
  return video_state["painted_images"][track_pause_number_slider],interactive_state, operation_log, operation_log
160
 
161
  # use sam to get the mask
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  def sam_refine(video_state, point_prompt, click_state, interactive_state, evt:gr.SelectData):
163
  """
164
  Args:
 
166
  point_prompt: flag for positive or negative button click
167
  click_state: [[points], [labels]]
168
  """
 
 
169
  if point_prompt == "Positive":
170
  coordinate = "[[{},{},1]]".format(evt.index[0], evt.index[1])
171
  interactive_state["positive_click_times"] += 1
172
  else:
173
  coordinate = "[[{},{},0]]".format(evt.index[0], evt.index[1])
174
  interactive_state["negative_click_times"] += 1
175
+
176
+ # prompt for sam model
177
+ model.samcontroler.sam_controler.reset_image()
178
+ model.samcontroler.sam_controler.set_image(video_state["origin_images"][video_state["select_frame_number"]])
179
+ prompt = get_prompt(click_state=click_state, click_input=coordinate)
180
 
181
+ mask, logit, painted_image = model.first_frame_click(
182
+ image=video_state["origin_images"][video_state["select_frame_number"]],
183
+ points=np.array(prompt["input_point"]),
184
+ labels=np.array(prompt["input_label"]),
185
+ multimask=prompt["multimask_output"],
186
+ )
187
+ video_state["masks"][video_state["select_frame_number"]] = mask
188
+ video_state["logits"][video_state["select_frame_number"]] = logit
189
+ video_state["painted_images"][video_state["select_frame_number"]] = painted_image
190
 
191
  operation_log = [("[Must Do]", "Add mask"), (": add the current displayed mask for video segmentation.\n", None),
192
  ("[Optional]", "Remove mask"), (": remove all added masks.\n", None),
 
231
  return select_frame, operation_log, operation_log
232
 
233
  # tracking vos
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  def vos_tracking_video(video_state, interactive_state, mask_dropdown):
235
  operation_log = [("",""), ("Tracking finished! Try to click the Inpainting button to get the inpainting result.","Normal")]
236
  model.cutie.clear_memory()
 
291
  #### shanggao code for mask save
292
  return video_output, video_state, interactive_state, operation_log, operation_log
293
 
294
+ # inpaint
 
 
 
 
 
 
 
 
 
 
 
295
  def inpaint_video(video_state, resize_ratio_number, dilate_radius_number, raft_iter_number, subvideo_length_number, neighbor_length_number, ref_stride_number, mask_dropdown):
296
  operation_log = [("",""), ("Inpainting finished!","Normal")]
297
 
 
329
  def generate_video_from_frames(frames, output_path, fps=30):
330
  """
331
  Generates a video from a list of frames.
332
+
333
  Args:
334
  frames (list of numpy arrays): The frames to include in the video.
335
  output_path (str): The path to save the generated video.
336
  fps (int, optional): The frame rate of the output video. Defaults to 30.
337
  """
338
+ frames = torch.from_numpy(np.asarray(frames))
 
 
339
  if not os.path.exists(os.path.dirname(output_path)):
340
  os.makedirs(os.path.dirname(output_path))
341
+ torchvision.io.write_video(output_path, frames, fps=fps, video_codec="libx264")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  return output_path
343
 
344
  def restart():
 
554
  visible=False,
555
  min_width=100,
556
  scale=1,)
557
+ with gr.Row(scale=2, elem_classes="mask_button_group"):
558
  Add_mask_button = gr.Button(value="Add mask", interactive=True, visible=False, elem_classes="add_button")
559
  remove_mask_button = gr.Button(value="Remove mask", interactive=True, visible=False, elem_classes="remove_button")
560
  clear_button_click = gr.Button(value="Clear clicks", interactive=True, visible=False, elem_classes="clear_button")
 
676
  )
677
  gr.Markdown(article)
678
 
679
+ iface.queue(concurrency_count=1)
680
  iface.launch(debug=True)
web-demos/hugging_face/requirements.txt CHANGED
@@ -6,6 +6,7 @@ hickle
6
  tensorboard
7
  numpy
8
  git+https://github.com/facebookresearch/segment-anything.git
 
9
  opencv-python
10
  matplotlib
11
  pyyaml
 
6
  tensorboard
7
  numpy
8
  git+https://github.com/facebookresearch/segment-anything.git
9
+ gradio
10
  opencv-python
11
  matplotlib
12
  pyyaml