Skip to content

Commit adfa54b

Browse files
authored
Merge pull request #80 from UmutDeniz26/master
Two-fold Performance Enhancement by Optimizing Face Extraction Function When align_first == True
2 parents 721d8a7 + a5c47c6 commit adfa54b

File tree

2 files changed

+55
-12
lines changed

2 files changed

+55
-12
lines changed

retinaface/RetinaFace.py

+54-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import warnings
33
import logging
4-
from typing import Union, Any, Optional, Dict
4+
from typing import Union, Any, Optional, Dict, Tuple
55

66
import numpy as np
77
import tensorflow as tf
@@ -270,19 +270,62 @@ def extract_faces(
270270
nose = landmarks["nose"]
271271
# mouth_right = landmarks["mouth_right"]
272272
# mouth_left = landmarks["mouth_left"]
273-
facial_img = postprocess.alignment_procedure(facial_img, right_eye, left_eye, nose)
273+
facial_img, rotate_angle, rotate_direction = postprocess.alignment_procedure(
274+
facial_img, right_eye, left_eye, nose
275+
)
274276

275277
if align_first is True and len(obj) == 1:
276-
facial_img = extract_faces(
277-
img_path=facial_img,
278-
threshold=threshold,
279-
model=model,
280-
allow_upscaling=allow_upscaling,
281-
expand_face_area=expand_face_area,
282-
align=False,
283-
align_first=False,
284-
)[0][:, :, ::-1]
278+
facial_area = rotate_facial_area(
279+
facial_area, rotate_angle, rotate_direction, img.shape
280+
)
281+
# Expand the facial area to be extracted and stay within img.shape limits
282+
x1 = max(0, facial_area[0] - int((facial_area[2] * expand_face_area) / 100))
283+
y1 = max(0, facial_area[1] - int((facial_area[3] * expand_face_area) / 100))
284+
x2 = min(
285+
img.shape[1], facial_area[2] + int((facial_area[2] * expand_face_area) / 100)
286+
)
287+
y2 = min(
288+
img.shape[0], facial_area[3] + int((facial_area[3] * expand_face_area) / 100)
289+
)
290+
facial_img = facial_img[y1:y2, x1:x2]
285291

286292
resp.append(facial_img[:, :, ::-1])
287293

288294
return resp
295+
296+
def rotate_facial_area(facial_area: Tuple[int, int, int, int], angle: float, direction:
297+
int, size: Tuple[int, int]) -> Tuple[int, int, int, int]:
298+
"""
299+
Rotate the facial area around its center.
300+
301+
Args:
302+
facial_area (tuple of int): Representing the (x1, y1, x2, y2) of the facial area.
303+
angle (float): Angle of rotation in degrees.
304+
direction (int): Direction of rotation (-1 for clockwise, 1 for counterclockwise).
305+
size (tuple of int): Tuple representing the size of the image (width, height).
306+
307+
Returns:
308+
tuple of int: Representing the new coordinates (x1, y1, x2, y2) of the rotated facial area.
309+
"""
310+
# Angle in radians
311+
angle = angle * np.pi / 180
312+
313+
# Translate the facial area to the center of the image
314+
x = (facial_area[0] + facial_area[2]) / 2 - size[1] / 2
315+
y = (facial_area[1] + facial_area[3]) / 2 - size[0] / 2
316+
317+
# Rotate the facial area
318+
x_new = x * np.cos(angle) + y * direction * np.sin(angle)
319+
y_new = -x * direction * np.sin(angle) + y * np.cos(angle)
320+
321+
# Translate the facial area back to the original position
322+
x_new = x_new + size[1] / 2
323+
y_new = y_new + size[0] / 2
324+
325+
# Calculate the new facial area
326+
x1 = x_new - (facial_area[2] - facial_area[0]) / 2
327+
y1 = y_new - (facial_area[3] - facial_area[1]) / 2
328+
x2 = x_new + (facial_area[2] - facial_area[0]) / 2
329+
y2 = y_new + (facial_area[3] - facial_area[1]) / 2
330+
331+
return (int(x1), int(y1), int(x2), int(y2))

retinaface/commons/postprocess.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def alignment_procedure(img: np.ndarray, left_eye: tuple, right_eye: tuple, nose
8888

8989
# -----------------------
9090

91-
return img
91+
return img, angle, direction
9292

9393

9494
def bbox_pred(boxes, box_deltas):

0 commit comments

Comments
 (0)