Spaces:
Runtime error
Runtime error
| # built-in dependencies | |
| from typing import Any, Dict, List, Tuple, Union | |
| # 3rd part dependencies | |
| import numpy as np | |
| import cv2 | |
| from PIL import Image | |
| # project dependencies | |
| from deepface.models.Detector import DetectedFace, FacialAreaRegion | |
| from deepface.detectors import DetectorWrapper | |
| from deepface.commons import image_utils | |
| from deepface.commons import logger as log | |
| logger = log.get_singletonish_logger() | |
| # pylint: disable=no-else-raise | |
| def extract_faces( | |
| img_path: Union[str, np.ndarray], | |
| detector_backend: str = "opencv", | |
| enforce_detection: bool = True, | |
| align: bool = True, | |
| expand_percentage: int = 0, | |
| grayscale: bool = False, | |
| ) -> List[Dict[str, Any]]: | |
| """ | |
| Extract faces from a given image | |
| Args: | |
| img_path (str or np.ndarray): Path to the first image. Accepts exact image path | |
| as a string, numpy array (BGR), or base64 encoded images. | |
| detector_backend (string): face detector backend. Options: 'opencv', 'retinaface', | |
| 'mtcnn', 'ssd', 'dlib', 'mediapipe', 'yolov8', 'centerface' or 'skip' | |
| (default is opencv) | |
| enforce_detection (boolean): If no face is detected in an image, raise an exception. | |
| Default is True. Set to False to avoid the exception for low-resolution images. | |
| align (bool): Flag to enable face alignment (default is True). | |
| expand_percentage (int): expand detected facial area with a percentage | |
| grayscale (boolean): Flag to convert the image to grayscale before | |
| processing (default is False). | |
| Returns: | |
| results (List[Dict[str, Any]]): A list of dictionaries, where each dictionary contains: | |
| - "face" (np.ndarray): The detected face as a NumPy array in RGB format. | |
| - "facial_area" (Dict[str, Any]): The detected face's regions as a dictionary containing: | |
| - keys 'x', 'y', 'w', 'h' with int values | |
| - keys 'left_eye', 'right_eye' with a tuple of 2 ints as values. | |
| left eye and right eye are eyes on the left and right respectively with respect | |
| to the person itself instead of observer. | |
| - "confidence" (float): The confidence score associated with the detected face. | |
| """ | |
| resp_objs = [] | |
| # img might be path, base64 or numpy array. Convert it to numpy whatever it is. | |
| img, img_name = image_utils.load_image(img_path) | |
| if img is None: | |
| raise ValueError(f"Exception while loading {img_name}") | |
| base_region = FacialAreaRegion(x=0, y=0, w=img.shape[1], h=img.shape[0], confidence=0) | |
| if detector_backend == "skip": | |
| face_objs = [DetectedFace(img=img, facial_area=base_region, confidence=0)] | |
| else: | |
| face_objs = DetectorWrapper.detect_faces( | |
| detector_backend=detector_backend, | |
| img=img, | |
| align=align, | |
| expand_percentage=expand_percentage, | |
| ) | |
| # in case of no face found | |
| if len(face_objs) == 0 and enforce_detection is True: | |
| if img_name is not None: | |
| raise ValueError( | |
| f"Face could not be detected in {img_name}." | |
| "Please confirm that the picture is a face photo " | |
| "or consider to set enforce_detection param to False." | |
| ) | |
| else: | |
| raise ValueError( | |
| "Face could not be detected. Please confirm that the picture is a face photo " | |
| "or consider to set enforce_detection param to False." | |
| ) | |
| if len(face_objs) == 0 and enforce_detection is False: | |
| face_objs = [DetectedFace(img=img, facial_area=base_region, confidence=0)] | |
| for face_obj in face_objs: | |
| current_img = face_obj.img | |
| current_region = face_obj.facial_area | |
| if current_img.shape[0] == 0 or current_img.shape[1] == 0: | |
| continue | |
| if grayscale is True: | |
| current_img = cv2.cvtColor(current_img, cv2.COLOR_BGR2GRAY) | |
| current_img = current_img / 255 # normalize input in [0, 1] | |
| resp_objs.append( | |
| { | |
| "face": current_img[:, :, ::-1], | |
| "facial_area": { | |
| "x": int(current_region.x), | |
| "y": int(current_region.y), | |
| "w": int(current_region.w), | |
| "h": int(current_region.h), | |
| "left_eye": current_region.left_eye, | |
| "right_eye": current_region.right_eye, | |
| }, | |
| "confidence": round(current_region.confidence, 2), | |
| } | |
| ) | |
| if len(resp_objs) == 0 and enforce_detection == True: | |
| raise ValueError( | |
| f"Exception while extracting faces from {img_name}." | |
| "Consider to set enforce_detection arg to False." | |
| ) | |
| return resp_objs | |
| def align_face( | |
| img: np.ndarray, | |
| left_eye: Union[list, tuple], | |
| right_eye: Union[list, tuple], | |
| ) -> Tuple[np.ndarray, float]: | |
| """ | |
| Align a given image horizantally with respect to their left and right eye locations | |
| Args: | |
| img (np.ndarray): pre-loaded image with detected face | |
| left_eye (list or tuple): coordinates of left eye with respect to the person itself | |
| right_eye(list or tuple): coordinates of right eye with respect to the person itself | |
| Returns: | |
| img (np.ndarray): aligned facial image | |
| """ | |
| # if eye could not be detected for the given image, return image itself | |
| if left_eye is None or right_eye is None: | |
| return img, 0 | |
| # sometimes unexpectedly detected images come with nil dimensions | |
| if img.shape[0] == 0 or img.shape[1] == 0: | |
| return img, 0 | |
| angle = float(np.degrees(np.arctan2(left_eye[1] - right_eye[1], left_eye[0] - right_eye[0]))) | |
| img = np.array(Image.fromarray(img).rotate(angle)) | |
| return img, angle | |