|
|
import cv2 |
|
|
from video_utils import extract_frames,recombine_frames |
|
|
from face_detection import (detect_faces_insightface_from_frames, |
|
|
extract_faces_from_frames_folder) |
|
|
from grouping import group_faces_by_identity_facenet_fixed,split_csv_by_identity |
|
|
from faceswap import face_swap_on_frame_folder,face_swap_multiple_identities |
|
|
from generate import generate_face_image |
|
|
import os |
|
|
from load_models import warm_up_models |
|
|
from csv_utils import temporal_fill_gaps_in_csv,temporal_smooth_csv |
|
|
|
|
|
def anonymise_video(input_path: str, output_path: str = None) -> None: |
|
|
""" |
|
|
Anonymises a video by detecting faces, clustering identities, generating synthetic replacements, |
|
|
swapping them, and recombining the frames into a new video. |
|
|
Args: |
|
|
input_path (str): Path to the input video. |
|
|
output_path (str): Optional path to save the anonymised video. |
|
|
""" |
|
|
print(f"Anonymising video: {input_path}") |
|
|
|
|
|
frames_folder = 'frames' |
|
|
csv_path = 'meta_data/frames_detections.csv' |
|
|
output_faces = 'output_faces' |
|
|
num_identities = 2 |
|
|
output_folder = 'output_frames' |
|
|
|
|
|
warm_up_models() |
|
|
''' |
|
|
# Step 1: Extract frames from the video |
|
|
#extract_frames(input_path, frames_folder) |
|
|
# Step 2: Detect faces and save to CSV |
|
|
#detect_faces_insightface_from_frames(frames_folder, csv_path) |
|
|
# Step 3: Crop detected faces |
|
|
#extract_faces_from_frames_folder(frames_folder, csv_path=csv_path, padding=30, output_folder=output_faces) |
|
|
# Step 4: Group faces into identities |
|
|
group_faces_by_identity_facenet_fixed(faces_folder=output_faces, num_identities=num_identities) |
|
|
# Step 5: Split detection CSV into per-identity CSVs |
|
|
split_csv_by_identity(original_csv=csv_path) |
|
|
''' |
|
|
|
|
|
|
|
|
generated_faces = [] |
|
|
for i in range(num_identities): |
|
|
print(f'🧬 Generating face for identity: {i}') |
|
|
generated_faces.append(generate_face_image()) |
|
|
|
|
|
|
|
|
csv_identities_dir = 'meta_data/identity_csvs' |
|
|
identity_csv_paths = [] |
|
|
for i in range(num_identities): |
|
|
path = os.path.join(csv_identities_dir, f"identity_{i}.csv") |
|
|
if not os.path.exists(path): |
|
|
raise FileNotFoundError(f"Expected CSV not found: {path}") |
|
|
identity_csv_paths.append(path) |
|
|
|
|
|
identity_csv_paths = fix_faces(num_identities,identity_csv_paths) |
|
|
|
|
|
|
|
|
face_swap_multiple_identities( |
|
|
frames_folder, |
|
|
output_folder = output_folder, |
|
|
generated_images=generated_faces, |
|
|
identity_csv_paths=identity_csv_paths |
|
|
) |
|
|
|
|
|
|
|
|
if output_path is None: |
|
|
base, ext = os.path.splitext(input_path) |
|
|
output_path = f"{base}_anonymised.mp4" |
|
|
|
|
|
|
|
|
recombine_frames(input_path,frames_folder = output_folder,output_video=output_path) |
|
|
|
|
|
|
|
|
def fix_faces(num_identities,identity_csv_paths): |
|
|
new_csv_paths = [] |
|
|
for i in range(num_identities): |
|
|
csv_path = identity_csv_paths[i] |
|
|
csv_path = temporal_fill_gaps_in_csv(csv_path) |
|
|
|
|
|
new_csv_paths.append(csv_path) |
|
|
|
|
|
return new_csv_paths |
|
|
|
|
|
if __name__ == "__main__": |
|
|
input_video = "/Users/sophiemaw/Downloads/CONFIDENTIAL DO NOT SHARE Edna & Paul 29.10.10 Part 2 00.12.46.531.mov" |
|
|
output_video = 'anonymised.mp4' |
|
|
anonymise_video(input_video) |
|
|
|
|
|
|
|
|
|