Deepro Bardhan commited on
Commit
3881be4
·
1 Parent(s): 7cdf7d9

Add application file and Initial commits

Browse files
Files changed (8) hide show
  1. .gitignore +19 -0
  2. MultiSrcMultiDst.py +59 -0
  3. SinglePhoto.py +85 -0
  4. SingleSrcMultiDst.py +70 -0
  5. VideoSwapping.py +168 -0
  6. app.py +130 -0
  7. inswapper_128.onnx +3 -0
  8. requirements.txt +8 -0
.gitignore ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ venv310/
2
+
3
+ MultiSrcMultiDst/*/*
4
+ !MultiSrcMultiDst/
5
+ !MultiSrcMultiDst/*/
6
+
7
+ SingleSrcMultiDst/*/*
8
+ !SingleSrcMultiDst/
9
+ !SingleSrcMultiDst/*/
10
+
11
+ SinglePhoto/*/*
12
+ !SinglePhoto/
13
+ !SinglePhoto/*/
14
+
15
+ VideoSwapping/*/*
16
+ !VideoSwapping/
17
+ !VideoSwapping/*/
18
+
19
+ __pycache__/*
MultiSrcMultiDst.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import os
3
+ from SinglePhoto import FaceSwapper # Updated import
4
+
5
+ def main():
6
+ src_dir = os.path.join("MultiSrcMultiDst", "src")
7
+ dst_dir = os.path.join("MultiSrcMultiDst", "dst")
8
+ output_root = os.path.join("MultiSrcMultiDst", "output")
9
+
10
+ os.makedirs(output_root, exist_ok=True)
11
+
12
+ swapper = FaceSwapper()
13
+
14
+ # Get all source and destination image paths
15
+ source_images = [os.path.join(src_dir, f) for f in os.listdir(src_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
16
+ dest_images = [os.path.join(dst_dir, f) for f in os.listdir(dst_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
17
+
18
+ # Ask user for target_face_idx for each destination image
19
+ dest_face_indices = {}
20
+ for dest_path in dest_images:
21
+ dest_name = os.path.basename(dest_path)
22
+ while True:
23
+ try:
24
+ idx_str = input(f"Enter target_face_idx for destination image '{dest_name}' (default 1): ")
25
+ if idx_str.strip() == "":
26
+ idx = 1
27
+ else:
28
+ idx = int(idx_str)
29
+ if idx < 1:
30
+ print("Index must be >= 1.")
31
+ continue
32
+ dest_face_indices[dest_path] = idx
33
+ break
34
+ except ValueError:
35
+ print("Please enter a valid integer.")
36
+
37
+ for source_path in source_images:
38
+ source_name = os.path.splitext(os.path.basename(source_path))[0]
39
+ source_output_dir = os.path.join(output_root, source_name)
40
+ os.makedirs(source_output_dir, exist_ok=True)
41
+
42
+ for dest_path in dest_images:
43
+ dest_name = os.path.splitext(os.path.basename(dest_path))[0]
44
+ target_face_idx = dest_face_indices[dest_path]
45
+ try:
46
+ result = swapper.swap_faces(
47
+ source_path=source_path,
48
+ source_face_idx=1,
49
+ target_path=dest_path,
50
+ target_face_idx=target_face_idx
51
+ )
52
+ output_path = os.path.join(source_output_dir, f"{source_name}_to_{dest_name}.jpg")
53
+ cv2.imwrite(output_path, result)
54
+ print(f"Swapped {source_name} -> {dest_name}: {output_path}")
55
+ except Exception as e:
56
+ print(f"Error swapping {source_name} to {dest_name}: {str(e)}")
57
+
58
+ if __name__ == "__main__":
59
+ main()
SinglePhoto.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import insightface
3
+ from insightface.app import FaceAnalysis
4
+ import os
5
+
6
+ class FaceSwapper:
7
+ def __init__(self):
8
+ self.app = FaceAnalysis(name='buffalo_l')
9
+ self.app.prepare(ctx_id=0, det_size=(640, 640))
10
+ self.swapper = insightface.model_zoo.get_model(
11
+ 'inswapper_128.onnx', download=True, download_zip=True
12
+ )
13
+
14
+ def swap_faces(self, source_path, source_face_idx, target_path, target_face_idx):
15
+ source_img = cv2.imread(source_path)
16
+ target_img = cv2.imread(target_path)
17
+
18
+ if source_img is None or target_img is None:
19
+ raise ValueError("Could not read one or both images")
20
+
21
+ source_faces = self.app.get(source_img)
22
+ target_faces = self.app.get(target_img)
23
+
24
+ source_faces = sorted(source_faces, key=lambda x: x.bbox[0])
25
+ target_faces = sorted(target_faces, key=lambda x: x.bbox[0])
26
+
27
+ if len(source_faces) < source_face_idx or source_face_idx < 1:
28
+ raise ValueError(f"Source image contains {len(source_faces)} faces, but requested face {source_face_idx}")
29
+ if len(target_faces) < target_face_idx or target_face_idx < 1:
30
+ raise ValueError(f"Target image contains {len(target_faces)} faces, but requested face {target_face_idx}")
31
+
32
+ source_face = source_faces[source_face_idx - 1]
33
+ target_face = target_faces[target_face_idx - 1]
34
+
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")
41
+ target_path = os.path.join("SinglePhoto", "data_dst.jpg")
42
+ output_dir = os.path.join("SinglePhoto", "output")
43
+ if not os.path.exists(output_dir):
44
+ os.makedirs(output_dir)
45
+
46
+ swapper = FaceSwapper()
47
+
48
+ try:
49
+ # Ask user for target_face_idx, default to 1 if no input or invalid input
50
+ try:
51
+ user_input = input("Enter the target face index (starting from 1, default is 1): ")
52
+ target_face_idx = int(user_input) if user_input.strip() else 1
53
+ if target_face_idx < 1:
54
+ print("Invalid index. Using default value 1.")
55
+ target_face_idx = 1
56
+ except ValueError:
57
+ print("Invalid input. Using default value 1.")
58
+ target_face_idx = 1
59
+
60
+ try:
61
+ result = swapper.swap_faces(
62
+ source_path=source_path,
63
+ source_face_idx=1,
64
+ target_path=target_path,
65
+ target_face_idx=target_face_idx
66
+ )
67
+ except ValueError as ve:
68
+ if "Target image contains" in str(ve):
69
+ print(f"Target face idx {target_face_idx} not found, trying with idx 1.")
70
+ result = swapper.swap_faces(
71
+ source_path=source_path,
72
+ source_face_idx=1,
73
+ target_path=target_path,
74
+ target_face_idx=1
75
+ )
76
+ else:
77
+ raise ve
78
+ output_path = os.path.join(output_dir, "swapped_face.jpg")
79
+ cv2.imwrite(output_path, result)
80
+ print(f"Face swap completed successfully. Result saved to: {output_path}")
81
+ except Exception as e:
82
+ print(f"Error occurred: {str(e)}")
83
+
84
+ if __name__ == "__main__":
85
+ main()
SingleSrcMultiDst.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ from SinglePhoto import FaceSwapper # Use the shared class
4
+
5
+ def main():
6
+ base_folder = "SingleSrcMultiDst"
7
+ dst_folder = os.path.join(base_folder, "dst")
8
+ output_folder = os.path.join(base_folder, "output")
9
+ source_img_name = "data_src.jpg" # Change as needed
10
+
11
+ if not os.path.exists(output_folder):
12
+ os.makedirs(output_folder)
13
+
14
+ source_img_path = os.path.join(base_folder, source_img_name)
15
+ if not os.path.exists(source_img_path):
16
+ print(f"Could not find source image: {source_img_path}")
17
+ return
18
+
19
+ swapper = FaceSwapper()
20
+
21
+ # Ask user for source_face_idx (default 1)
22
+ try:
23
+ user_input = input("Enter the source face index (starting from 1, default is 1): ")
24
+ source_face_idx = int(user_input) if user_input.strip() else 1
25
+ if source_face_idx < 1:
26
+ print("Invalid index. Using default value 1.")
27
+ source_face_idx = 1
28
+ except ValueError:
29
+ print("Invalid input. Using default value 1.")
30
+ source_face_idx = 1
31
+
32
+ # Ask user for each target_face_idx for each destination image
33
+ dest_images = [f for f in os.listdir(dst_folder) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
34
+ dest_face_indices = {}
35
+ for filename in dest_images:
36
+ while True:
37
+ try:
38
+ idx_str = input(f"Enter target_face_idx for destination image '{filename}' (default 1): ")
39
+ if idx_str.strip() == "":
40
+ idx = 1
41
+ else:
42
+ idx = int(idx_str)
43
+ if idx < 1:
44
+ print("Index must be >= 1.")
45
+ continue
46
+ dest_face_indices[filename] = idx
47
+ break
48
+ except ValueError:
49
+ print("Please enter a valid integer.")
50
+
51
+ for filename in dest_images:
52
+ target_img_path = os.path.join(dst_folder, filename)
53
+ if not os.path.exists(target_img_path):
54
+ print(f"Could not find target image: {target_img_path}")
55
+ continue
56
+ try:
57
+ result = swapper.swap_faces(
58
+ source_path=source_img_path,
59
+ source_face_idx=source_face_idx,
60
+ target_path=target_img_path,
61
+ target_face_idx=dest_face_indices[filename]
62
+ )
63
+ output_path = os.path.join(output_folder, f"swapped_{filename}")
64
+ cv2.imwrite(output_path, result)
65
+ print(f"Swapped face saved to: {output_path}")
66
+ except Exception as e:
67
+ print(f"Error processing {filename}: {str(e)}")
68
+
69
+ if __name__ == "__main__":
70
+ main()
VideoSwapping.py ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import os
3
+ import shutil
4
+ import time
5
+ from SinglePhoto import FaceSwapper
6
+
7
+ def extract_frames(video_path, frames_dir):
8
+ if not os.path.exists(frames_dir):
9
+ os.makedirs(frames_dir)
10
+ last_idx = -1
11
+ else:
12
+ # Find the last extracted frame index
13
+ existing = [f for f in os.listdir(frames_dir) if f.startswith("frame_") and f.endswith(".jpg")]
14
+ if existing:
15
+ last_idx = max([int(f.split("_")[1].split(".")[0]) for f in existing])
16
+ else:
17
+ last_idx = -1
18
+
19
+ cap = cv2.VideoCapture(video_path)
20
+ frame_paths = []
21
+ idx = 0
22
+ while True:
23
+ ret, frame = cap.read()
24
+ if not ret:
25
+ break
26
+ frame_path = os.path.join(frames_dir, f"frame_{idx:05d}.jpg")
27
+ if idx > last_idx:
28
+ cv2.imwrite(frame_path, frame)
29
+ frame_paths.append(frame_path)
30
+ idx += 1
31
+ cap.release()
32
+ return frame_paths
33
+
34
+ def frames_to_video(frames_dir, output_video_path, fps):
35
+ frames = sorted([os.path.join(frames_dir, f) for f in os.listdir(frames_dir) if f.endswith('.jpg')])
36
+ if not frames:
37
+ print("No frames found in directory.")
38
+ return
39
+ first_frame = cv2.imread(frames[0])
40
+ height, width, layers = first_frame.shape
41
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
42
+ out = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
43
+ for frame_path in frames:
44
+ frame = cv2.imread(frame_path)
45
+ out.write(frame)
46
+ out.release()
47
+
48
+ def main():
49
+ # Use files from VideoSwapping folder
50
+ video_path = os.path.join("VideoSwapping", "data_dst.mp4")
51
+ source_image_path = os.path.join("VideoSwapping", "data_src.jpg")
52
+ frames_dir = os.path.join("VideoSwapping", "video_frames")
53
+ swapped_dir = os.path.join("VideoSwapping", "swapped_frames")
54
+ output_video_path = os.path.join("VideoSwapping", "output_swapped_video.mp4")
55
+ source_face_idx = 1
56
+
57
+ # Ask user for target_face_idx
58
+ while True:
59
+ try:
60
+ user_input = input("Enter target_face_idx (default is 1): ").strip()
61
+ if user_input == "":
62
+ dest_face_idx = 1
63
+ break
64
+ dest_face_idx = int(user_input)
65
+ break
66
+ except ValueError:
67
+ print("Invalid input. Please enter an integer value.")
68
+
69
+ print("Choose an option:")
70
+ print("1. Extract frames only")
71
+ print("2. Face swap only (requires extracted frames)")
72
+ print("3. Both extract frames and face swap")
73
+ choice = input("Enter 1, 2, or 3: ").strip()
74
+
75
+ frame_paths = []
76
+ if choice == "1" or choice == "3":
77
+ print("Extracting frames from video (resuming if needed)...")
78
+ frame_paths = extract_frames(video_path, frames_dir)
79
+ print(f"Extracted {len(frame_paths)} frames to {frames_dir}.")
80
+ if choice == "1":
81
+ return
82
+
83
+ if choice == "2":
84
+ # If only face swap, ensure frames are present
85
+ if not os.path.exists(frames_dir):
86
+ print("Frames directory does not exist. Please extract frames first.")
87
+ return
88
+ frame_paths = sorted([os.path.join(frames_dir, f) for f in os.listdir(frames_dir) if f.endswith('.jpg')])
89
+
90
+ if choice == "2" or choice == "3":
91
+ # Prepare output directory
92
+ if not os.path.exists(swapped_dir):
93
+ os.makedirs(swapped_dir)
94
+
95
+ # Initialize face swapper
96
+ swapper = FaceSwapper()
97
+
98
+ # Swap faces on each frame
99
+ print("Swapping faces on frames...")
100
+ start_time = time.time()
101
+ for idx, frame_path in enumerate(frame_paths):
102
+ frame_name = os.path.basename(frame_path)
103
+ # Replace 'frame_' with 'swapped_' in the filename
104
+ if frame_name.startswith("frame_"):
105
+ swapped_name = "swapped_" + frame_name[len("frame_"):]
106
+ else:
107
+ swapped_name = "swapped_" + frame_name
108
+ out_path = os.path.join(swapped_dir, swapped_name)
109
+ if os.path.exists(out_path):
110
+ # Skip already swapped frames
111
+ print(f"Frame {idx+1}/{len(frame_paths)} already swapped, skipping...", end='\r')
112
+ continue
113
+ try:
114
+ try:
115
+ swapped = swapper.swap_faces(
116
+ source_path=source_image_path,
117
+ source_face_idx=source_face_idx,
118
+ target_path=frame_path,
119
+ target_face_idx=dest_face_idx
120
+ )
121
+ except ValueError as ve:
122
+ if "Target image contains" in str(ve):
123
+ print(f"\nFrame {idx}: Target face idx {dest_face_idx} not found, trying with idx 1.",end='\r')
124
+ swapped = swapper.swap_faces(
125
+ source_path=source_image_path,
126
+ source_face_idx=source_face_idx,
127
+ target_path=frame_path,
128
+ target_face_idx=1
129
+ )
130
+ else:
131
+ raise ve
132
+ cv2.imwrite(out_path, swapped)
133
+ except Exception as e:
134
+ print(f"\nFrame {idx}: {e}")
135
+ # Optionally, copy the original frame if swap fails
136
+ cv2.imwrite(out_path, cv2.imread(frame_path))
137
+ # Estimate time left
138
+ elapsed = time.time() - start_time
139
+ avg_time = elapsed / (idx + 1)
140
+ remaining = avg_time * (len(frame_paths) - (idx + 1))
141
+ mins, secs = divmod(int(remaining), 60)
142
+ print(f"Swapping frame {idx+1}/{len(frame_paths)} | Est. time left: {mins:02d}:{secs:02d}", end='\r')
143
+ print() # Move to the next line after the loop
144
+
145
+ # Get FPS from original video
146
+ cap = cv2.VideoCapture(video_path)
147
+ fps = cap.get(cv2.CAP_PROP_FPS)
148
+ cap.release()
149
+
150
+ # Combine swapped frames into video
151
+ print("Combining swapped frames into video...")
152
+ frames_to_video(swapped_dir, output_video_path, fps)
153
+ print(f"Done! Output video saved as {output_video_path}")
154
+
155
+ # Ask user if they want to keep the extracted frames and swapped images
156
+ answer = input("Do you want to keep the extracted frames and swapped images? (y/n): ").strip().lower()
157
+ if answer == 'n':
158
+ try:
159
+ shutil.rmtree(frames_dir)
160
+ shutil.rmtree(swapped_dir)
161
+ print("Temporary folders deleted.")
162
+ except Exception as e:
163
+ print(f"Error deleting folders: {e}")
164
+ else:
165
+ print("Temporary folders kept.")
166
+
167
+ if __name__ == "__main__":
168
+ main()
app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import cv2
4
+ from SinglePhoto import FaceSwapper
5
+
6
+ wellcomingMessage = """
7
+ <h1>Face Swapping Suite</h1>
8
+ <p>All-in-one face swapping: single photo, video, multi-source, and multi-destination!</p>
9
+ """
10
+
11
+ swapper = FaceSwapper()
12
+
13
+ def swap_single_photo(src_img, src_idx, dst_img, dst_idx):
14
+ try:
15
+ src_path = "tmp_src.jpg"
16
+ dst_path = "tmp_dst.jpg"
17
+ cv2.imwrite(src_path, src_img)
18
+ cv2.imwrite(dst_path, dst_img)
19
+ result = swapper.swap_faces(src_path, int(src_idx), dst_path, int(dst_idx))
20
+ return result
21
+ except Exception as e:
22
+ return f"Error: {e}"
23
+
24
+ def swap_video(src_img, src_idx, video, dst_idx):
25
+ # Save source image
26
+ src_path = "tmp_src.jpg"
27
+ cv2.imwrite(src_path, src_img)
28
+ # Save video
29
+ video_path = "tmp_video.mp4"
30
+ with open(video_path, "wb") as f:
31
+ f.write(video.read())
32
+ # Extract frames
33
+ frames_dir = "tmp_video_frames"
34
+ swapped_dir = "tmp_swapped_frames"
35
+ output_video_path = "tmp_output_video.mp4"
36
+ from VideoSwapping import extract_frames, frames_to_video
37
+ frame_paths = extract_frames(video_path, frames_dir)
38
+ os.makedirs(swapped_dir, exist_ok=True)
39
+ for idx, frame_path in enumerate(frame_paths):
40
+ out_path = os.path.join(swapped_dir, f"swapped_{idx:05d}.jpg")
41
+ try:
42
+ swapped = swapper.swap_faces(src_path, int(src_idx), frame_path, int(dst_idx))
43
+ cv2.imwrite(out_path, swapped)
44
+ except Exception:
45
+ cv2.imwrite(out_path, cv2.imread(frame_path))
46
+ # Combine frames to video
47
+ cap = cv2.VideoCapture(video_path)
48
+ fps = cap.get(cv2.CAP_PROP_FPS)
49
+ cap.release()
50
+ frames_to_video(swapped_dir, output_video_path, fps)
51
+ return output_video_path
52
+
53
+ def swap_multi_src_single_dst(src_imgs, dst_img, dst_idx):
54
+ # src_imgs: list of images
55
+ results = []
56
+ dst_path = "tmp_dst.jpg"
57
+ cv2.imwrite(dst_path, dst_img)
58
+ for i, src_img in enumerate(src_imgs):
59
+ src_path = f"tmp_src_{i}.jpg"
60
+ cv2.imwrite(src_path, src_img)
61
+ try:
62
+ result = swapper.swap_faces(src_path, 1, dst_path, int(dst_idx))
63
+ results.append(result)
64
+ except Exception as e:
65
+ results.append(f"Error: {e}")
66
+ return results
67
+
68
+ def swap_multi_src_multi_dst(src_imgs, dst_imgs, dst_indices):
69
+ # src_imgs, dst_imgs: lists of images; dst_indices: list of indices
70
+ results = []
71
+ for i, src_img in enumerate(src_imgs):
72
+ src_path = f"tmp_src_{i}.jpg"
73
+ cv2.imwrite(src_path, src_img)
74
+ for j, dst_img in enumerate(dst_imgs):
75
+ dst_path = f"tmp_dst_{j}.jpg"
76
+ cv2.imwrite(dst_path, dst_img)
77
+ try:
78
+ result = swapper.swap_faces(src_path, 1, dst_path, int(dst_indices[j]))
79
+ results.append(result)
80
+ except Exception as e:
81
+ results.append(f"Error: {e}")
82
+ return results
83
+
84
+ with gr.Blocks() as demo:
85
+ gr.Markdown(wellcomingMessage)
86
+ with gr.Tab("Single Photo Swapping"):
87
+ gr.Interface(
88
+ fn=swap_single_photo,
89
+ inputs=[
90
+ gr.Image(label="Source Image"),
91
+ gr.Number(value=1, label="Source Face Index"),
92
+ gr.Image(label="Destination Image"),
93
+ gr.Number(value=1, label="Destination Face Index"),
94
+ ],
95
+ outputs=gr.Image(label="Swapped Image"),
96
+ )
97
+ with gr.Tab("Video Swapping"):
98
+ gr.Interface(
99
+ fn=swap_video,
100
+ inputs=[
101
+ gr.Image(label="Source Image"),
102
+ gr.Number(value=1, label="Source Face Index"),
103
+ gr.Video(label="Target Video"),
104
+ gr.Number(value=1, label="Destination Face Index"),
105
+ ],
106
+ outputs=gr.Video(label="Swapped Video"),
107
+ )
108
+ with gr.Tab("MultiSrc SingleDst"):
109
+ gr.Interface(
110
+ fn=swap_multi_src_single_dst,
111
+ inputs=[
112
+ gr.Gallery(label="Source Images", type="numpy", columns=3),
113
+ gr.Image(label="Destination Image"),
114
+ gr.Number(value=1, label="Destination Face Index"),
115
+ ],
116
+ outputs=gr.Gallery(label="Swapped Images"),
117
+ )
118
+ with gr.Tab("MultiSrc MultiDst"):
119
+ gr.Interface(
120
+ fn=swap_multi_src_multi_dst,
121
+ inputs=[
122
+ gr.Gallery(label="Source Images", type="numpy", columns=3),
123
+ gr.Gallery(label="Destination Images", type="numpy", columns=3),
124
+ gr.Textbox(label="Destination Face Indices (comma-separated, e.g. 1,1,2)"),
125
+ ],
126
+ outputs=gr.Gallery(label="Swapped Images"),
127
+ )
128
+
129
+ if __name__ == "__main__":
130
+ demo.launch()
inswapper_128.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e4a3f08c753cb72d04e10aa0f7dbe3deebbf39567d4ead6dce08e98aa49e16af
3
+ size 554253681
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ numpy
2
+ opencv-python
3
+ onnxruntime-gpu
4
+ scikit-learn
5
+ scikit-image
6
+ tqdm
7
+ mxnet
8
+ insightface