Deepro Bardhan commited on
Commit
40709e4
·
1 Parent(s): 2c5b827

added swap video in all faces function

Browse files
Files changed (3) hide show
  1. .gitignore +1 -0
  2. SinglePhoto.py +11 -0
  3. app.py +120 -1
.gitignore CHANGED
@@ -1,6 +1,7 @@
1
  venv310/
2
  SinglePhoto/
3
  VideoSwapping/
 
4
  MultiSrcSingleDst/
5
  MultiSrcMultiDst/
6
  SingleSrcMultiDst/
 
1
  venv310/
2
  SinglePhoto/
3
  VideoSwapping/
4
+ VideoSwappingAllFaces/
5
  MultiSrcSingleDst/
6
  MultiSrcMultiDst/
7
  SingleSrcMultiDst/
SinglePhoto.py CHANGED
@@ -35,6 +35,17 @@ class FaceSwapper:
35
  result = self.swapper.get(target_img, target_face, source_face, paste_back=True)
36
  return result
37
 
 
 
 
 
 
 
 
 
 
 
 
38
  def main():
39
  # Paths relative to root
40
  source_path = os.path.join("SinglePhoto", "data_src.jpg")
 
35
  result = self.swapper.get(target_img, target_face, source_face, paste_back=True)
36
  return result
37
 
38
+ def count_faces(self, img_path):
39
+ """
40
+ Counts the number of faces in the given image file.
41
+ """
42
+ img = cv2.imread(img_path)
43
+ # Use your face detector here. For example, with OpenCV's Haar cascade:
44
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
45
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
46
+ faces = face_cascade.detectMultiScale(gray, 1.1, 4)
47
+ return len(faces)
48
+
49
  def main():
50
  # Paths relative to root
51
  source_path = os.path.join("SinglePhoto", "data_src.jpg")
app.py CHANGED
@@ -319,6 +319,111 @@ def swap_single_src_multi_dst(src_img, dst_imgs, dst_indices, progress=gr.Progre
319
  progress(1, desc="Done")
320
  return results, log
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  with gr.Blocks() as demo:
323
  gr.Markdown(wellcomingMessage)
324
  with gr.Tab("Single Photo Swapping"):
@@ -349,6 +454,19 @@ with gr.Blocks() as demo:
349
  gr.Textbox(label="Log Output", lines=8, interactive=False)
350
  ],
351
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  with gr.Tab("SingleSrc MultiDst"):
353
  gr.Interface(
354
  fn=swap_single_src_multi_dst,
@@ -388,6 +506,7 @@ with gr.Blocks() as demo:
388
  gr.Textbox(label="Log Output", lines=8, interactive=False)
389
  ],
390
  )
 
391
 
392
  if __name__ == "__main__":
393
- demo.launch(share=True)
 
319
  progress(1, desc="Done")
320
  return results, log
321
 
322
+ def swap_video_all_faces(src_img, video, num_faces_to_swap, progress=gr.Progress()):
323
+ """
324
+ Swaps the single source image to all faces in each frame of the destination video.
325
+ For each frame, swaps one by one, always using the latest swapped image for the next face.
326
+ """
327
+ log = ""
328
+ src_path = "VideoSwappingAllFaces/data_src.jpg"
329
+ dst_video_path = "VideoSwappingAllFaces/data_dst.mp4"
330
+ frames_dir = "VideoSwappingAllFaces/video_frames"
331
+ swapped_dir = "VideoSwappingAllFaces/swapped_frames"
332
+ output_video_path = "VideoSwappingAllFaces/output_tmp_output_video.mp4"
333
+ final_output_path = "VideoSwappingAllFaces/output_with_audio.mp4"
334
+
335
+ os.makedirs(os.path.dirname(src_path), exist_ok=True)
336
+ os.makedirs(os.path.dirname(dst_video_path), exist_ok=True)
337
+ os.makedirs(frames_dir, exist_ok=True)
338
+ os.makedirs(swapped_dir, exist_ok=True)
339
+
340
+ src_img_bgr = cv2.cvtColor(src_img, cv2.COLOR_RGB2BGR)
341
+ cv2.imwrite(src_path, src_img_bgr)
342
+ log += f"Saved source image to {src_path}\n"
343
+ progress(0.05, desc="Saved source image")
344
+
345
+ if isinstance(video, str) and os.path.exists(video):
346
+ shutil.copy(video, dst_video_path)
347
+ log += f"Copied video to {dst_video_path}\n"
348
+ else:
349
+ dst_video_path = video
350
+
351
+ from VideoSwapping import extract_frames, frames_to_video
352
+
353
+ frame_paths = extract_frames(dst_video_path, frames_dir)
354
+ log += f"Extracted {len(frame_paths)} frames to {frames_dir}\n"
355
+ progress(0.15, desc="Extracted frames")
356
+
357
+ swapped_files = set(os.listdir(swapped_dir))
358
+ temp_dir = os.path.join(swapped_dir, "temp_swap")
359
+ os.makedirs(temp_dir, exist_ok=True)
360
+ start_time = time.time()
361
+ total_frames = len(frame_paths)
362
+
363
+ for idx, frame_path in enumerate(frame_paths):
364
+ swapped_name = f"swapped_{idx:05d}.jpg"
365
+ out_path = os.path.join(swapped_dir, swapped_name)
366
+ temp_frame_path = os.path.join(temp_dir, "temp.jpg")
367
+ if swapped_name in swapped_files and os.path.exists(out_path):
368
+ log += f"Frame {idx}: already swapped, skipping.\n"
369
+ elapsed = time.time() - start_time
370
+ avg_time = elapsed / (idx + 1) if idx + 1 > 0 else 0
371
+ remaining = avg_time * (total_frames - (idx + 1))
372
+ mins, secs = divmod(int(remaining), 60)
373
+ progress(0.15 + 0.6 * (idx + 1) / total_frames, desc=f"Swapping {idx+1}/{total_frames} | {mins:02d}:{secs:02d} left")
374
+ continue
375
+ try:
376
+ shutil.copy(frame_path, temp_frame_path)
377
+ for face_idx in range(1, int(num_faces_to_swap) + 1):
378
+ try:
379
+ swapped_img = swapper.swap_faces(src_path, 1, temp_frame_path, face_idx)
380
+ cv2.imwrite(temp_frame_path, swapped_img)
381
+ except Exception as e:
382
+ log += f"Failed to swap face {face_idx} in frame {idx}: {e}\n"
383
+ shutil.copy(temp_frame_path, out_path)
384
+ log += f"Swapped all faces in frame {idx} and saved to {out_path}\n"
385
+ if os.path.exists(temp_frame_path):
386
+ os.remove(temp_frame_path)
387
+ except Exception as e:
388
+ cv2.imwrite(out_path, cv2.imread(frame_path))
389
+ log += f"Failed to swap frame {idx}: {e}\n"
390
+ elapsed = time.time() - start_time
391
+ avg_time = elapsed / (idx + 1) if idx + 1 > 0 else 0
392
+ remaining = avg_time * (total_frames - (idx + 1))
393
+ mins, secs = divmod(int(remaining), 60)
394
+ progress(0.15 + 0.6 * (idx + 1) / total_frames, desc=f"Swapping {idx+1}/{total_frames} | {mins:02d}:{secs:02d} left")
395
+ if os.path.exists(temp_dir):
396
+ shutil.rmtree(temp_dir)
397
+
398
+ cap = cv2.VideoCapture(dst_video_path)
399
+ fps = cap.get(cv2.CAP_PROP_FPS)
400
+ cap.release()
401
+ frames_to_video(swapped_dir, output_video_path, fps)
402
+ log += f"Combined swapped frames into video {output_video_path}\n"
403
+ progress(0.8, desc="Muxing audio")
404
+
405
+ ok, audio_log = add_audio_to_video(dst_video_path, output_video_path, final_output_path)
406
+ if ok:
407
+ log += f"Added audio to {final_output_path}\n"
408
+ else:
409
+ log += f"Audio muxing failed: {audio_log}\n"
410
+ final_output_path = output_video_path
411
+
412
+ try:
413
+ if os.path.exists(src_path):
414
+ os.remove(src_path)
415
+ if os.path.exists(dst_video_path):
416
+ os.remove(dst_video_path)
417
+ if os.path.exists(frames_dir):
418
+ shutil.rmtree(frames_dir)
419
+ if os.path.exists(swapped_dir):
420
+ shutil.rmtree(swapped_dir)
421
+ log += "Cleaned up temp files and folders.\n"
422
+ except Exception as cleanup_error:
423
+ log += f"Cleanup error: {cleanup_error}\n"
424
+ progress(1, desc="Done")
425
+ return final_output_path, log
426
+
427
  with gr.Blocks() as demo:
428
  gr.Markdown(wellcomingMessage)
429
  with gr.Tab("Single Photo Swapping"):
 
454
  gr.Textbox(label="Log Output", lines=8, interactive=False)
455
  ],
456
  )
457
+ with gr.Tab("Video All Faces"):
458
+ gr.Interface(
459
+ fn=swap_video_all_faces,
460
+ inputs=[
461
+ gr.Image(label="Source Image"),
462
+ gr.Video(label="Target Video"),
463
+ gr.Number(value=1, label="Number of Faces to Swap"),
464
+ ],
465
+ outputs=[
466
+ gr.Video(label="Swapped Video"),
467
+ gr.Textbox(label="Log Output", lines=8, interactive=False)
468
+ ],
469
+ )
470
  with gr.Tab("SingleSrc MultiDst"):
471
  gr.Interface(
472
  fn=swap_single_src_multi_dst,
 
506
  gr.Textbox(label="Log Output", lines=8, interactive=False)
507
  ],
508
  )
509
+
510
 
511
  if __name__ == "__main__":
512
+ demo.launch(share=False)