CoolFace
Apppublic

san021/phi_ratio

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
face_detector.py76 linesDownload Raw Back to main
1import cv2
2import dlib
3import numpy as np
4import os
5
6# --- Constants ---
7# Define the path to the shape predictor model file
8# We use os.path.join to make it work on any operating system (Windows, Mac, Linux)
9MODEL_PATH = os.path.join(os.path.dirname(__file__), "..", "models", "shape_predictor_68_face_landmarks.dat")
10
11# --- Error Classes ---
12class NoFaceFoundError(Exception):
13    """Custom exception raised when no face is detected in the image."""
14    pass
15
16class MultipleFacesFoundError(Exception):
17    """Custom exception raised when multiple faces are detected."""
18    pass
19
20# --- Initialization ---
21# Initialize dlib's face detector (HOG-based)
22detector = dlib.get_frontal_face_detector()
23
24# Load the facial landmark predictor
25try:
26    predictor = dlib.shape_predictor(MODEL_PATH)
27except RuntimeError as e:
28    print(f"Error loading model from {MODEL_PATH}")
29    print("Please make sure you have downloaded the file and placed it in the 'models' directory.")
30    print(f"Error details: {e}")
31    exit()
32
33def get_landmarks(image):
34    """
35    Detects faces in an image and returns the 68 facial landmarks
36    for the first face found.
37
38    Args:
39        image (numpy.ndarray): The input image (loaded via OpenCV).
40
41    Returns:
42        numpy.ndarray: A 68x2 NumPy array where each row is an (x, y)
43                       coordinate of a facial landmark.
44
45    Raises:
46        NoFaceFoundError: If no faces are detected in the image.
47        MultipleFacesFoundError: If more than one face is detected.
48    """
49    # Convert the image to grayscale (dlib works on grayscale images)
50    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
51
52    # Detect faces in the grayscale image.
53    # The '1' indicates to upsample the image 1 time, which helps find smaller faces.
54    rects = detector(gray, 1)
55
56    # --- Handle detection results ---
57    if len(rects) == 0:
58        # If no faces are found, raise our custom error
59        raise NoFaceFoundError("No face was detected in the provided image.")
60
61    if len(rects) > 1:
62        # If multiple faces are found, we raise an error.
63        # For a Phi ratio, we should only analyze one face at a time.
64        raise MultipleFacesFoundError("Multiple faces were detected. Please provide an image with one face.")
65
66    # --- Get Landmarks ---
67    # Get the landmarks for the *first* face found
68    shape = predictor(gray, rects[0])
69
70    # Convert the shape object to a 68x2 NumPy array
71    # This makes it much easier to work with the coordinates
72    coords = np.zeros((68, 2), dtype="int")
73    for i in range(0, 68):
74        coords[i] = (shape.part(i).x, shape.part(i).y)
75
76    return coords