import mediapipe as mp import cv2 import numpy as np import os import shutil import subprocess import uuid model_path = "./face_landmarker_v2_with_blendshapes.task" BaseOptions = mp.tasks.BaseOptions FaceLandmarker = mp.tasks.vision.FaceLandmarker FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions VisionRunningMode = mp.tasks.vision.RunningMode options = FaceLandmarkerOptions( base_options=BaseOptions(model_asset_path=model_path), running_mode=VisionRunningMode.IMAGE, num_faces=3 ) landmarker = FaceLandmarker.create_from_options(options) def align_to_fixed_eyes(image, lm, ref_left_eye, ref_right_eye, canvas_size=1024): """Align a face to fixed eye positions on a canvas.""" h, w, _ = image.shape # Current eyes left_eye = np.array([lm[468].x * w, lm[468].y * h]) right_eye = np.array([lm[473].x * w, lm[473].y * h]) # Compute rotation dx = right_eye[0] - left_eye[0] dy = right_eye[1] - left_eye[1] angle = np.degrees(np.arctan2(dy, dx)) # Compute scale to match reference eye distance eye_dist = np.linalg.norm(right_eye - left_eye) ref_eye_dist = np.linalg.norm(np.array(ref_right_eye) - np.array(ref_left_eye)) scale = ref_eye_dist / eye_dist # Midpoints eye_center = (left_eye + right_eye) / 2 ref_center = (np.array(ref_left_eye) + np.array(ref_right_eye)) / 2 # Transformation: rotate + scale + translate M = cv2.getRotationMatrix2D(tuple(eye_center), angle, scale) M[0,2] += (ref_center[0] - eye_center[0]) M[1,2] += (ref_center[1] - eye_center[1]) # Optional: place on large canvas offset_x = canvas_size//2 - int(ref_center[0]) offset_y = canvas_size//2 - int(ref_center[1]) M[0,2] += offset_x M[1,2] += offset_y aligned = cv2.warpAffine(image, M, (canvas_size, canvas_size), flags=cv2.INTER_CUBIC) return aligned def process_images_fixed_eyes(files, output_folder="./aligned_fixed_eyes", canvas_size=1024): """Process a list of image files and align faces with fixed eyes.""" if os.path.exists(output_folder): shutil.rmtree(output_folder) os.makedirs(output_folder, exist_ok=True) ref_left_eye, ref_right_eye = None, None for idx, in_path in enumerate(files): image = cv2.imread(in_path) if image is None: continue mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image) result = landmarker.detect(mp_image) # Skip if no face or multiple faces if not result.face_landmarks: continue if len(result.face_landmarks) > 1: continue lm = result.face_landmarks[0] # First frame: define reference eyes if ref_left_eye is None or ref_right_eye is None: h, w, _ = image.shape ref_left_eye = (int(lm[468].x * w), int(lm[468].y * h)) ref_right_eye = (int(lm[473].x * w), int(lm[473].y * h)) aligned = align_to_fixed_eyes(image, lm, ref_left_eye, ref_right_eye, canvas_size) out_path = os.path.join(output_folder, f"{idx:04d}.png") cv2.imwrite(out_path, aligned) import os import uuid import subprocess def create_timelapse(input_folder="./aligned_fixed_eyes", output_folder="./download", fps_in=10, fps_out=30): """ Create a timelapse video using FFmpeg and a file list (handles missing numbers) Output is hidden unless FFmpeg fails. """ os.makedirs(output_folder, exist_ok=True) # Get all image files sorted images = sorted([ f for f in os.listdir(input_folder) if f.lower().endswith((".png", ".jpg", ".jpeg")) ]) if not images: print("No images found in folder:", input_folder) return None # Create temporary file list for FFmpeg file_list_path = "./file_list.txt" with open(file_list_path, "w") as f: for img in images: f.write(f"file '{os.path.join(input_folder, img)}'\n") random_str = str(uuid.uuid4())[:6] output_path = os.path.join(output_folder, f"{random_str}.mp4") # FFmpeg command using file list command = [ "ffmpeg", "-y", "-r", str(fps_in), # input frame rate "-f", "concat", "-safe", "0", "-i", file_list_path, "-c:v", "libx264", "-r", str(fps_out), # output frame rate "-pix_fmt", "yuv420p", output_path ] # Run FFmpeg, hide output result = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) os.remove(file_list_path) # clean up if result.returncode == 0: return output_path else: print("FFmpeg failed. Command was:") print(" ".join(command)) return None def EyeLock_Timelapse(selfies_folder, aligned_folder="./aligned_fixed_eyes", output_folder="./download",image_duraion=0.1): """Wrapper: process selfies from a folder and create a timelapse.""" files = sorted([ os.path.join(selfies_folder, f) for f in os.listdir(selfies_folder) if f.lower().endswith((".jpg", ".png", ".jpeg")) ]) process_images_fixed_eyes(files, aligned_folder, canvas_size=1024) output_video = create_timelapse(aligned_folder, output_folder,fps_in=image_duraion*100) print("Final video:", output_video) return output_video # if __name__ == "__main__": # timelapse_video = EyeLock_Timelapse("./selfies") # print("Timelapse video saved at:", timelapse_video)