Skip to content

Commit 329606f

Browse files
authored
Merge pull request #1140 from serengil/feat-task-2403-eye-coordinates-in-biology
Feat task 2403 eye coordinates in biology
2 parents ad80a31 + 09499c9 commit 329606f

16 files changed

+86
-39
lines changed

deepface/DeepFace.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,9 @@ def extract_faces(
476476
477477
- "facial_area" (Dict[str, Any]): The detected face's regions as a dictionary containing:
478478
- keys 'x', 'y', 'w', 'h' with int values
479-
- keys 'left_eye', 'right_eye' with a tuple of 2 ints as values
479+
- keys 'left_eye', 'right_eye' with a tuple of 2 ints as values. left and right eyes
480+
are eyes on the left and right respectively with respect to the person itself
481+
instead of observer.
480482
481483
- "confidence" (float): The confidence score associated with the detected face.
482484
"""

deepface/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.89"
1+
__version__ = "0.0.90"

deepface/detectors/DetectorWrapper.py

+7-9
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ def detect_faces(
7676
7777
- img (np.ndarray): The detected face as a NumPy array.
7878
79-
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h
79+
- facial_area (FacialAreaRegion): The facial area region represented as x, y, w, h,
80+
left_eye and right eye. left eye and right eye are eyes on the left and right
81+
with respect to the person instead of observer.
8082
8183
- confidence (float): The confidence score associated with the detected face.
8284
"""
@@ -123,13 +125,11 @@ def detect_faces(
123125
img=img, left_eye=left_eye, right_eye=right_eye
124126
)
125127
rotated_x1, rotated_y1, rotated_x2, rotated_y2 = rotate_facial_area(
126-
facial_area=(x, y, x + w, y + h),
127-
angle=angle,
128-
size=(img.shape[0], img.shape[1])
128+
facial_area=(x, y, x + w, y + h), angle=angle, size=(img.shape[0], img.shape[1])
129129
)
130130
detected_face = aligned_img[
131-
int(rotated_y1) : int(rotated_y2),
132-
int(rotated_x1) : int(rotated_x2)]
131+
int(rotated_y1) : int(rotated_y2), int(rotated_x1) : int(rotated_x2)
132+
]
133133

134134
result = DetectedFace(
135135
img=detected_face,
@@ -143,9 +143,7 @@ def detect_faces(
143143

144144

145145
def rotate_facial_area(
146-
facial_area: Tuple[int, int, int, int],
147-
angle: float,
148-
size: Tuple[int, int]
146+
facial_area: Tuple[int, int, int, int], angle: float, size: Tuple[int, int]
149147
) -> Tuple[int, int, int, int]:
150148
"""
151149
Rotate the facial area around its center.

deepface/detectors/Dlib.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
8888

8989
shape = self.model["sp"](img, detection)
9090

91-
left_eye = (
91+
right_eye = (
9292
int((shape.part(2).x + shape.part(3).x) // 2),
9393
int((shape.part(2).y + shape.part(3).y) // 2),
9494
)
95-
right_eye = (
95+
left_eye = (
9696
int((shape.part(0).x + shape.part(1).x) // 2),
9797
int((shape.part(0).y + shape.part(1).y) // 2),
9898
)

deepface/detectors/FastMtCnn.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
3434
):
3535
for regions, confidence, eyes in zip(*detections):
3636
x, y, w, h = xyxy_to_xywh(regions)
37-
left_eye = eyes[0]
38-
right_eye = eyes[1]
37+
right_eye = eyes[0]
38+
left_eye = eyes[1]
3939

4040
left_eye = tuple(int(i) for i in left_eye)
4141
right_eye = tuple(int(i) for i in right_eye)

deepface/detectors/MediaPipe.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
6161
y = int(bounding_box.ymin * img_height)
6262
h = int(bounding_box.height * img_height)
6363

64-
left_eye = (int(landmarks[0].x * img_width), int(landmarks[0].y * img_height))
65-
right_eye = (int(landmarks[1].x * img_width), int(landmarks[1].y * img_height))
64+
right_eye = (int(landmarks[0].x * img_width), int(landmarks[0].y * img_height))
65+
left_eye = (int(landmarks[1].x * img_width), int(landmarks[1].y * img_height))
6666
# nose = (int(landmarks[2].x * img_width), int(landmarks[2].y * img_height))
6767
# mouth = (int(landmarks[3].x * img_width), int(landmarks[3].y * img_height))
6868
# right_ear = (int(landmarks[4].x * img_width), int(landmarks[4].y * img_height))

deepface/detectors/MtCnn.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
3535
for current_detection in detections:
3636
x, y, w, h = current_detection["box"]
3737
confidence = current_detection["confidence"]
38-
left_eye = current_detection["keypoints"]["left_eye"]
39-
right_eye = current_detection["keypoints"]["right_eye"]
38+
# mtcnn detector assigns left eye with respect to the observer
39+
# but we are setting it with respect to the person itself
40+
left_eye = current_detection["keypoints"]["right_eye"]
41+
right_eye = current_detection["keypoints"]["left_eye"]
4042

4143
facial_area = FacialAreaRegion(
4244
x=x,

deepface/detectors/OpenCv.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,18 @@ def find_eyes(self, img: np.ndarray) -> tuple:
112112
eye_2 = eyes[1]
113113

114114
if eye_1[0] < eye_2[0]:
115-
left_eye = eye_1
116-
right_eye = eye_2
117-
else:
118-
left_eye = eye_2
119115
right_eye = eye_1
116+
left_eye = eye_2
117+
else:
118+
right_eye = eye_2
119+
left_eye = eye_1
120120

121121
# -----------------------
122122
# find center of eyes
123-
left_eye = (int(left_eye[0] + (left_eye[2] / 2)), int(left_eye[1] + (left_eye[3] / 2)))
123+
left_eye = (
124+
int(left_eye[0] + (left_eye[2] / 2)),
125+
int(left_eye[1] + (left_eye[3] / 2)),
126+
)
124127
right_eye = (
125128
int(right_eye[0] + (right_eye[2] / 2)),
126129
int(right_eye[1] + (right_eye[3] / 2)),

deepface/detectors/RetinaFace.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
3434
x = detection[0]
3535
w = detection[2] - x
3636

37-
# notice that these must be inverse for retinaface
38-
left_eye = identity["landmarks"]["right_eye"]
39-
right_eye = identity["landmarks"]["left_eye"]
37+
# retinaface sets left and right eyes with respect to the person
38+
left_eye = identity["landmarks"]["left_eye"]
39+
right_eye = identity["landmarks"]["right_eye"]
4040

4141
# eyes are list of float, need to cast them tuple of int
4242
left_eye = tuple(int(i) for i in left_eye)

deepface/detectors/Yolo.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
8181
x, y, w, h = result.boxes.xywh.tolist()[0]
8282
confidence = result.boxes.conf.tolist()[0]
8383

84-
# left_eye_conf = result.keypoints.conf[0][0]
85-
# right_eye_conf = result.keypoints.conf[0][1]
86-
left_eye = result.keypoints.xy[0][0].tolist()
87-
right_eye = result.keypoints.xy[0][1].tolist()
84+
# right_eye_conf = result.keypoints.conf[0][0]
85+
# left_eye_conf = result.keypoints.conf[0][1]
86+
right_eye = result.keypoints.xy[0][0].tolist()
87+
left_eye = result.keypoints.xy[0][1].tolist()
8888

8989
# eyes are list of float, need to cast them tuple of int
9090
left_eye = tuple(int(i) for i in left_eye)

deepface/detectors/YuNet.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]:
9999
{x, y}_{re, le, nt, rcm, lcm} stands for the coordinates of right eye,
100100
left eye, nose tip, the right corner and left corner of the mouth respectively.
101101
"""
102-
(x, y, w, h, x_re, y_re, x_le, y_le) = list(map(int, face[:8]))
102+
(x, y, w, h, x_le, y_le, x_re, y_re) = list(map(int, face[:8]))
103103

104104
# YuNet returns negative coordinates if it thinks part of the detected face
105105
# is outside the frame.

deepface/models/Detector.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ def detect_faces(self, img: np.ndarray) -> List["FacialAreaRegion"]:
2020
where each object contains:
2121
2222
- facial_area (FacialAreaRegion): The facial area region represented
23-
as x, y, w, h, left_eye and right_eye
23+
as x, y, w, h, left_eye and right_eye. left eye and right eye are
24+
eyes on the left and right respectively with respect to the person
25+
instead of observer.
2426
"""
2527
pass
2628

@@ -44,6 +46,21 @@ def __init__(
4446
right_eye: Optional[Tuple[int, int]] = None,
4547
confidence: Optional[float] = None,
4648
):
49+
"""
50+
Initialize a Face object.
51+
52+
Args:
53+
x (int): The x-coordinate of the top-left corner of the bounding box.
54+
y (int): The y-coordinate of the top-left corner of the bounding box.
55+
w (int): The width of the bounding box.
56+
h (int): The height of the bounding box.
57+
left_eye (tuple): The coordinates (x, y) of the left eye with respect to
58+
the person instead of observer. Default is None.
59+
right_eye (tuple): The coordinates (x, y) of the right eye with respect to
60+
the person instead of observer. Default is None.
61+
confidence (float, optional): Confidence score associated with the face detection.
62+
Default is None.
63+
"""
4764
self.x = x
4865
self.y = y
4966
self.w = w
@@ -59,6 +76,14 @@ class DetectedFace:
5976
confidence: float
6077

6178
def __init__(self, img: np.ndarray, facial_area: FacialAreaRegion, confidence: float):
79+
"""
80+
Initialize detected face object.
81+
82+
Args:
83+
img (np.ndarray): detected face image as numpy array
84+
facial_area (FacialAreaRegion): detected face's metadata (e.g. bounding box)
85+
confidence (float): confidence score for face detection
86+
"""
6287
self.img = img
6388
self.facial_area = facial_area
6489
self.confidence = confidence

deepface/modules/detection.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ def extract_faces(
6868
6969
- "facial_area" (Dict[str, Any]): The detected face's regions as a dictionary containing:
7070
- keys 'x', 'y', 'w', 'h' with int values
71-
- keys 'left_eye', 'right_eye' with a tuple of 2 ints as values
71+
- keys 'left_eye', 'right_eye' with a tuple of 2 ints as values.
72+
left eye and right eye are eyes on the left and right respectively with respect
73+
to the person itself instead of observer.
7274
7375
- "confidence" (float): The confidence score associated with the detected face.
7476
"""
@@ -201,8 +203,8 @@ def align_face(
201203
Align a given image horizantally with respect to their left and right eye locations
202204
Args:
203205
img (np.ndarray): pre-loaded image with detected face
204-
left_eye (list or tuple): coordinates of left eye with respect to the you
205-
right_eye(list or tuple): coordinates of right eye with respect to the you
206+
left_eye (list or tuple): coordinates of left eye with respect to the person itself
207+
right_eye(list or tuple): coordinates of right eye with respect to the person itself
206208
Returns:
207209
img (np.ndarray): aligned facial image
208210
"""
@@ -214,6 +216,6 @@ def align_face(
214216
if img.shape[0] == 0 or img.shape[1] == 0:
215217
return img, 0
216218

217-
angle = float(np.degrees(np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0])))
219+
angle = float(np.degrees(np.arctan2(left_eye[1] - right_eye[1], left_eye[0] - right_eye[0])))
218220
img = np.array(Image.fromarray(img).rotate(angle))
219221
return img, angle

package_info.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"version": "0.0.89"
2+
"version": "0.0.90"
33
}

tests/test_extract_faces.py

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ def test_different_detectors():
1919
assert "y" in img_obj["facial_area"].keys()
2020
assert "w" in img_obj["facial_area"].keys()
2121
assert "h" in img_obj["facial_area"].keys()
22+
# is left eye set with respect to the person instead of observer
23+
assert "left_eye" in img_obj["facial_area"].keys()
24+
assert "right_eye" in img_obj["facial_area"].keys()
25+
right_eye = img_obj["facial_area"]["right_eye"]
26+
left_eye = img_obj["facial_area"]["left_eye"]
27+
assert left_eye[0] > right_eye[0]
2228
assert "confidence" in img_obj.keys()
2329

2430
img = img_obj["face"]

tests/visual-test.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
logger.info(df)
5858

5959

60-
expand_areas = [0, 25]
60+
expand_areas = [0]
6161
img_paths = ["dataset/img11.jpg", "dataset/img11_reflection.jpg"]
6262
for expand_area in expand_areas:
6363
for img_path in img_paths:
@@ -86,6 +86,15 @@
8686
assert isinstance(face_obj["facial_area"]["right_eye"][0], int)
8787
assert isinstance(face_obj["facial_area"]["right_eye"][1], int)
8888

89+
# left eye is really the left eye of the person
90+
if (
91+
face_obj["facial_area"]["left_eye"] is not None
92+
and face_obj["facial_area"]["right_eye"] is not None
93+
):
94+
re_x = face_obj["facial_area"]["right_eye"][0]
95+
le_x = face_obj["facial_area"]["left_eye"][0]
96+
assert re_x < le_x, "right eye must be the right eye of the person"
97+
8998
assert isinstance(face_obj["confidence"], float)
9099
assert face_obj["confidence"] <= 1
91100

0 commit comments

Comments
 (0)