details about return types

This commit is contained in:
Sefik Ilkin Serengil 2024-01-21 18:10:21 +00:00
parent c9a7db8815
commit 359162aa5e
22 changed files with 284 additions and 100 deletions

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import gdown import gdown
import numpy as np import numpy as np
@ -53,7 +54,7 @@ class ArcFaceClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "ArcFace" self.model_name = "ArcFace"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with ArcFace model find embeddings with ArcFace model
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import gdown import gdown
import numpy as np import numpy as np
@ -49,7 +50,7 @@ class DeepIdClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "DeepId" self.model_name = "DeepId"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with DeepId model find embeddings with DeepId model
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import bz2 import bz2
import gdown import gdown
@ -20,7 +21,7 @@ class DlibClient(FacialRecognition):
self.model = DlibResNet() self.model = DlibResNet()
self.model_name = "Dlib" self.model_name = "Dlib"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with Dlib model - different than regular models find embeddings with Dlib model - different than regular models
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import gdown import gdown
import numpy as np import numpy as np
@ -53,7 +54,7 @@ class FaceNet128dClient(FacialRecognition):
self.model = load_facenet128d_model() self.model = load_facenet128d_model()
self.model_name = "FaceNet-128d" self.model_name = "FaceNet-128d"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with FaceNet-128d model find embeddings with FaceNet-128d model
Args: Args:
@ -75,7 +76,7 @@ class FaceNet512dClient(FacialRecognition):
self.model = load_facenet512d_model() self.model = load_facenet512d_model()
self.model_name = "FaceNet-512d" self.model_name = "FaceNet-512d"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with FaceNet-512d model find embeddings with FaceNet-512d model
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import zipfile import zipfile
import gdown import gdown
@ -46,7 +47,7 @@ class DeepFaceClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "DeepFace" self.model_name = "DeepFace"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with OpenFace model find embeddings with OpenFace model
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import gdown import gdown
import tensorflow as tf import tensorflow as tf
@ -36,7 +37,7 @@ class OpenFaceClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "OpenFace" self.model_name = "OpenFace"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with OpenFace model find embeddings with OpenFace model
Args: Args:

View File

@ -1,5 +1,5 @@
import os import os
from typing import Any from typing import Any, List
import numpy as np import numpy as np
import cv2 as cv import cv2 as cv
@ -23,7 +23,7 @@ class SFaceClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "SFace" self.model_name = "SFace"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with SFace model - different than regular models find embeddings with SFace model - different than regular models
Args: Args:

View File

@ -1,3 +1,4 @@
from typing import List
import os import os
import gdown import gdown
import numpy as np import numpy as np
@ -47,7 +48,7 @@ class VggFaceClient(FacialRecognition):
self.model = load_model() self.model = load_model()
self.model_name = "VGG-Face" self.model_name = "VGG-Face"
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
""" """
find embeddings with VGG-Face model find embeddings with VGG-Face model
Args: Args:

View File

@ -1,5 +1,5 @@
import os import os
from typing import Union, Tuple from typing import Union, Tuple, List
import base64 import base64
from pathlib import Path from pathlib import Path
@ -140,9 +140,9 @@ def extract_faces(
grayscale: bool = False, grayscale: bool = False,
enforce_detection: bool = True, enforce_detection: bool = True,
align: bool = True, align: bool = True,
) -> list: ) -> List[Tuple[np.ndarray, dict, float]]:
"""Extract faces from an image. """
Extract faces from an image.
Args: Args:
img: a path, url, base64 or numpy array. img: a path, url, base64 or numpy array.
target_size (tuple, optional): the target size of the extracted faces. target_size (tuple, optional): the target size of the extracted faces.
@ -157,7 +157,12 @@ def extract_faces(
ValueError: if face could not be detected and enforce_detection is True. ValueError: if face could not be detected and enforce_detection is True.
Returns: Returns:
list: a list of extracted faces. results (List[Tuple[np.ndarray, dict, float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (dict): The image region represented as
{"x": x, "y": y, "w": w, "h": h}
- confidence (float): The confidence score associated with the detected face.
""" """
# this is going to store a list of img itself (numpy), it region and confidence # this is going to store a list of img itself (numpy), it region and confidence
@ -246,7 +251,7 @@ def extract_faces(
"h": int(current_region[3]), "h": int(current_region[3]),
} }
extracted_face = [img_pixels, region_obj, confidence] extracted_face = (img_pixels, region_obj, confidence)
extracted_faces.append(extracted_face) extracted_faces.append(extracted_face)
if len(extracted_faces) == 0 and enforce_detection == True: if len(extracted_faces) == 0 and enforce_detection == True:

View File

@ -59,9 +59,20 @@ def detect_faces(detector_backend: str, img: np.ndarray, align: bool = True) ->
detector_backend (str): detector name detector_backend (str): detector name
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
alig (bool): enable or disable alignment after detection alig (bool): enable or disable alignment after detection
Returns Returns:
result (list): tuple of face (np.ndarray), face region (list) results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
, confidence score (float) where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
face_detector: Detector = build_model(detector_backend) face_detector: Detector = build_model(detector_backend)
return face_detector.detect_faces(img=img, align=align) return face_detector.detect_faces(img=img, align=align)

View File

@ -1,3 +1,4 @@
from typing import List, Tuple
import os import os
import bz2 import bz2
import gdown import gdown
@ -55,7 +56,9 @@ class DlibClient(Detector):
detector["sp"] = sp detector["sp"] = sp
return detector return detector
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with dlib Detect and align face with dlib
Args: Args:
@ -63,7 +66,19 @@ class DlibClient(Detector):
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
# this is not a must dependency. do not import it in the global level. # this is not a must dependency. do not import it in the global level.
try: try:

View File

@ -1,7 +1,8 @@
from typing import Any, Union from typing import Any, Union, List, Tuple
import cv2 import cv2
import numpy as np import numpy as np
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
# Link -> https://github.com/timesler/facenet-pytorch # Link -> https://github.com/timesler/facenet-pytorch
# Examples https://www.kaggle.com/timesler/guide-to-mtcnn-in-facenet-pytorch # Examples https://www.kaggle.com/timesler/guide-to-mtcnn-in-facenet-pytorch
@ -11,14 +12,28 @@ class FastMtCnnClient(Detector):
def __init__(self): def __init__(self):
self.model = self.build_model() self.model = self.build_model()
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with mtcnn Detect and align face with mtcnn
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -31,16 +46,16 @@ class FastMtCnnClient(Detector):
) # returns boundingbox, prob, landmark ) # returns boundingbox, prob, landmark
if len(detections[0]) > 0: if len(detections[0]) > 0:
for detection in zip(*detections): for current_detection in zip(*detections):
x, y, w, h = xyxy_to_xywh(detection[0]) x, y, w, h = xyxy_to_xywh(current_detection[0])
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]
img_region = [x, y, w, h] img_region = [x, y, w, h]
confidence = detection[1] confidence = current_detection[1]
if align: if align:
left_eye = detection[2][0] left_eye = current_detection[2][0]
right_eye = detection[2][1] right_eye = current_detection[2][1]
detected_face = self.align_face( detected_face = detection.align_face(
img=detected_face, left_eye=left_eye, right_eye=right_eye img=detected_face, left_eye=left_eye, right_eye=right_eye
) )

View File

@ -1,6 +1,7 @@
from typing import Any from typing import Any, List, Tuple
import numpy as np import numpy as np
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
# Link - https://google.github.io/mediapipe/solutions/face_detection # Link - https://google.github.io/mediapipe/solutions/face_detection
@ -28,14 +29,28 @@ class MediaPipeClient(Detector):
face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.7) face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.7)
return face_detection return face_detection
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with mediapipe Detect and align face with mediapipe
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -49,11 +64,11 @@ class MediaPipeClient(Detector):
return resp return resp
# Extract the bounding box, the landmarks and the confidence score # Extract the bounding box, the landmarks and the confidence score
for detection in results.detections: for current_detection in results.detections:
(confidence,) = detection.score (confidence,) = current_detection.score
bounding_box = detection.location_data.relative_bounding_box bounding_box = current_detection.location_data.relative_bounding_box
landmarks = detection.location_data.relative_keypoints landmarks = current_detection.location_data.relative_keypoints
x = int(bounding_box.xmin * img_width) x = int(bounding_box.xmin * img_width)
w = int(bounding_box.width * img_width) w = int(bounding_box.width * img_width)
@ -73,7 +88,7 @@ class MediaPipeClient(Detector):
img_region = [x, y, w, h] img_region = [x, y, w, h]
if align: if align:
detected_face = self.align_face( detected_face = detection.align_face(
img=detected_face, left_eye=left_eye, right_eye=right_eye img=detected_face, left_eye=left_eye, right_eye=right_eye
) )

View File

@ -1,9 +1,11 @@
from typing import List, Tuple
import cv2 import cv2
import numpy as np import numpy as np
from mtcnn import MTCNN from mtcnn import MTCNN
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
# pylint: disable=too-few-public-methods
class MtCnnClient(Detector): class MtCnnClient(Detector):
""" """
Class to cover common face detection functionalitiy for MtCnn backend Class to cover common face detection functionalitiy for MtCnn backend
@ -12,14 +14,28 @@ class MtCnnClient(Detector):
def __init__(self): def __init__(self):
self.model = MTCNN() self.model = MTCNN()
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with mtcnn Detect and align face with mtcnn
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -32,17 +48,17 @@ class MtCnnClient(Detector):
if len(detections) > 0: if len(detections) > 0:
for detection in detections: for current_detection in detections:
x, y, w, h = detection["box"] x, y, w, h = current_detection["box"]
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]
img_region = [x, y, w, h] img_region = [x, y, w, h]
confidence = detection["confidence"] confidence = current_detection["confidence"]
if align: if align:
keypoints = detection["keypoints"] keypoints = current_detection["keypoints"]
left_eye = keypoints["left_eye"] left_eye = keypoints["left_eye"]
right_eye = keypoints["right_eye"] right_eye = keypoints["right_eye"]
detected_face = self.align_face( detected_face = detection.align_face(
img=detected_face, left_eye=left_eye, right_eye=right_eye img=detected_face, left_eye=left_eye, right_eye=right_eye
) )

View File

@ -1,8 +1,9 @@
import os import os
from typing import Any from typing import Any, List, Tuple
import cv2 import cv2
import numpy as np import numpy as np
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
class OpenCvClient(Detector): class OpenCvClient(Detector):
@ -24,7 +25,9 @@ class OpenCvClient(Detector):
detector["eye_detector"] = self.__build_cascade("haarcascade_eye") detector["eye_detector"] = self.__build_cascade("haarcascade_eye")
return detector return detector
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with opencv Detect and align face with opencv
Args: Args:
@ -32,7 +35,19 @@ class OpenCvClient(Detector):
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -56,7 +71,7 @@ class OpenCvClient(Detector):
if align: if align:
left_eye, right_eye = self.find_eyes(img=detected_face) left_eye, right_eye = self.find_eyes(img=detected_face)
detected_face = self.align_face(detected_face, left_eye, right_eye) detected_face = detection.align_face(detected_face, left_eye, right_eye)
img_region = [x, y, w, h] img_region = [x, y, w, h]

View File

@ -1,21 +1,36 @@
from typing import List, Tuple
import numpy as np import numpy as np
from retinaface import RetinaFace as rf from retinaface import RetinaFace as rf
from retinaface.commons import postprocess from retinaface.commons import postprocess
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
# pylint: disable=too-few-public-methods
class RetinaFaceClient(Detector): class RetinaFaceClient(Detector):
def __init__(self): def __init__(self):
self.model = rf.build_model() self.model = rf.build_model()
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with retinaface Detect and align face with retinaface
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []

View File

@ -1,3 +1,4 @@
from typing import List, Tuple
import os import os
import gdown import gdown
import cv2 import cv2
@ -6,6 +7,7 @@ import numpy as np
from deepface.detectors import OpenCv from deepface.detectors import OpenCv
from deepface.commons import functions from deepface.commons import functions
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
from deepface.commons.logger import Logger from deepface.commons.logger import Logger
logger = Logger(module="detectors.SsdWrapper") logger = Logger(module="detectors.SsdWrapper")
@ -69,14 +71,28 @@ class SsdClient(Detector):
return detector return detector
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with ssd Detect and align face with ssd
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -134,9 +150,9 @@ class SsdClient(Detector):
confidence = instance["confidence"] confidence = instance["confidence"]
if align: if align:
opencv_module: OpenCv.OpenCv = self.model["opencv_module"] opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"]
left_eye, right_eye = opencv_module.find_eyes(detected_face) left_eye, right_eye = opencv_module.find_eyes(detected_face)
detected_face = self.align_face( detected_face = detection.align_face(
img=detected_face, left_eye=left_eye, right_eye=right_eye img=detected_face, left_eye=left_eye, right_eye=right_eye
) )

View File

@ -1,6 +1,7 @@
from typing import Any from typing import Any, List, Tuple
import numpy as np import numpy as np
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
from deepface.commons.logger import Logger from deepface.commons.logger import Logger
logger = Logger() logger = Logger()
@ -50,7 +51,9 @@ class YoloClient(Detector):
# Return face_detector # Return face_detector
return YOLO(weight_path) return YOLO(weight_path)
def detect_faces(self, img: np.ndarray, align: bool = False) -> list: def detect_faces(
self, img: np.ndarray, align: bool = False
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with yolo Detect and align face with yolo
Args: Args:
@ -58,7 +61,19 @@ class YoloClient(Detector):
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
resp = [] resp = []
@ -85,7 +100,7 @@ class YoloClient(Detector):
left_eye[1] > LANDMARKS_CONFIDENCE_THRESHOLD left_eye[1] > LANDMARKS_CONFIDENCE_THRESHOLD
and right_eye[1] > LANDMARKS_CONFIDENCE_THRESHOLD and right_eye[1] > LANDMARKS_CONFIDENCE_THRESHOLD
): ):
detected_face = self.align_face( detected_face = detection.align_face(
img=detected_face, left_eye=left_eye[0].cpu(), right_eye=right_eye[0].cpu() img=detected_face, left_eye=left_eye[0].cpu(), right_eye=right_eye[0].cpu()
) )
resp.append((detected_face, [x, y, w, h], confidence)) resp.append((detected_face, [x, y, w, h], confidence))

View File

@ -1,11 +1,12 @@
import os import os
from typing import Any from typing import Any, List, Tuple
import cv2 import cv2
import numpy as np import numpy as np
import gdown import gdown
from deepface.commons import functions from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.Detector import Detector from deepface.models.Detector import Detector
from deepface.modules import detection
from deepface.commons.logger import Logger
logger = Logger(module="detectors.YunetWrapper") logger = Logger(module="detectors.YunetWrapper")
@ -41,14 +42,28 @@ class YuNetClient(Detector):
) from err ) from err
return face_detector return face_detector
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
""" """
Detect and align face with yunet Detect and align face with yunet
Args: Args:
img (np.ndarray): pre-loaded image img (np.ndarray): pre-loaded image
align (bool): default is true align (bool): default is true
Returns: Returns:
list of detected and aligned faces results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
# FaceDetector.detect_faces does not support score_threshold parameter. # FaceDetector.detect_faces does not support score_threshold parameter.
# We can set it via environment variable. # We can set it via environment variable.
@ -107,6 +122,6 @@ class YuNetClient(Detector):
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]
img_region = [x, y, w, h] img_region = [x, y, w, h]
if align: if align:
detected_face = self.align_face(detected_face, (x_re, y_re), (x_le, y_le)) detected_face = detection.align_face(detected_face, (x_re, y_re), (x_le, y_le))
resp.append((detected_face, img_region, confidence)) resp.append((detected_face, img_region, confidence))
return resp return resp

View File

@ -1,42 +1,34 @@
from typing import List, Tuple
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Union, Optional
import numpy as np import numpy as np
from PIL import Image
# Notice that all facial detector models must be inherited from this class # Notice that all facial detector models must be inherited from this class
# pylint: disable=unnecessary-pass, too-few-public-methods
class Detector(ABC): class Detector(ABC):
@abstractmethod @abstractmethod
def detect_faces(self, img: np.ndarray, align: bool = True) -> list: def detect_faces(
pass self, img: np.ndarray, align: bool = True
) -> List[Tuple[np.ndarray, List[float], float]]:
def align_face(
self,
img: np.ndarray,
left_eye: Optional[Union[list, tuple]] = None,
right_eye: Optional[Union[list, tuple]] = None,
) -> np.ndarray:
""" """
Align a given image horizantally with respect to their left and right eye locations Detect faces from a given image
Args: Args:
img (np.ndarray): pre-loaded image with detected face img (np.ndarray): pre-loaded image as a NumPy array
left_eye (list or tuple): coordinates of left eye with respect to the you align (bool): enable or disable alignment after face detection
right_eye(list or tuple): coordinates of right eye with respect to the you
Returns: Returns:
img (np.ndarray): aligned facial image results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
where each tuple contains:
- detected_face (np.ndarray): The detected face as a NumPy array.
- face_region (List[float]): The image region represented as
a list of floats e.g. [x, y, w, h]
- confidence (float): The confidence score associated with the detected face.
Example:
results = [
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
]
""" """
# if eye could not be detected for the given image, return image itself pass
if left_eye is None or right_eye is None:
return img
# sometimes unexpectedly detected images come with nil dimensions
if img.shape[0] == 0 or img.shape[1] == 0:
return img
angle = float(
np.degrees(np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0]))
)
img = Image.fromarray(img)
img = np.array(img.rotate(angle))
return img

View File

@ -1,5 +1,5 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Union from typing import Any, Union, List
import numpy as np import numpy as np
from deepface.commons import functions from deepface.commons import functions
@ -17,5 +17,5 @@ class FacialRecognition(ABC):
model_name: str model_name: str
@abstractmethod @abstractmethod
def find_embeddings(self, img: np.ndarray) -> list: def find_embeddings(self, img: np.ndarray) -> List[float]:
pass pass

View File

@ -3,6 +3,7 @@ from typing import Any, Dict, List, Tuple, Union
# 3rd part dependencies # 3rd part dependencies
import numpy as np import numpy as np
from PIL import Image
# project dependencies # project dependencies
from deepface.commons import functions from deepface.commons import functions
@ -40,8 +41,11 @@ def extract_faces(
grayscale (boolean): extracting faces in rgb or gray scale grayscale (boolean): extracting faces in rgb or gray scale
Returns: Returns:
list of dictionaries. Each dictionary will have facial image itself (RGB), results (List[Dict[str, Any]]): A list of dictionaries, where each dictionary contains:
extracted area from the original image and confidence score. - "face" (np.ndarray): The detected face as a NumPy array.
- "facial_area" (List[float]): The detected face's regions represented as a list of floats.
- "confidence" (float): The confidence score associated with the detected face.
""" """
@ -70,3 +74,31 @@ def extract_faces(
resp_objs.append(resp_obj) resp_objs.append(resp_obj)
return resp_objs return resp_objs
def align_face(
img: np.ndarray,
left_eye: Union[list, tuple],
right_eye: Union[list, tuple],
) -> np.ndarray:
"""
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 you
right_eye(list or tuple): coordinates of right eye with respect to the you
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
# sometimes unexpectedly detected images come with nil dimensions
if img.shape[0] == 0 or img.shape[1] == 0:
return img
angle = float(np.degrees(np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0])))
img = Image.fromarray(img)
img = np.array(img.rotate(angle))
return img