KingNish commited on
Commit
0f83d78
1 Parent(s): 0791cf5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -97
app.py CHANGED
@@ -13,7 +13,6 @@ import tempfile
13
  import uuid
14
  import schedule
15
  import time
16
- import threading
17
  import shutil
18
 
19
  torch.set_float32_matmul_precision("medium")
@@ -33,116 +32,64 @@ transform_image = transforms.Compose(
33
  )
34
 
35
 
36
- def load_background_image(bg, image_size):
37
- """Loads and resizes the background image based on the provided input."""
38
- try:
39
- if isinstance(bg, str) and bg.startswith("#"):
40
- color_rgb = tuple(int(bg[i:i+2], 16) for i in (1, 3, 5))
41
- return Image.new("RGBA", image_size, color_rgb + (255,))
42
- elif isinstance(bg, Image.Image):
43
- return bg.convert("RGBA").resize(image_size)
44
- else:
45
- return Image.open(bg).convert("RGBA").resize(image_size)
46
- except Exception as e:
47
- print(f"Error opening background image: {e}")
48
- return None
49
-
50
- def clear_temp_directory():
51
- temp_dir = "temp"
52
- if os.path.exists(temp_dir):
53
- for filename in os.listdir(temp_dir):
54
- file_path = os.path.join(temp_dir, filename)
55
- try:
56
- if os.path.isfile(file_path) or os.path.islink(file_path):
57
- os.unlink(file_path)
58
- elif os.path.isdir(file_path):
59
- shutil.rmtree(file_path)
60
- except Exception as e:
61
- print(f"Failed to delete {file_path}. Reason: {e}")
62
-
63
- def run_scheduler():
64
- schedule.every(10).minutes.do(clear_temp_directory)
65
- while True:
66
- schedule.run_pending()
67
- time.sleep(1)
68
-
69
- # Start the scheduler in a separate thread
70
- scheduler_thread = threading.Thread(target=run_scheduler)
71
- scheduler_thread.daemon = True # Allow the main thread to exit even if the scheduler is running
72
- scheduler_thread.start()
73
-
74
  @spaces.GPU
75
- def process_video(input_video_path, bg_type="Color", bg_image_path=None, bg_video_path=None,
76
- bg_color="#00FF00", output_fps=0, video_handling_mode="slow_down"):
77
- """Processes the input video and replaces the background."""
78
  try:
79
  # Load the video using moviepy
80
- video = mp.VideoFileClip(input_video_path)
81
 
82
  # Load original fps if fps value is equal to 0
83
- if output_fps == 0:
84
- output_fps = video.fps
85
 
86
  # Extract audio from the video
87
  audio = video.audio
88
 
89
  # Extract frames at the specified FPS
90
- frames = video.iter_frames(fps=output_fps)
91
 
92
  # Process each frame for background removal
93
  processed_frames = []
94
- yield gr.update(visible=True), gr.update(visible=False), gr.update(value=0)
95
 
96
  if bg_type == "Video":
97
- background_video = mp.VideoFileClip(bg_video_path)
98
  if background_video.duration < video.duration:
99
- if video_handling_mode == "slow_down":
100
  background_video = background_video.fx(mp.vfx.speedx, factor=video.duration / background_video.duration)
101
- else: # video_handling_mode == "loop"
102
  background_video = mp.concatenate_videoclips([background_video] * int(video.duration / background_video.duration + 1))
103
- background_frames = list(background_video.iter_frames(fps=output_fps)) # Convert to list
104
  else:
105
  background_frames = None
106
 
107
  bg_frame_index = 0 # Initialize background frame index
108
- total_frames = len(list(frames))
109
- frames = video.iter_frames(fps=output_fps)
110
- batch_size = 4
111
-
112
- for i in range(0, total_frames, batch_size):
113
- batch_frames = list(frames)[i:i+batch_size]
114
- processed_batch = []
115
- for frame in batch_frames:
116
- pil_image = Image.fromarray(frame)
117
- if bg_type == "Color":
118
- background_image = load_background_image(bg_color, pil_image.size)
119
- elif bg_type == "Image":
120
- background_image = load_background_image(bg_image_path, pil_image.size)
121
- elif bg_type == "Video":
122
- if video_handling_mode == "slow_down":
123
- background_frame = background_frames[bg_frame_index % len(background_frames)]
124
- bg_frame_index += 1
125
- background_image = Image.fromarray(background_frame)
126
- else: # video_handling_mode == "loop"
127
- background_frame = background_frames[bg_frame_index % len(background_frames)]
128
- bg_frame_index += 1
129
- background_image = Image.fromarray(background_frame)
130
- else:
131
- background_image = None # Default to original image if no background is selected
132
-
133
- if background_image is not None:
134
- processed_image = process(pil_image, background_image)
135
- else:
136
- processed_image = pil_image
137
 
138
- processed_batch.append(np.array(processed_image))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- processed_frames.extend(processed_batch)
141
- progress = (i + len(batch_frames)) / total_frames
142
- yield processed_batch[-1], None, gr.update(value=progress) # Update progress bar
143
 
144
  # Create a new video from the processed frames
145
- processed_video = mp.ImageSequenceClip(processed_frames, fps=output_fps)
146
 
147
  # Add the original audio back to the processed video
148
  processed_video = processed_video.set_audio(audio)
@@ -154,15 +101,15 @@ def process_video(input_video_path, bg_type="Color", bg_image_path=None, bg_vide
154
  temp_filepath = os.path.join(temp_dir, unique_filename)
155
  processed_video.write_videofile(temp_filepath, codec="libx264")
156
 
157
- yield gr.update(visible=False), gr.update(visible=True), gr.update(value=1)
158
  # Return the path to the temporary file
159
- yield processed_batch[-1], temp_filepath
160
 
161
  except Exception as e:
162
- error_message = f"Error processing video: {e}"
163
- print(error_message)
164
- yield gr.update(visible=False), gr.update(visible=True), gr.update(value=0)
165
- yield None, error_message
166
 
167
 
168
  def process(image, bg):
@@ -175,11 +122,31 @@ def process(image, bg):
175
  pred_pil = transforms.ToPILImage()(pred)
176
  mask = pred_pil.resize(image_size)
177
 
 
 
 
 
 
 
 
 
178
  # Composite the image onto the background using the mask
179
- image = Image.composite(image, bg, mask)
180
 
181
  return image
182
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  with gr.Blocks(theme=gr.themes.Ocean()) as demo:
185
  gr.Markdown("# Video Background Remover & Changer\n### You can replace image background with any color, image or video.\nNOTE: As this Space is running on ZERO GPU it has limit. It can handle approx 200frmaes at once. So, if you have big video than use small chunks or Duplicate this space.")
@@ -188,7 +155,6 @@ with gr.Blocks(theme=gr.themes.Ocean()) as demo:
188
  stream_image = gr.Image(label="Streaming Output", visible=False)
189
  out_video = gr.Video(label="Final Output Video")
190
  submit_button = gr.Button("Change Background", interactive=True)
191
- progress_bar = gr.ProgressBar(label="Processing Progress")
192
  with gr.Row():
193
  fps_slider = gr.Slider(
194
  minimum=0,
@@ -226,18 +192,24 @@ with gr.Blocks(theme=gr.themes.Ocean()) as demo:
226
  ["rickroll-2sec.mp4", "Color", None, None],
227
  ],
228
  inputs=[in_video, bg_type, bg_image, bg_video],
229
- outputs=[stream_image, out_video, progress_bar],
230
- fn=process_video,
231
  cache_examples=True,
232
  cache_mode="eager",
233
  )
234
 
235
 
236
  submit_button.click(
237
- process_video,
238
  inputs=[in_video, bg_type, bg_image, bg_video, color_picker, fps_slider, video_handling_radio],
239
- outputs=[stream_image, out_video, progress_bar],
240
  )
241
 
242
  if __name__ == "__main__":
 
 
 
 
 
 
243
  demo.launch(show_error=True)
 
13
  import uuid
14
  import schedule
15
  import time
 
16
  import shutil
17
 
18
  torch.set_float32_matmul_precision("medium")
 
32
  )
33
 
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  @spaces.GPU
36
+ def fn(vid, bg_type="Color", bg_image=None, bg_video=None, color="#00FF00", fps=0, video_handling="slow_down"):
 
 
37
  try:
38
  # Load the video using moviepy
39
+ video = mp.VideoFileClip(vid)
40
 
41
  # Load original fps if fps value is equal to 0
42
+ if fps == 0:
43
+ fps = video.fps
44
 
45
  # Extract audio from the video
46
  audio = video.audio
47
 
48
  # Extract frames at the specified FPS
49
+ frames = video.iter_frames(fps=fps)
50
 
51
  # Process each frame for background removal
52
  processed_frames = []
53
+ yield gr.update(visible=True), gr.update(visible=False)
54
 
55
  if bg_type == "Video":
56
+ background_video = mp.VideoFileClip(bg_video)
57
  if background_video.duration < video.duration:
58
+ if video_handling == "slow_down":
59
  background_video = background_video.fx(mp.vfx.speedx, factor=video.duration / background_video.duration)
60
+ else: # video_handling == "loop"
61
  background_video = mp.concatenate_videoclips([background_video] * int(video.duration / background_video.duration + 1))
62
+ background_frames = list(background_video.iter_frames(fps=fps)) # Convert to list
63
  else:
64
  background_frames = None
65
 
66
  bg_frame_index = 0 # Initialize background frame index
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
+ for i, frame in enumerate(frames):
69
+ pil_image = Image.fromarray(frame)
70
+ if bg_type == "Color":
71
+ processed_image = process(pil_image, color)
72
+ elif bg_type == "Image":
73
+ processed_image = process(pil_image, bg_image)
74
+ elif bg_type == "Video":
75
+ if video_handling == "slow_down":
76
+ background_frame = background_frames[bg_frame_index % len(background_frames)]
77
+ bg_frame_index += 1
78
+ background_image = Image.fromarray(background_frame)
79
+ processed_image = process(pil_image, background_image)
80
+ else: # video_handling == "loop"
81
+ background_frame = background_frames[bg_frame_index % len(background_frames)]
82
+ bg_frame_index += 1
83
+ background_image = Image.fromarray(background_frame)
84
+ processed_image = process(pil_image, background_image)
85
+ else:
86
+ processed_image = pil_image # Default to original image if no background is selected
87
 
88
+ processed_frames.append(np.array(processed_image))
89
+ yield processed_image, None
 
90
 
91
  # Create a new video from the processed frames
92
+ processed_video = mp.ImageSequenceClip(processed_frames, fps=fps)
93
 
94
  # Add the original audio back to the processed video
95
  processed_video = processed_video.set_audio(audio)
 
101
  temp_filepath = os.path.join(temp_dir, unique_filename)
102
  processed_video.write_videofile(temp_filepath, codec="libx264")
103
 
104
+ yield gr.update(visible=False), gr.update(visible=True)
105
  # Return the path to the temporary file
106
+ yield processed_image, temp_filepath
107
 
108
  except Exception as e:
109
+ print(f"Error: {e}")
110
+ yield gr.update(visible=False), gr.update(visible=True)
111
+ yield None, f"Error processing video: {e}"
112
+
113
 
114
 
115
  def process(image, bg):
 
122
  pred_pil = transforms.ToPILImage()(pred)
123
  mask = pred_pil.resize(image_size)
124
 
125
+ if isinstance(bg, str) and bg.startswith("#"):
126
+ color_rgb = tuple(int(bg[i:i+2], 16) for i in (1, 3, 5))
127
+ background = Image.new("RGBA", image_size, color_rgb + (255,))
128
+ elif isinstance(bg, Image.Image):
129
+ background = bg.convert("RGBA").resize(image_size)
130
+ else:
131
+ background = Image.open(bg).convert("RGBA").resize(image_size)
132
+
133
  # Composite the image onto the background using the mask
134
+ image = Image.composite(image, background, mask)
135
 
136
  return image
137
 
138
+ def clear_temp_directory():
139
+ temp_dir = "temp"
140
+ for filename in os.listdir(temp_dir):
141
+ file_path = os.path.join(temp_dir, filename)
142
+ try:
143
+ if os.path.isfile(file_path) or os.path.islink(file_path):
144
+ os.unlink(file_path)
145
+ elif os.path.isdir(file_path):
146
+ shutil.rmtree(file_path)
147
+ except Exception as e:
148
+ print('Failed to delete %s. Reason: %s' % (file_path, e)) # Keep this print statement for debugging purposes
149
+
150
 
151
  with gr.Blocks(theme=gr.themes.Ocean()) as demo:
152
  gr.Markdown("# Video Background Remover & Changer\n### You can replace image background with any color, image or video.\nNOTE: As this Space is running on ZERO GPU it has limit. It can handle approx 200frmaes at once. So, if you have big video than use small chunks or Duplicate this space.")
 
155
  stream_image = gr.Image(label="Streaming Output", visible=False)
156
  out_video = gr.Video(label="Final Output Video")
157
  submit_button = gr.Button("Change Background", interactive=True)
 
158
  with gr.Row():
159
  fps_slider = gr.Slider(
160
  minimum=0,
 
192
  ["rickroll-2sec.mp4", "Color", None, None],
193
  ],
194
  inputs=[in_video, bg_type, bg_image, bg_video],
195
+ outputs=[stream_image, out_video],
196
+ fn=fn,
197
  cache_examples=True,
198
  cache_mode="eager",
199
  )
200
 
201
 
202
  submit_button.click(
203
+ fn,
204
  inputs=[in_video, bg_type, bg_image, bg_video, color_picker, fps_slider, video_handling_radio],
205
+ outputs=[stream_image, out_video],
206
  )
207
 
208
  if __name__ == "__main__":
209
+ schedule.every(10).minutes.do(clear_temp_directory)
210
+
211
+ while True:
212
+ schedule.run_pending()
213
+ time.sleep(1)
214
+
215
  demo.launch(show_error=True)