mirror of
https://github.com/serengil/deepface.git
synced 2025-06-06 11:35:21 +00:00
lint
This commit is contained in:
parent
8bfdcf139a
commit
7e59cdf05d
@ -10,14 +10,15 @@ import numpy as np
|
||||
class Detector(ABC):
|
||||
@abstractmethod
|
||||
def detect_faces(
|
||||
self,
|
||||
imgs: Union[np.ndarray, List[np.ndarray]]
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List["FacialAreaRegion"], List[List["FacialAreaRegion"]]]:
|
||||
"""
|
||||
Interface for detect and align faces in a batch of images
|
||||
|
||||
Args:
|
||||
imgs (Union[np.ndarray, List[np.ndarray]]): pre-loaded image as numpy array or a list of those
|
||||
img (Union[np.ndarray, List[np.ndarray]]):
|
||||
Pre-loaded image as numpy array or a list of those
|
||||
|
||||
Returns:
|
||||
results (Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]):
|
||||
|
@ -18,9 +18,8 @@ class MtCnnClient(Detector):
|
||||
self.model = MTCNN()
|
||||
|
||||
def detect_faces(
|
||||
self,
|
||||
img: Union[np.ndarray,
|
||||
List[np.ndarray]]
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
"""
|
||||
Detect and align faces with mtcnn for a list of images
|
||||
@ -31,7 +30,8 @@ class MtCnnClient(Detector):
|
||||
|
||||
Returns:
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
||||
A list of FacialAreaRegion objects for a single image or a list of lists of FacialAreaRegion objects for each image
|
||||
A list of FacialAreaRegion objects for a single image
|
||||
or a list of lists of FacialAreaRegion objects for each image
|
||||
"""
|
||||
|
||||
if not isinstance(img, list):
|
||||
|
@ -29,35 +29,42 @@ class OpenCvClient(Detector):
|
||||
detector["eye_detector"] = self.__build_cascade("haarcascade_eye")
|
||||
return detector
|
||||
|
||||
def detect_faces(self, imgs: Union[np.ndarray, List[np.ndarray]]) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
def detect_faces(
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
"""
|
||||
Detect and align face with opencv
|
||||
|
||||
Args:
|
||||
imgs (Union[np.ndarray, List[np.ndarray]]): pre-loaded image as numpy array or a list of those
|
||||
img (Union[np.ndarray, List[np.ndarray]]):
|
||||
Pre-loaded image as numpy array or a list of those
|
||||
|
||||
Returns:
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]): A list or a list of lists of FacialAreaRegion objects
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
||||
A list or a list of lists of FacialAreaRegion objects
|
||||
"""
|
||||
if isinstance(imgs, np.ndarray):
|
||||
imgs = [imgs]
|
||||
if isinstance(img, np.ndarray):
|
||||
imgs = [img]
|
||||
else:
|
||||
imgs = img
|
||||
|
||||
batch_results = []
|
||||
|
||||
for img in imgs:
|
||||
for single_img in imgs:
|
||||
resp = []
|
||||
detected_face = None
|
||||
faces = []
|
||||
try:
|
||||
faces, _, scores = self.model["face_detector"].detectMultiScale3(
|
||||
img, 1.1, 10, outputRejectLevels=True
|
||||
single_img, 1.1, 10, outputRejectLevels=True
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
if len(faces) > 0:
|
||||
for (x, y, w, h), confidence in zip(faces, scores):
|
||||
detected_face = img[int(y):int(y + h), int(x):int(x + w)]
|
||||
detected_face = single_img[int(y):int(y + h), int(x):int(x + w)]
|
||||
left_eye, right_eye = self.find_eyes(img=detected_face)
|
||||
|
||||
if left_eye is not None:
|
||||
|
@ -13,15 +13,20 @@ class RetinaFaceClient(Detector):
|
||||
def __init__(self):
|
||||
self.model = rf.build_model()
|
||||
|
||||
def detect_faces(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
def detect_faces(
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
"""
|
||||
Detect and align faces with retinaface in an image or a list of images
|
||||
Detect and align faces with retinaface in a batch of images
|
||||
|
||||
Args:
|
||||
img (Union[np.ndarray, List[np.ndarray]]): pre-loaded image as numpy array or a list of those
|
||||
img (Union[np.ndarray, List[np.ndarray]]):
|
||||
Pre-loaded image as numpy array or a list of those
|
||||
|
||||
Returns:
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]): A list or a list of lists of FacialAreaRegion objects
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
||||
A list or a list of lists of FacialAreaRegion objects
|
||||
"""
|
||||
if isinstance(img, np.ndarray):
|
||||
imgs = [img]
|
||||
@ -30,9 +35,9 @@ class RetinaFaceClient(Detector):
|
||||
|
||||
batch_results = []
|
||||
|
||||
for img in imgs:
|
||||
for single_img in imgs:
|
||||
resp = []
|
||||
obj = rf.detect_faces(img, model=self.model, threshold=0.9)
|
||||
obj = rf.detect_faces(single_img, model=self.model, threshold=0.9)
|
||||
|
||||
if isinstance(obj, dict):
|
||||
for face_idx in obj.keys():
|
||||
|
@ -1,5 +1,5 @@
|
||||
# built-in dependencies
|
||||
from typing import List
|
||||
from typing import List, Union
|
||||
from enum import IntEnum
|
||||
|
||||
# 3rd party dependencies
|
||||
@ -54,83 +54,96 @@ class SsdClient(Detector):
|
||||
|
||||
return {"face_detector": face_detector, "opencv_module": OpenCv.OpenCvClient()}
|
||||
|
||||
def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||
def detect_faces(
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||
"""
|
||||
Detect and align face with ssd
|
||||
Detect and align faces with ssd in a batch of images
|
||||
|
||||
Args:
|
||||
img (np.ndarray): pre-loaded image as numpy array
|
||||
img (Union[np.ndarray, List[np.ndarray]]):
|
||||
Pre-loaded image as numpy array or a list of those
|
||||
|
||||
Returns:
|
||||
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
||||
A list or a list of lists of FacialAreaRegion objects
|
||||
"""
|
||||
if isinstance(img, np.ndarray):
|
||||
imgs = [img]
|
||||
else:
|
||||
imgs = img
|
||||
|
||||
# Because cv2.dnn.blobFromImage expects CV_8U (8-bit unsigned integer) values
|
||||
if img.dtype != np.uint8:
|
||||
img = img.astype(np.uint8)
|
||||
batch_results = []
|
||||
|
||||
opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"]
|
||||
for single_img in imgs:
|
||||
# Because cv2.dnn.blobFromImage expects CV_8U (8-bit unsigned integer) values
|
||||
if single_img.dtype != np.uint8:
|
||||
single_img = single_img.astype(np.uint8)
|
||||
|
||||
target_size = (300, 300)
|
||||
opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"]
|
||||
|
||||
original_size = img.shape
|
||||
target_size = (300, 300)
|
||||
original_size = single_img.shape
|
||||
current_img = cv2.resize(single_img, target_size)
|
||||
|
||||
current_img = cv2.resize(img, target_size)
|
||||
aspect_ratio_x = original_size[1] / target_size[1]
|
||||
aspect_ratio_y = original_size[0] / target_size[0]
|
||||
|
||||
aspect_ratio_x = original_size[1] / target_size[1]
|
||||
aspect_ratio_y = original_size[0] / target_size[0]
|
||||
imageBlob = cv2.dnn.blobFromImage(image=current_img)
|
||||
|
||||
imageBlob = cv2.dnn.blobFromImage(image=current_img)
|
||||
face_detector = self.model["face_detector"]
|
||||
face_detector.setInput(imageBlob)
|
||||
detections = face_detector.forward()
|
||||
|
||||
face_detector = self.model["face_detector"]
|
||||
face_detector.setInput(imageBlob)
|
||||
detections = face_detector.forward()
|
||||
class ssd_labels(IntEnum):
|
||||
img_id = 0
|
||||
is_face = 1
|
||||
confidence = 2
|
||||
left = 3
|
||||
top = 4
|
||||
right = 5
|
||||
bottom = 6
|
||||
|
||||
class ssd_labels(IntEnum):
|
||||
img_id = 0
|
||||
is_face = 1
|
||||
confidence = 2
|
||||
left = 3
|
||||
top = 4
|
||||
right = 5
|
||||
bottom = 6
|
||||
|
||||
faces = detections[0][0]
|
||||
faces = faces[
|
||||
(faces[:, ssd_labels.is_face] == 1) & (faces[:, ssd_labels.confidence] >= 0.90)
|
||||
]
|
||||
margins = [ssd_labels.left, ssd_labels.top, ssd_labels.right, ssd_labels.bottom]
|
||||
faces[:, margins] = np.int32(faces[:, margins] * 300)
|
||||
faces[:, margins] = np.int32(
|
||||
faces[:, margins] * [aspect_ratio_x, aspect_ratio_y, aspect_ratio_x, aspect_ratio_y]
|
||||
)
|
||||
faces[:, [ssd_labels.right, ssd_labels.bottom]] -= faces[
|
||||
:, [ssd_labels.left, ssd_labels.top]
|
||||
]
|
||||
|
||||
resp = []
|
||||
for face in faces:
|
||||
confidence = float(face[ssd_labels.confidence])
|
||||
x, y, w, h = map(int, face[margins])
|
||||
detected_face = img[y : y + h, x : x + w]
|
||||
|
||||
left_eye, right_eye = opencv_module.find_eyes(detected_face)
|
||||
|
||||
# eyes found in the detected face instead image itself
|
||||
# detected face's coordinates should be added
|
||||
if left_eye is not None:
|
||||
left_eye = x + int(left_eye[0]), y + int(left_eye[1])
|
||||
if right_eye is not None:
|
||||
right_eye = x + int(right_eye[0]), y + int(right_eye[1])
|
||||
|
||||
facial_area = FacialAreaRegion(
|
||||
x=x,
|
||||
y=y,
|
||||
w=w,
|
||||
h=h,
|
||||
left_eye=left_eye,
|
||||
right_eye=right_eye,
|
||||
confidence=confidence,
|
||||
faces = detections[0][0]
|
||||
faces = faces[
|
||||
(faces[:, ssd_labels.is_face] == 1) & (faces[:, ssd_labels.confidence] >= 0.90)
|
||||
]
|
||||
margins = [ssd_labels.left, ssd_labels.top, ssd_labels.right, ssd_labels.bottom]
|
||||
faces[:, margins] = np.int32(faces[:, margins] * 300)
|
||||
faces[:, margins] = np.int32(
|
||||
faces[:, margins] * [aspect_ratio_x, aspect_ratio_y, aspect_ratio_x, aspect_ratio_y]
|
||||
)
|
||||
resp.append(facial_area)
|
||||
return resp
|
||||
faces[:, [ssd_labels.right, ssd_labels.bottom]] -= faces[
|
||||
:, [ssd_labels.left, ssd_labels.top]
|
||||
]
|
||||
|
||||
resp = []
|
||||
for face in faces:
|
||||
confidence = float(face[ssd_labels.confidence])
|
||||
x, y, w, h = map(int, face[margins])
|
||||
detected_face = single_img[y : y + h, x : x + w]
|
||||
|
||||
left_eye, right_eye = opencv_module.find_eyes(detected_face)
|
||||
|
||||
# eyes found in the detected face instead image itself
|
||||
# detected face's coordinates should be added
|
||||
if left_eye is not None:
|
||||
left_eye = x + int(left_eye[0]), y + int(left_eye[1])
|
||||
if right_eye is not None:
|
||||
right_eye = x + int(right_eye[0]), y + int(right_eye[1])
|
||||
|
||||
facial_area = FacialAreaRegion(
|
||||
x=x,
|
||||
y=y,
|
||||
w=w,
|
||||
h=h,
|
||||
left_eye=left_eye,
|
||||
right_eye=right_eye,
|
||||
confidence=confidence,
|
||||
)
|
||||
resp.append(facial_area)
|
||||
|
||||
batch_results.append(resp)
|
||||
|
||||
return batch_results if len(batch_results) > 1 else batch_results[0]
|
||||
|
@ -1,6 +1,6 @@
|
||||
# built-in dependencies
|
||||
import os
|
||||
from typing import List, Any, Union, Tuple
|
||||
from typing import List, Any, Union
|
||||
from enum import Enum
|
||||
|
||||
# 3rd party dependencies
|
||||
@ -62,25 +62,30 @@ class YoloDetectorClient(Detector):
|
||||
# Return face_detector
|
||||
return YOLO(weight_file)
|
||||
|
||||
def detect_faces(self, imgs: Union[np.ndarray, List[np.ndarray]]) -> Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]:
|
||||
def detect_faces(
|
||||
self,
|
||||
img: Union[np.ndarray, List[np.ndarray]]
|
||||
) -> Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]:
|
||||
"""
|
||||
Detect and align faces in an image or a list of images with yolo
|
||||
Detect and align faces in a batch of images with yolo
|
||||
|
||||
Args:
|
||||
imgs (Union[np.ndarray, List[np.ndarray]]): pre-loaded image as numpy array or a list of those
|
||||
img (Union[np.ndarray, List[np.ndarray]]):
|
||||
Pre-loaded image as numpy array or a list of those
|
||||
|
||||
Returns:
|
||||
results (Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]):
|
||||
A list of lists of FacialAreaRegion objects for each image or a list of FacialAreaRegion objects
|
||||
A list of lists of FacialAreaRegion objects
|
||||
for each image or a list of FacialAreaRegion objects
|
||||
"""
|
||||
if not isinstance(imgs, list):
|
||||
imgs = [imgs]
|
||||
if not isinstance(img, list):
|
||||
img = [img]
|
||||
|
||||
all_results = []
|
||||
|
||||
# Detect faces for all images
|
||||
results_list = self.model.predict(
|
||||
imgs,
|
||||
img,
|
||||
verbose=False,
|
||||
show=False,
|
||||
conf=float(os.getenv("YOLO_MIN_DETECTION_CONFIDENCE", "0.25")),
|
||||
@ -113,9 +118,16 @@ class YoloDetectorClient(Detector):
|
||||
|
||||
# eyes are list of float, need to cast them tuple of int
|
||||
# Ensure eyes are tuples of exactly two integers or None
|
||||
left_eye = tuple(map(int, left_eye[:2])) if left_eye and len(left_eye) == 2 else None
|
||||
right_eye = tuple(map(int, right_eye[:2])) if right_eye and len(right_eye) == 2 else None
|
||||
|
||||
left_eye = (
|
||||
tuple(map(int, left_eye[:2]))
|
||||
if left_eye and len(left_eye) == 2
|
||||
else None
|
||||
)
|
||||
right_eye = (
|
||||
tuple(map(int, right_eye[:2]))
|
||||
if right_eye and len(right_eye) == 2
|
||||
else None
|
||||
)
|
||||
x, y, w, h = int(x - w / 2), int(y - h / 2), int(w), int(h)
|
||||
facial_area = FacialAreaRegion(
|
||||
x=x,
|
||||
|
@ -34,8 +34,9 @@ def extract_faces(
|
||||
Extract faces from a given image or list of images
|
||||
|
||||
Args:
|
||||
img_paths (List[str or np.ndarray or IO[bytes]] or str or np.ndarray or IO[bytes]): Path(s) to the image(s). Accepts exact image path
|
||||
as a string, numpy array (BGR), a file object that supports at least `.read` and is
|
||||
img_paths (List[str or np.ndarray or IO[bytes]] or str or np.ndarray or IO[bytes]):
|
||||
Path(s) to the image(s) as a string,
|
||||
numpy array (BGR), a file object that supports at least `.read` and is
|
||||
opened in binary mode, or base64 encoded images.
|
||||
|
||||
detector_backend (string): face detector backend. Options: 'opencv', 'retinaface',
|
||||
@ -148,7 +149,10 @@ def extract_faces(
|
||||
elif color_face == "gray":
|
||||
current_img = cv2.cvtColor(current_img, cv2.COLOR_BGR2GRAY)
|
||||
else:
|
||||
raise ValueError(f"The color_face can be rgb, bgr or gray, but it is {color_face}.")
|
||||
raise ValueError(
|
||||
f"The color_face can be rgb, bgr or gray, "
|
||||
f"but it is {color_face}."
|
||||
)
|
||||
|
||||
if normalize_face:
|
||||
current_img = current_img / 255 # normalize input in [0, 1]
|
||||
@ -184,7 +188,10 @@ def extract_faces(
|
||||
|
||||
if anti_spoofing is True:
|
||||
antispoof_model = modeling.build_model(task="spoofing", model_name="Fasnet")
|
||||
is_real, antispoof_score = antispoof_model.analyze(img=img, facial_area=(x, y, w, h))
|
||||
is_real, antispoof_score = antispoof_model.analyze(
|
||||
img=img,
|
||||
facial_area=(x, y, w, h)
|
||||
)
|
||||
resp_obj["is_real"] = is_real
|
||||
resp_obj["antispoof_score"] = antispoof_score
|
||||
|
||||
@ -226,10 +233,18 @@ def detect_faces(
|
||||
"""
|
||||
if not isinstance(img, list):
|
||||
img = [img]
|
||||
|
||||
|
||||
if detector_backend == "skip":
|
||||
all_face_objs = [
|
||||
[DetectedFace(img=single_img, facial_area=FacialAreaRegion(x=0, y=0, w=single_img.shape[1], h=single_img.shape[0]), confidence=0)]
|
||||
[
|
||||
DetectedFace(
|
||||
img=single_img,
|
||||
facial_area=FacialAreaRegion(
|
||||
x=0, y=0, w=single_img.shape[1], h=single_img.shape[0]
|
||||
),
|
||||
confidence=0,
|
||||
)
|
||||
]
|
||||
for single_img in img
|
||||
]
|
||||
if len(img) == 1:
|
||||
@ -280,7 +295,17 @@ def detect_faces(
|
||||
all_facial_areas = [all_facial_areas]
|
||||
|
||||
all_detected_faces = []
|
||||
for single_img, facial_areas, width_border, height_border in zip(preprocessed_images, all_facial_areas, width_borders, height_borders):
|
||||
for (
|
||||
single_img,
|
||||
facial_areas,
|
||||
width_border,
|
||||
height_border
|
||||
) in zip(
|
||||
preprocessed_images,
|
||||
all_facial_areas,
|
||||
width_borders,
|
||||
height_borders
|
||||
):
|
||||
if not isinstance(facial_areas, list):
|
||||
facial_areas = [facial_areas]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user