Spaces:
Sleeping
Sleeping
File size: 5,497 Bytes
888242a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
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)
|