Spaces:
Sleeping
Sleeping
| import cv2 | |
| import numpy as np | |
| import mediapipe as mp | |
| import gradio as gr | |
| mp_face_mesh = mp.solutions.face_mesh | |
| face_mesh = mp_face_mesh.FaceMesh( | |
| static_image_mode=False, | |
| max_num_faces=1, | |
| refine_landmarks=True, | |
| min_detection_confidence=0.5, | |
| min_tracking_confidence=0.5 | |
| ) | |
| def overlay_mask(image, mask_img, landmarks): | |
| h, w, _ = image.shape | |
| if not landmarks: | |
| return image | |
| # Define landmark indices for key points | |
| left_cheek_idx = 234 # left cheek | |
| right_cheek_idx = 454 # right cheek | |
| top_idx = 10 # nose bridge or forehead, for top alignment | |
| # Get coordinates of key points | |
| left = landmarks[left_cheek_idx] | |
| right = landmarks[right_cheek_idx] | |
| top = landmarks[top_idx] | |
| # Normalize the coordinates to pixel positions | |
| left = (int(left.x * w), int(left.y * h)) | |
| right = (int(right.x * w), int(right.y * h)) | |
| top = (int(top.x * w), int(top.y * h)) | |
| # Calculate the width and height of the mask dynamically | |
| mask_width = int(np.linalg.norm(np.array(right) - np.array(left))) # Distance between cheeks | |
| mask_height = int(1.5 * np.linalg.norm(np.array(top) - np.array(((left[0] + right[0]) // 2, (left[1] + right[1]) // 2)))) # Height based on forehead | |
| # Resize the mask to the calculated width and height | |
| resized_mask = cv2.resize(mask_img, (mask_width, mask_height)) | |
| # Calculate the center of the mask on the face | |
| center_x = (left[0] + right[0]) // 2 | |
| center_y = (left[1] + right[1]) // 2 | |
| top_left_x = center_x - mask_width // 2 | |
| top_left_y = center_y - mask_height // 2 | |
| # Overlay mask with alpha blending (assumes the mask has an alpha channel) | |
| for i in range(mask_height): | |
| for j in range(mask_width): | |
| if 0 <= top_left_y + i < h and 0 <= top_left_x + j < w: | |
| alpha = resized_mask[i, j, 3] / 255.0 # assuming mask has alpha channel | |
| image[top_left_y + i, top_left_x + j] = ( | |
| alpha * resized_mask[i, j, :3] + (1 - alpha) * image[top_left_y + i, top_left_x + j] | |
| ) | |
| return image | |
| # Process function | |
| def process(image): | |
| if image is None: | |
| return None | |
| image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| results = face_mesh.process(image_rgb) | |
| if results.multi_face_landmarks: | |
| landmarks = results.multi_face_landmarks[0].landmark | |
| # Load and process your mask PNG with alpha channel | |
| mask_img = cv2.imread("mask.png", cv2.IMREAD_UNCHANGED) | |
| image = overlay_mask(image, mask_img, landmarks) | |
| return image | |
| # Gradio UI | |
| iface = gr.Interface( | |
| fn=process, | |
| inputs=gr.Image(type="numpy"), # Updated line for camera input | |
| outputs="image", | |
| live=True | |
| ) | |
| iface.launch() | |