MogensR commited on
Commit
365f9ca
·
verified ·
1 Parent(s): 968b4b5

Update processing/two_stage/two_stage_processor.py

Browse files
processing/two_stage/two_stage_processor.py CHANGED
@@ -235,94 +235,250 @@ def _create_trimap(self, mask_path: str) -> str:
235
 
236
  def _process_video_to_greenscreen(self, video_path: str, trimap_path: str, trim_seconds: float) -> str:
237
  """
238
- Process video to create green screen version.
239
 
240
- KEY: This creates RGB video with GREEN BACKGROUND, not alpha matte.
241
  """
242
 
243
- logger.info("Processing video to green screen format...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
- # Load trimap
246
  trimap = cv2.imread(trimap_path, cv2.IMREAD_GRAYSCALE)
247
  if trimap is None:
248
  raise ValueError(f"Could not load trimap: {trimap_path}")
249
 
250
- # Open input video
251
  cap = cv2.VideoCapture(video_path)
252
  if not cap.isOpened():
253
  raise ValueError(f"Could not open video: {video_path}")
254
 
255
- # Get video properties
256
  fps = cap.get(cv2.CAP_PROP_FPS)
257
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
258
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
259
- total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
260
- target_frames = min(int(trim_seconds * fps), total_frames)
261
 
262
- # Resize trimap to match video
263
  trimap_resized = cv2.resize(trimap, (width, height))
 
264
 
265
- # Create output video writer
266
  green_screen_path = os.path.join(self.temp_dir, "greenscreen_video.mp4")
267
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
268
  out = cv2.VideoWriter(green_screen_path, fourcc, fps, (width, height))
269
 
270
- logger.info(f"Creating green screen video: {target_frames} frames")
271
-
272
  frame_count = 0
273
- while frame_count < target_frames:
274
  ret, frame = cap.read()
275
  if not ret:
276
  break
277
 
278
- try:
279
- # Convert to RGB for MatAnyone
280
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
281
-
282
- # FIXED: Use correct MatAnyone InferenceCore API
283
- try:
284
- # Try different MatAnyone interface methods
285
- if hasattr(self.matanyone_processor, 'process'):
286
- alpha_matte = self.matanyone_processor.process(frame_rgb, trimap_resized)
287
- elif hasattr(self.matanyone_processor, 'predict'):
288
- alpha_matte = self.matanyone_processor.predict(frame_rgb, trimap_resized)
289
- elif hasattr(self.matanyone_processor, '__call__'):
290
- alpha_matte = self.matanyone_processor(frame_rgb, trimap_resized)
291
- else:
292
- # If no known method, try the most common ones
293
- logger.error(f"MatAnyone methods: {[m for m in dir(self.matanyone_processor) if not m.startswith('_')]}")
294
- raise AttributeError("No known MatAnyone processing method found")
295
-
296
- except Exception as matanyone_error:
297
- logger.error(f"MatAnyone processing failed: {matanyone_error}")
298
- # Use trimap as fallback
299
- alpha_matte = (trimap_resized > 128).astype(np.float32)
300
-
301
- if len(alpha_matte.shape) == 3:
302
- alpha_matte = np.mean(alpha_matte, axis=2)
303
-
304
- alpha_matte = np.clip(alpha_matte, 0, 1)
305
-
306
- # Create green screen frame
307
- green_screen_frame = self._create_greenscreen_frame(frame, alpha_matte)
308
-
309
- out.write(green_screen_frame)
310
-
311
- except Exception as e:
312
- logger.error(f"Frame processing failed on frame {frame_count}: {e}")
313
- # Fallback: use trimap
314
- fallback_alpha = (trimap_resized > 128).astype(np.float32)
315
- green_screen_frame = self._create_greenscreen_frame(frame, fallback_alpha)
316
- out.write(green_screen_frame)
317
-
318
  frame_count += 1
319
- if frame_count % 25 == 0:
320
- logger.info(f"Processed {frame_count}/{target_frames} frames")
321
 
322
  cap.release()
323
  out.release()
324
 
325
- logger.info(f"Green screen video created: {green_screen_path}")
326
  return green_screen_path
327
 
328
  def _create_greenscreen_frame(self, original_frame: np.ndarray, alpha_matte: np.ndarray) -> np.ndarray:
 
235
 
236
  def _process_video_to_greenscreen(self, video_path: str, trimap_path: str, trim_seconds: float) -> str:
237
  """
238
+ Process video to create green screen version using robust MatAnyone adapter.
239
 
240
+ Uses the ChatGPT-provided adapter that handles all interface variations.
241
  """
242
 
243
+ logger.info("Processing video with robust MatAnyone adapter...")
244
+
245
+ # Import the adapter (assuming it's in the same module or available)
246
+ from .matanyone_adapter import run_matanyone_with_reference_mask
247
+
248
+ # Trim video first
249
+ cap = cv2.VideoCapture(video_path)
250
+ fps = cap.get(cv2.CAP_PROP_FPS)
251
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
252
+ target_frames = min(int(trim_seconds * fps), total_frames)
253
+ cap.release()
254
+
255
+ # Create trimmed video
256
+ trimmed_video_path = os.path.join(self.temp_dir, "trimmed_for_matanyone.mp4")
257
+ with VideoFileClip(video_path) as clip:
258
+ trimmed_clip = clip.subclip(0, trim_seconds)
259
+ trimmed_clip.write_videofile(
260
+ trimmed_video_path,
261
+ codec='libx264',
262
+ audio_codec='aac',
263
+ verbose=False,
264
+ logger=None
265
+ )
266
+
267
+ # Prepare MatAnyone output directory
268
+ matanyone_output_dir = os.path.join(self.temp_dir, "matanyone_output")
269
+ os.makedirs(matanyone_output_dir, exist_ok=True)
270
+
271
+ try:
272
+ logger.info("Using robust MatAnyone adapter...")
273
+ logger.info(f"Video: {trimmed_video_path}")
274
+ logger.info(f"Trimap: {trimap_path}")
275
+ logger.info(f"Output dir: {matanyone_output_dir}")
276
+
277
+ # Use the robust adapter that handles all interface variations
278
+ alpha_dir = run_matanyone_with_reference_mask(
279
+ inference_core=self.matanyone_processor,
280
+ video_path=trimmed_video_path,
281
+ reference_mask_path=trimap_path,
282
+ output_dir=matanyone_output_dir,
283
+ write_png=True
284
+ )
285
+
286
+ if not alpha_dir or not os.path.exists(alpha_dir):
287
+ raise RuntimeError(f"MatAnyone adapter failed to create alpha directory: {alpha_dir}")
288
+
289
+ # Convert PNG alpha sequence to green screen video
290
+ green_screen_path = self._convert_png_alpha_to_greenscreen(
291
+ trimmed_video_path, alpha_dir
292
+ )
293
+
294
+ logger.info(f"Green screen video created: {green_screen_path}")
295
+ return green_screen_path
296
+
297
+ except Exception as e:
298
+ logger.error(f"MatAnyone adapter failed: {e}")
299
+ logger.error(f"Falling back to SAM2-only green screen...")
300
+
301
+ # Fallback: create green screen using just trimap
302
+ return self._create_sam2_only_greenscreen(trimmed_video_path, trimap_path)
303
+
304
+ def _convert_png_alpha_to_greenscreen(self, original_video_path: str, alpha_dir: str) -> str:
305
+ """Convert PNG alpha sequence to green screen video."""
306
+
307
+ logger.info("Converting PNG alpha sequence to green screen format...")
308
+
309
+ # Get PNG files
310
+ png_files = sorted([f for f in os.listdir(alpha_dir) if f.startswith("alpha_") and f.endswith(".png")])
311
+ if not png_files:
312
+ raise RuntimeError(f"No alpha PNG files found in {alpha_dir}")
313
+
314
+ # Open original video
315
+ original_cap = cv2.VideoCapture(original_video_path)
316
+ if not original_cap.isOpened():
317
+ raise ValueError("Could not open original video for conversion")
318
+
319
+ # Get video properties
320
+ fps = original_cap.get(cv2.CAP_PROP_FPS)
321
+ width = int(original_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
322
+ height = int(original_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
323
+
324
+ # Create output video writer
325
+ green_screen_path = os.path.join(self.temp_dir, "greenscreen_video.mp4")
326
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
327
+ out = cv2.VideoWriter(green_screen_path, fourcc, fps, (width, height))
328
+
329
+ frame_count = 0
330
+ while True:
331
+ ret, original_frame = original_cap.read()
332
+ if not ret:
333
+ break
334
+
335
+ # Load corresponding alpha PNG
336
+ if frame_count < len(png_files):
337
+ alpha_path = os.path.join(alpha_dir, png_files[frame_count])
338
+ alpha_frame = cv2.imread(alpha_path, cv2.IMREAD_GRAYSCALE)
339
+
340
+ if alpha_frame is not None:
341
+ # Resize alpha to match video if needed
342
+ if alpha_frame.shape[:2] != (height, width):
343
+ alpha_frame = cv2.resize(alpha_frame, (width, height))
344
+
345
+ alpha_matte = alpha_frame.astype(np.float32) / 255.0
346
+ else:
347
+ # Fallback alpha if PNG read fails
348
+ alpha_matte = np.ones((height, width), dtype=np.float32)
349
+ else:
350
+ # Use last alpha if we run out of PNG files
351
+ alpha_matte = np.ones((height, width), dtype=np.float32)
352
+
353
+ # Create green screen frame
354
+ green_screen_frame = self._create_greenscreen_frame(original_frame, alpha_matte)
355
+ out.write(green_screen_frame)
356
+
357
+ frame_count += 1
358
+ if frame_count % 25 == 0:
359
+ logger.info(f"Converted {frame_count} frames to green screen")
360
+
361
+ original_cap.release()
362
+ out.release()
363
+
364
+ logger.info(f"PNG alpha to green screen conversion complete: {green_screen_path}")
365
+ return green_screen_path
366
+
367
+ def _find_alpha_video(self, output_dir: str, input_video_path: str) -> Optional[str]:
368
+ """Find the alpha video file created by MatAnyone."""
369
+ input_name = Path(input_video_path).stem
370
+
371
+ patterns = [
372
+ f"{input_name}_pha.mp4",
373
+ f"{input_name}_alpha.mp4",
374
+ "alpha.mp4",
375
+ "output_alpha.mp4",
376
+ "pha.mp4"
377
+ ]
378
+
379
+ for pattern in patterns:
380
+ potential_path = os.path.join(output_dir, pattern)
381
+ if os.path.exists(potential_path):
382
+ return potential_path
383
+
384
+ # Fallback: find any .mp4 file in output directory
385
+ for file in os.listdir(output_dir):
386
+ if file.endswith('.mp4'):
387
+ return os.path.join(output_dir, file)
388
+
389
+ return None
390
+
391
+ def _convert_alpha_to_greenscreen(self, original_video_path: str, alpha_video_path: str) -> str:
392
+ """Convert MatAnyone alpha video to green screen video."""
393
+
394
+ logger.info("Converting alpha video to green screen format...")
395
+
396
+ original_cap = cv2.VideoCapture(original_video_path)
397
+ alpha_cap = cv2.VideoCapture(alpha_video_path)
398
+
399
+ if not original_cap.isOpened() or not alpha_cap.isOpened():
400
+ raise ValueError("Could not open video files for conversion")
401
+
402
+ # Get video properties
403
+ fps = original_cap.get(cv2.CAP_PROP_FPS)
404
+ width = int(original_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
405
+ height = int(original_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
406
+
407
+ # Create output video writer
408
+ green_screen_path = os.path.join(self.temp_dir, "greenscreen_video.mp4")
409
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
410
+ out = cv2.VideoWriter(green_screen_path, fourcc, fps, (width, height))
411
+
412
+ frame_count = 0
413
+ while True:
414
+ ret_orig, original_frame = original_cap.read()
415
+ ret_alpha, alpha_frame = alpha_cap.read()
416
+
417
+ if not ret_orig or not ret_alpha:
418
+ break
419
+
420
+ # Process alpha
421
+ if len(alpha_frame.shape) == 3:
422
+ alpha_matte = np.mean(alpha_frame, axis=2)
423
+ else:
424
+ alpha_matte = alpha_frame
425
+
426
+ alpha_matte = alpha_matte.astype(np.float32) / 255.0
427
+ alpha_matte = np.clip(alpha_matte, 0, 1)
428
+
429
+ # Create green screen frame
430
+ green_screen_frame = self._create_greenscreen_frame(original_frame, alpha_matte)
431
+ out.write(green_screen_frame)
432
+
433
+ frame_count += 1
434
+ if frame_count % 25 == 0:
435
+ logger.info(f"Converted {frame_count} frames to green screen")
436
+
437
+ original_cap.release()
438
+ alpha_cap.release()
439
+ out.release()
440
+
441
+ logger.info(f"Alpha to green screen conversion complete: {green_screen_path}")
442
+ return green_screen_path
443
+
444
+ def _create_sam2_only_greenscreen(self, video_path: str, trimap_path: str) -> str:
445
+ """Fallback: create green screen video using only SAM2 trimap."""
446
+
447
+ logger.info("Creating SAM2-only green screen video (fallback)...")
448
 
 
449
  trimap = cv2.imread(trimap_path, cv2.IMREAD_GRAYSCALE)
450
  if trimap is None:
451
  raise ValueError(f"Could not load trimap: {trimap_path}")
452
 
 
453
  cap = cv2.VideoCapture(video_path)
454
  if not cap.isOpened():
455
  raise ValueError(f"Could not open video: {video_path}")
456
 
 
457
  fps = cap.get(cv2.CAP_PROP_FPS)
458
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
459
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
 
460
 
 
461
  trimap_resized = cv2.resize(trimap, (width, height))
462
+ alpha_matte = (trimap_resized > 128).astype(np.float32)
463
 
 
464
  green_screen_path = os.path.join(self.temp_dir, "greenscreen_video.mp4")
465
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
466
  out = cv2.VideoWriter(green_screen_path, fourcc, fps, (width, height))
467
 
 
 
468
  frame_count = 0
469
+ while True:
470
  ret, frame = cap.read()
471
  if not ret:
472
  break
473
 
474
+ green_screen_frame = self._create_greenscreen_frame(frame, alpha_matte)
475
+ out.write(green_screen_frame)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  frame_count += 1
 
 
477
 
478
  cap.release()
479
  out.release()
480
 
481
+ logger.info(f"SAM2-only green screen created: {green_screen_path}")
482
  return green_screen_path
483
 
484
  def _create_greenscreen_frame(self, original_frame: np.ndarray, alpha_matte: np.ndarray) -> np.ndarray: