Skip to content

Commit e5f0da3

Browse files
committed
pretty return type for detect faces
1 parent 0833da1 commit e5f0da3

13 files changed

+192
-234
lines changed

deepface/commons/functions.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
# package dependencies
1414
from deepface.detectors import DetectorWrapper
15+
from deepface.models.Detector import DetectedFace, FacialAreaRegion
1516
from deepface.commons.logger import Logger
1617

1718
logger = Logger(module="commons.functions")
@@ -170,10 +171,11 @@ def extract_faces(
170171

171172
# img might be path, base64 or numpy array. Convert it to numpy whatever it is.
172173
img, img_name = load_image(img)
173-
img_region = [0, 0, img.shape[1], img.shape[0]]
174+
175+
base_region = FacialAreaRegion(x=0, y=0, w=img.shape[1], h=img.shape[0])
174176

175177
if detector_backend == "skip":
176-
face_objs = [(img, img_region, 0)]
178+
face_objs = [DetectedFace(img=img, facial_area=base_region, confidence=0)]
177179
else:
178180
face_objs = DetectorWrapper.detect_faces(detector_backend, img, align)
179181

@@ -192,9 +194,12 @@ def extract_faces(
192194
)
193195

194196
if len(face_objs) == 0 and enforce_detection is False:
195-
face_objs = [(img, img_region, 0)]
197+
face_objs = [DetectedFace(img=img, facial_area=base_region, confidence=0)]
196198

197-
for current_img, current_region, confidence in face_objs:
199+
for face_obj in face_objs:
200+
current_img = face_obj.img
201+
current_region = face_obj.facial_area
202+
confidence = face_obj.confidence
198203
if current_img.shape[0] > 0 and current_img.shape[1] > 0:
199204
if grayscale is True:
200205
current_img = cv2.cvtColor(current_img, cv2.COLOR_BGR2GRAY)
@@ -245,10 +250,10 @@ def extract_faces(
245250

246251
# int cast is for the exception - object of type 'float32' is not JSON serializable
247252
region_obj = {
248-
"x": int(current_region[0]),
249-
"y": int(current_region[1]),
250-
"w": int(current_region[2]),
251-
"h": int(current_region[3]),
253+
"x": current_region.x,
254+
"y": current_region.y,
255+
"w": current_region.w,
256+
"h": current_region.h,
252257
}
253258

254259
extracted_face = (img_pixels, region_obj, confidence)

deepface/detectors/DetectorWrapper.py

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Any
1+
from typing import Any, List
22
import numpy as np
3-
from deepface.models.Detector import Detector
3+
from deepface.models.Detector import Detector, DetectedFace
44
from deepface.detectors import (
55
FastMtCnn,
66
MediaPipe,
@@ -52,27 +52,19 @@ def build_model(detector_backend: str) -> Any:
5252
return face_detector_obj[detector_backend]
5353

5454

55-
def detect_faces(detector_backend: str, img: np.ndarray, align: bool = True) -> list:
55+
def detect_faces(detector_backend: str, img: np.ndarray, align: bool = True) -> List[DetectedFace]:
5656
"""
5757
Detect face(s) from a given image
5858
Args:
5959
detector_backend (str): detector name
6060
img (np.ndarray): pre-loaded image
6161
alig (bool): enable or disable alignment after detection
6262
Returns:
63-
results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
64-
where each tuple contains:
65-
- detected_face (np.ndarray): The detected face as a NumPy array.
66-
- face_region (List[float]): The image region represented as
67-
a list of floats e.g. [x, y, w, h]
63+
results (List[DetectedFace]): A list of DetectedFace objects
64+
where each object contains:
65+
- img (np.ndarray): The detected face as a NumPy array.
66+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
6867
- confidence (float): The confidence score associated with the detected face.
69-
70-
Example:
71-
results = [
72-
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
73-
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
74-
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
75-
]
7668
"""
7769
face_detector: Detector = build_model(detector_backend)
7870
return face_detector.detect_faces(img=img, align=align)

deepface/detectors/Dlib.py

+14-22
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from typing import List, Tuple
1+
from typing import List
22
import os
33
import bz2
44
import gdown
55
import numpy as np
66
from deepface.commons import functions
7-
from deepface.models.Detector import Detector
7+
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion
88
from deepface.commons.logger import Logger
99

1010
logger = Logger(module="detectors.DlibWrapper")
@@ -56,29 +56,19 @@ def build_model(self) -> dict:
5656
detector["sp"] = sp
5757
return detector
5858

59-
def detect_faces(
60-
self, img: np.ndarray, align: bool = True
61-
) -> List[Tuple[np.ndarray, List[float], float]]:
59+
def detect_faces(self, img: np.ndarray, align: bool = True) -> List[DetectedFace]:
6260
"""
6361
Detect and align face with dlib
6462
Args:
6563
face_detector (Any): dlib face detector object
6664
img (np.ndarray): pre-loaded image
6765
align (bool): default is true
6866
Returns:
69-
results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
70-
where each tuple contains:
71-
- detected_face (np.ndarray): The detected face as a NumPy array.
72-
- face_region (List[float]): The image region represented as
73-
a list of floats e.g. [x, y, w, h]
74-
- confidence (float): The confidence score associated with the detected face.
75-
76-
Example:
77-
results = [
78-
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
79-
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
80-
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
81-
]
67+
results (List[DetectedFace]): A list of DetectedFace objects
68+
where each object contains:
69+
- img (np.ndarray): The detected face as a NumPy array.
70+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
71+
- confidence (float): The confidence score associated with the detected face.
8272
"""
8373
# this is not a must dependency. do not import it in the global level.
8474
try:
@@ -95,8 +85,6 @@ def detect_faces(
9585

9686
detected_face = None
9787

98-
img_region = [0, 0, img.shape[1], img.shape[0]]
99-
10088
face_detector = self.model["face_detector"]
10189

10290
# note that, by design, dlib's fhog face detector scores are >0 but not capped at 1
@@ -115,13 +103,17 @@ def detect_faces(
115103
max(0, top) : min(bottom, img.shape[0]), max(0, left) : min(right, img.shape[1])
116104
]
117105

118-
img_region = [left, top, right - left, bottom - top]
106+
img_region = FacialAreaRegion(x=left, y=right, w=right - left, h=bottom - top)
119107
confidence = scores[idx]
120108

121109
if align:
122110
img_shape = sp(img, detections[idx])
123111
detected_face = dlib.get_face_chip(img, img_shape, size=detected_face.shape[0])
124112

125-
resp.append((detected_face, img_region, confidence))
113+
detected_face_obj = DetectedFace(
114+
img=detected_face, facial_area=img_region, confidence=confidence
115+
)
116+
117+
resp.append(detected_face_obj)
126118

127119
return resp

deepface/detectors/FastMtCnn.py

+14-21
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from typing import Any, Union, List, Tuple
1+
from typing import Any, Union, List
22
import cv2
33
import numpy as np
4-
from deepface.models.Detector import Detector
4+
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion
55
from deepface.modules import detection
66

77
# Link -> https://github.com/timesler/facenet-pytorch
@@ -12,33 +12,22 @@ class FastMtCnnClient(Detector):
1212
def __init__(self):
1313
self.model = self.build_model()
1414

15-
def detect_faces(
16-
self, img: np.ndarray, align: bool = True
17-
) -> List[Tuple[np.ndarray, List[float], float]]:
15+
def detect_faces(self, img: np.ndarray, align: bool = True) -> List[DetectedFace]:
1816
"""
1917
Detect and align face with mtcnn
2018
Args:
2119
img (np.ndarray): pre-loaded image
2220
align (bool): default is true
2321
Returns:
24-
results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
25-
where each tuple contains:
26-
- detected_face (np.ndarray): The detected face as a NumPy array.
27-
- face_region (List[float]): The image region represented as
28-
a list of floats e.g. [x, y, w, h]
29-
- confidence (float): The confidence score associated with the detected face.
30-
31-
Example:
32-
results = [
33-
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
34-
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
35-
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
36-
]
22+
results (List[DetectedFace]): A list of DetectedFace objects
23+
where each object contains:
24+
- img (np.ndarray): The detected face as a NumPy array.
25+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
26+
- confidence (float): The confidence score associated with the detected face.
3727
"""
3828
resp = []
3929

4030
detected_face = None
41-
img_region = [0, 0, img.shape[1], img.shape[0]]
4231

4332
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # mtcnn expects RGB but OpenCV read BGR
4433
detections = self.model.detect(
@@ -49,7 +38,7 @@ def detect_faces(
4938
for current_detection in zip(*detections):
5039
x, y, w, h = xyxy_to_xywh(current_detection[0])
5140
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]
52-
img_region = [x, y, w, h]
41+
img_region = FacialAreaRegion(x=x, y=y, w=w, h=h)
5342
confidence = current_detection[1]
5443

5544
if align:
@@ -59,7 +48,11 @@ def detect_faces(
5948
img=detected_face, left_eye=left_eye, right_eye=right_eye
6049
)
6150

62-
resp.append((detected_face, img_region, confidence))
51+
detected_face_obj = DetectedFace(
52+
img=detected_face, facial_area=img_region, confidence=confidence
53+
)
54+
55+
resp.append(detected_face_obj)
6356

6457
return resp
6558

deepface/detectors/MediaPipe.py

+16-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Any, List, Tuple
1+
from typing import Any, List
22
import numpy as np
3-
from deepface.models.Detector import Detector
3+
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion
44
from deepface.modules import detection
55

66
# Link - https://google.github.io/mediapipe/solutions/face_detection
@@ -29,28 +29,18 @@ def build_model(self) -> Any:
2929
face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.7)
3030
return face_detection
3131

32-
def detect_faces(
33-
self, img: np.ndarray, align: bool = True
34-
) -> List[Tuple[np.ndarray, List[float], float]]:
32+
def detect_faces(self, img: np.ndarray, align: bool = True) -> List[DetectedFace]:
3533
"""
3634
Detect and align face with mediapipe
3735
Args:
3836
img (np.ndarray): pre-loaded image
3937
align (bool): default is true
4038
Returns:
41-
results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
42-
where each tuple contains:
43-
- detected_face (np.ndarray): The detected face as a NumPy array.
44-
- face_region (List[float]): The image region represented as
45-
a list of floats e.g. [x, y, w, h]
46-
- confidence (float): The confidence score associated with the detected face.
47-
48-
Example:
49-
results = [
50-
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
51-
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
52-
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
53-
]
39+
results (List[DetectedFace): A list of DetectedFace objects
40+
where each object contains:
41+
- img (np.ndarray): The detected face as a NumPy array.
42+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
43+
- confidence (float): The confidence score associated with the detected face.
5444
"""
5545
resp = []
5646

@@ -85,13 +75,19 @@ def detect_faces(
8575

8676
if x > 0 and y > 0:
8777
detected_face = img[y : y + h, x : x + w]
88-
img_region = [x, y, w, h]
78+
img_region = FacialAreaRegion(x=x, y=y, w=w, h=h)
8979

9080
if align:
9181
detected_face = detection.align_face(
9282
img=detected_face, left_eye=left_eye, right_eye=right_eye
9383
)
9484

95-
resp.append((detected_face, img_region, confidence))
85+
detected_face_obj = DetectedFace(
86+
img=detected_face,
87+
facial_area=img_region,
88+
confidence=confidence,
89+
)
90+
91+
resp.append(detected_face_obj)
9692

9793
return resp

deepface/detectors/MtCnn.py

+14-21
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from typing import List, Tuple
1+
from typing import List
22
import cv2
33
import numpy as np
44
from mtcnn import MTCNN
5-
from deepface.models.Detector import Detector
5+
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion
66
from deepface.modules import detection
77

88
# pylint: disable=too-few-public-methods
@@ -14,34 +14,23 @@ class MtCnnClient(Detector):
1414
def __init__(self):
1515
self.model = MTCNN()
1616

17-
def detect_faces(
18-
self, img: np.ndarray, align: bool = True
19-
) -> List[Tuple[np.ndarray, List[float], float]]:
17+
def detect_faces(self, img: np.ndarray, align: bool = True) -> List[DetectedFace]:
2018
"""
2119
Detect and align face with mtcnn
2220
Args:
2321
img (np.ndarray): pre-loaded image
2422
align (bool): default is true
2523
Returns:
26-
results (List[Tuple[np.ndarray, List[float], float]]): A list of tuples
27-
where each tuple contains:
28-
- detected_face (np.ndarray): The detected face as a NumPy array.
29-
- face_region (List[float]): The image region represented as
30-
a list of floats e.g. [x, y, w, h]
31-
- confidence (float): The confidence score associated with the detected face.
32-
33-
Example:
34-
results = [
35-
(array(..., dtype=uint8), [110, 60, 150, 380], 0.99),
36-
(array(..., dtype=uint8), [150, 50, 299, 375], 0.98),
37-
(array(..., dtype=uint8), [120, 55, 300, 371], 0.96),
38-
]
24+
results (List[DetectedFace]): A list of DetectedFace objects
25+
where each object contains:
26+
- img (np.ndarray): The detected face as a NumPy array.
27+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
28+
- confidence (float): The confidence score associated with the detected face.
3929
"""
4030

4131
resp = []
4232

4333
detected_face = None
44-
img_region = [0, 0, img.shape[1], img.shape[0]]
4534

4635
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # mtcnn expects RGB but OpenCV read BGR
4736
detections = self.model.detect_faces(img_rgb)
@@ -51,7 +40,7 @@ def detect_faces(
5140
for current_detection in detections:
5241
x, y, w, h = current_detection["box"]
5342
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]
54-
img_region = [x, y, w, h]
43+
img_region = FacialAreaRegion(x=x, y=y, w=w, h=h)
5544
confidence = current_detection["confidence"]
5645

5746
if align:
@@ -62,6 +51,10 @@ def detect_faces(
6251
img=detected_face, left_eye=left_eye, right_eye=right_eye
6352
)
6453

65-
resp.append((detected_face, img_region, confidence))
54+
detected_face_obj = DetectedFace(
55+
img=detected_face, facial_area=img_region, confidence=confidence
56+
)
57+
58+
resp.append(detected_face_obj)
6659

6760
return resp

0 commit comments

Comments
 (0)