Update pipeline/video_pipeline.py
Browse files- pipeline/video_pipeline.py +35 -19
pipeline/video_pipeline.py
CHANGED
|
@@ -82,7 +82,7 @@ def generate_mask_from_video_first_frame(video_path, sam2_predictor):
|
|
| 82 |
return best_mask.astype(np.uint8) * 255
|
| 83 |
|
| 84 |
except Exception as e:
|
| 85 |
-
logger.error(f"Failed to generate mask: {e}")
|
| 86 |
return None
|
| 87 |
|
| 88 |
# ============================================================================
|
|
@@ -107,7 +107,7 @@ def smooth_alpha_video(alpha_video_path, output_path, window_size=5):
|
|
| 107 |
Returns:
|
| 108 |
Path to smoothed alpha video
|
| 109 |
"""
|
| 110 |
-
logger.info(f"
|
| 111 |
|
| 112 |
try:
|
| 113 |
cap = cv2.VideoCapture(alpha_video_path)
|
|
@@ -148,7 +148,7 @@ def smooth_alpha_video(alpha_video_path, output_path, window_size=5):
|
|
| 148 |
cap.release()
|
| 149 |
out.release()
|
| 150 |
|
| 151 |
-
logger.info(f"
|
| 152 |
return output_path
|
| 153 |
|
| 154 |
except Exception as e:
|
|
@@ -231,12 +231,12 @@ def stage1_create_transparent_video(input_file):
|
|
| 231 |
3. Apply temporal smoothing to alpha channel (FIXES SHAKING)
|
| 232 |
4. Create transparent .mov file
|
| 233 |
"""
|
| 234 |
-
logger.info("
|
| 235 |
|
| 236 |
# Check memory
|
| 237 |
memory_info = get_memory_usage()
|
| 238 |
if memory_info.get('gpu_free', 0) < 2.0:
|
| 239 |
-
st.warning("
|
| 240 |
clear_model_cache()
|
| 241 |
|
| 242 |
try:
|
|
@@ -252,15 +252,31 @@ def update_progress(progress, message):
|
|
| 252 |
|
| 253 |
# Load models
|
| 254 |
update_progress(0.05, "Loading SAM2 model...")
|
| 255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
if sam2_predictor is None:
|
| 257 |
-
st.error("
|
| 258 |
return None
|
| 259 |
|
| 260 |
update_progress(0.1, "Loading MatAnyone model...")
|
| 261 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
if matanyone_processor is None:
|
| 263 |
-
st.error("
|
| 264 |
return None
|
| 265 |
|
| 266 |
# Process video
|
|
@@ -279,7 +295,7 @@ def update_progress(progress, message):
|
|
| 279 |
mask = generate_mask_from_video_first_frame(input_path, sam2_predictor)
|
| 280 |
|
| 281 |
if mask is None:
|
| 282 |
-
st.error("
|
| 283 |
return None
|
| 284 |
|
| 285 |
mask_path = str(temp_dir / "mask.png")
|
|
@@ -300,13 +316,13 @@ def update_progress(progress, message):
|
|
| 300 |
|
| 301 |
logger.info(f"MatAnyone complete - Foreground: {foreground_path}, Alpha: {alpha_path}")
|
| 302 |
|
| 303 |
-
#
|
| 304 |
update_progress(0.6, "Applying temporal smoothing to eliminate jitter...")
|
| 305 |
|
| 306 |
smoothed_alpha_path = str(temp_dir / "alpha_smoothed.mp4")
|
| 307 |
alpha_path = smooth_alpha_video(alpha_path, smoothed_alpha_path, window_size=5)
|
| 308 |
|
| 309 |
-
logger.info("
|
| 310 |
|
| 311 |
update_progress(0.8, "Creating transparent .mov file...")
|
| 312 |
|
|
@@ -318,21 +334,21 @@ def update_progress(progress, message):
|
|
| 318 |
persist_path = TMP_DIR / "transparent_video.mov"
|
| 319 |
shutil.copyfile(transparent_path, persist_path)
|
| 320 |
|
| 321 |
-
update_progress(1.0, "
|
| 322 |
time.sleep(0.5)
|
| 323 |
return str(persist_path)
|
| 324 |
else:
|
| 325 |
-
st.error("
|
| 326 |
return None
|
| 327 |
|
| 328 |
except Exception as e:
|
| 329 |
logger.error(f"MatAnyone processing failed: {e}", exc_info=True)
|
| 330 |
-
st.error(f"
|
| 331 |
return None
|
| 332 |
|
| 333 |
except Exception as e:
|
| 334 |
logger.error(f"Stage 1 error: {e}", exc_info=True)
|
| 335 |
-
st.error(f"
|
| 336 |
|
| 337 |
# Show memory info for debugging
|
| 338 |
try:
|
|
@@ -359,7 +375,7 @@ def stage2_composite_background(transparent_video_path, background, bg_type):
|
|
| 359 |
STAGE 2: Composite transparent video with new background.
|
| 360 |
Fast compositing that can be repeated with different backgrounds.
|
| 361 |
"""
|
| 362 |
-
logger.info("
|
| 363 |
|
| 364 |
try:
|
| 365 |
progress_bar = st.progress(0)
|
|
@@ -457,7 +473,7 @@ def update_progress(progress, message):
|
|
| 457 |
persist_path = TMP_DIR / "final_video.mp4"
|
| 458 |
shutil.copyfile(output_path, persist_path)
|
| 459 |
|
| 460 |
-
update_progress(1.0, "
|
| 461 |
time.sleep(0.5)
|
| 462 |
return str(persist_path)
|
| 463 |
else:
|
|
@@ -465,5 +481,5 @@ def update_progress(progress, message):
|
|
| 465 |
|
| 466 |
except Exception as e:
|
| 467 |
logger.error(f"Stage 2 error: {e}", exc_info=True)
|
| 468 |
-
st.error(f"
|
| 469 |
return None
|
|
|
|
| 82 |
return best_mask.astype(np.uint8) * 255
|
| 83 |
|
| 84 |
except Exception as e:
|
| 85 |
+
logger.error(f"Failed to generate mask: {e}", exc_info=True)
|
| 86 |
return None
|
| 87 |
|
| 88 |
# ============================================================================
|
|
|
|
| 107 |
Returns:
|
| 108 |
Path to smoothed alpha video
|
| 109 |
"""
|
| 110 |
+
logger.info(f"Applying temporal smoothing to reduce jitter (window={window_size})")
|
| 111 |
|
| 112 |
try:
|
| 113 |
cap = cv2.VideoCapture(alpha_video_path)
|
|
|
|
| 148 |
cap.release()
|
| 149 |
out.release()
|
| 150 |
|
| 151 |
+
logger.info(f"Temporal smoothing complete: {frame_count} frames processed")
|
| 152 |
return output_path
|
| 153 |
|
| 154 |
except Exception as e:
|
|
|
|
| 231 |
3. Apply temporal smoothing to alpha channel (FIXES SHAKING)
|
| 232 |
4. Create transparent .mov file
|
| 233 |
"""
|
| 234 |
+
logger.info("Starting Stage 1: Create transparent video")
|
| 235 |
|
| 236 |
# Check memory
|
| 237 |
memory_info = get_memory_usage()
|
| 238 |
if memory_info.get('gpu_free', 0) < 2.0:
|
| 239 |
+
st.warning("Low GPU memory detected. Processing may be slower.")
|
| 240 |
clear_model_cache()
|
| 241 |
|
| 242 |
try:
|
|
|
|
| 252 |
|
| 253 |
# Load models
|
| 254 |
update_progress(0.05, "Loading SAM2 model...")
|
| 255 |
+
sam2_result = load_sam2_predictor()
|
| 256 |
+
|
| 257 |
+
# Handle tuple return from load_sam2_predictor
|
| 258 |
+
if isinstance(sam2_result, tuple):
|
| 259 |
+
sam2_predictor = sam2_result[0]
|
| 260 |
+
logger.info("Extracted predictor from tuple")
|
| 261 |
+
else:
|
| 262 |
+
sam2_predictor = sam2_result
|
| 263 |
+
|
| 264 |
if sam2_predictor is None:
|
| 265 |
+
st.error("Failed to load SAM2 model")
|
| 266 |
return None
|
| 267 |
|
| 268 |
update_progress(0.1, "Loading MatAnyone model...")
|
| 269 |
+
matanyone_result = load_matanyone_processor()
|
| 270 |
+
|
| 271 |
+
# Handle tuple return from load_matanyone_processor
|
| 272 |
+
if isinstance(matanyone_result, tuple):
|
| 273 |
+
matanyone_processor = matanyone_result[0]
|
| 274 |
+
logger.info("Extracted processor from tuple")
|
| 275 |
+
else:
|
| 276 |
+
matanyone_processor = matanyone_result
|
| 277 |
+
|
| 278 |
if matanyone_processor is None:
|
| 279 |
+
st.error("Failed to load MatAnyone model")
|
| 280 |
return None
|
| 281 |
|
| 282 |
# Process video
|
|
|
|
| 295 |
mask = generate_mask_from_video_first_frame(input_path, sam2_predictor)
|
| 296 |
|
| 297 |
if mask is None:
|
| 298 |
+
st.error("Failed to generate mask")
|
| 299 |
return None
|
| 300 |
|
| 301 |
mask_path = str(temp_dir / "mask.png")
|
|
|
|
| 316 |
|
| 317 |
logger.info(f"MatAnyone complete - Foreground: {foreground_path}, Alpha: {alpha_path}")
|
| 318 |
|
| 319 |
+
# Apply temporal smoothing to alpha channel
|
| 320 |
update_progress(0.6, "Applying temporal smoothing to eliminate jitter...")
|
| 321 |
|
| 322 |
smoothed_alpha_path = str(temp_dir / "alpha_smoothed.mp4")
|
| 323 |
alpha_path = smooth_alpha_video(alpha_path, smoothed_alpha_path, window_size=5)
|
| 324 |
|
| 325 |
+
logger.info("Temporal smoothing applied - shaking should be eliminated")
|
| 326 |
|
| 327 |
update_progress(0.8, "Creating transparent .mov file...")
|
| 328 |
|
|
|
|
| 334 |
persist_path = TMP_DIR / "transparent_video.mov"
|
| 335 |
shutil.copyfile(transparent_path, persist_path)
|
| 336 |
|
| 337 |
+
update_progress(1.0, "Transparent video created successfully")
|
| 338 |
time.sleep(0.5)
|
| 339 |
return str(persist_path)
|
| 340 |
else:
|
| 341 |
+
st.error("Failed to create transparent video")
|
| 342 |
return None
|
| 343 |
|
| 344 |
except Exception as e:
|
| 345 |
logger.error(f"MatAnyone processing failed: {e}", exc_info=True)
|
| 346 |
+
st.error(f"MatAnyone processing failed: {e}")
|
| 347 |
return None
|
| 348 |
|
| 349 |
except Exception as e:
|
| 350 |
logger.error(f"Stage 1 error: {e}", exc_info=True)
|
| 351 |
+
st.error(f"Stage 1 failed: {e}")
|
| 352 |
|
| 353 |
# Show memory info for debugging
|
| 354 |
try:
|
|
|
|
| 375 |
STAGE 2: Composite transparent video with new background.
|
| 376 |
Fast compositing that can be repeated with different backgrounds.
|
| 377 |
"""
|
| 378 |
+
logger.info("Starting Stage 2: Composite with background")
|
| 379 |
|
| 380 |
try:
|
| 381 |
progress_bar = st.progress(0)
|
|
|
|
| 473 |
persist_path = TMP_DIR / "final_video.mp4"
|
| 474 |
shutil.copyfile(output_path, persist_path)
|
| 475 |
|
| 476 |
+
update_progress(1.0, "Compositing complete")
|
| 477 |
time.sleep(0.5)
|
| 478 |
return str(persist_path)
|
| 479 |
else:
|
|
|
|
| 481 |
|
| 482 |
except Exception as e:
|
| 483 |
logger.error(f"Stage 2 error: {e}", exc_info=True)
|
| 484 |
+
st.error(f"Stage 2 failed: {e}")
|
| 485 |
return None
|