Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and strengthen rotate_facial_area #1047

Merged
51 changes: 33 additions & 18 deletions deepface/detectors/DetectorWrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,30 +103,33 @@ def detect_faces(
right_eye = facial_area.right_eye
confidence = facial_area.confidence

# expand the facial area to be extracted and stay within img.shape limits
x2 = max(0, x - int((w * expand_percentage) / 100)) # expand left
y2 = max(0, y - int((h * expand_percentage) / 100)) # expand top
w2 = min(img.shape[1], w + int((w * 2 * expand_percentage) / 100)) # expand right
h2 = min(img.shape[0], h + int((h * 2 * expand_percentage) / 100)) # expand bottom
if expand_percentage > 0:
# Expand the facial region height and width by the provided percentage
# ensuring that the expanded region stays within img.shape limits
expanded_w = w + int(w * expand_percentage / 100)
expanded_h = h + int(h * expand_percentage / 100)

# extract detected face unaligned
detected_face = img[int(y2) : int(y2 + h2), int(x2) : int(x2 + w2)]
x = max(0, x - int((expanded_w - w) / 2))
AndreaLanfranchi marked this conversation as resolved.
Show resolved Hide resolved
y = max(0, y - int((expanded_h - h) / 2))
AndreaLanfranchi marked this conversation as resolved.
Show resolved Hide resolved
w = min(img.shape[1] - x, expanded_w)
AndreaLanfranchi marked this conversation as resolved.
Show resolved Hide resolved
h = min(img.shape[0] - y, expanded_h)
AndreaLanfranchi marked this conversation as resolved.
Show resolved Hide resolved

# aligning detected face causes a lot of black pixels
# if align is True:
# detected_face, _ = detection.align_face(
# img=detected_face, left_eye=left_eye, right_eye=right_eye
# )
# extract detected face unaligned
detected_face = img[int(y) : int(y + h), int(x) : int(x + w)]

# align original image, then find projection of detected face area after alignment
if align is True: # and left_eye is not None and right_eye is not None:
aligned_img, angle = detection.align_face(
img=img, left_eye=left_eye, right_eye=right_eye
)
x1_new, y1_new, x2_new, y2_new = rotate_facial_area(
facial_area=(x2, y2, x2 + w2, y2 + h2), angle=angle, direction=1, size=img.shape
rotated_x1, rotated_y1, rotated_x2, rotated_y2 = rotate_facial_area(
facial_area=(x, y, x + w, y + h),
AndreaLanfranchi marked this conversation as resolved.
Show resolved Hide resolved
angle=angle,
size=(img.shape[0], img.shape[1])
)
detected_face = aligned_img[int(y1_new) : int(y2_new), int(x1_new) : int(x2_new)]
detected_face = aligned_img[
int(rotated_y1) : int(rotated_y2),
int(rotated_x1) : int(rotated_x2)]

result = DetectedFace(
img=detected_face,
Expand All @@ -140,7 +143,9 @@ def detect_faces(


def rotate_facial_area(
facial_area: Tuple[int, int, int, int], angle: float, direction: int, size: Tuple[int, int]
facial_area: Tuple[int, int, int, int],
angle: float,
size: Tuple[int, int]
) -> Tuple[int, int, int, int]:
"""
Rotate the facial area around its center.
Expand All @@ -149,14 +154,24 @@ def rotate_facial_area(
Args:
facial_area (tuple of int): Representing the (x1, y1, x2, y2) of the facial area.
x2 is equal to x1 + w1, and y2 is equal to y1 + h1
angle (float): Angle of rotation in degrees.
direction (int): Direction of rotation (-1 for clockwise, 1 for counterclockwise).
angle (float): Angle of rotation in degrees. Its sign determines the direction of rotation.
Note that angles > 360 degrees are normalized to the range [0, 360).
size (tuple of int): Tuple representing the size of the image (width, height).

Returns:
rotated_coordinates (tuple of int): Representing the new coordinates
(x1, y1, x2, y2) or (x1, y1, x1+w1, y1+h1) of the rotated facial area.
"""

# Normalize the witdh of the angle so we don't have to
# worry about rotations greater than 360 degrees.
# We workaround the quirky behavior of the modulo operator
# for negative angle values.
direction = 1 if angle >= 0 else -1
angle = abs(angle) % 360
if angle == 0:
serengil marked this conversation as resolved.
Show resolved Hide resolved
return facial_area

# Angle in radians
angle = angle * np.pi / 180

Expand Down
Loading