sanitized facial landmarks, and test for facial landmark sanitizaion

This commit is contained in:
Toys_On_Desk 2025-06-29 15:49:48 +05:30
parent debe68eac1
commit 07dcb87a9b
2 changed files with 122 additions and 5 deletions

View File

@ -80,6 +80,30 @@ def extract_faces(
just available in the result only if anti_spoofing is set to True in input arguments.
"""
def is_valid_landmark(coord, width, height):
"""
Check if a landmark coordinate is within valid image bounds
Args:
coord: (x, y) tuple or None; width; height: image dimensions
Returns True if coord is a valid (x, y) inside the image, else False
Returns:
bool: True if coordinate is valid and within bounds, False otherwise
"""
if coord is None:
return False
# handle case where coord might not be a tuple/list
try:
x, y = coord
except (TypeError, ValueError):
return False
# check if coordinates are within image bounds
return 0 <= x < width and 0 <= y < height
resp_objs = []
# img might be path, base64 or numpy array. Convert it to numpy whatever it is.
@ -149,22 +173,37 @@ def extract_faces(
w = min(width - x - 1, int(current_region.w))
h = min(height - y - 1, int(current_region.h))
# landmark vaildation
landmarks = {
"left_eye":current_region.left_eye,
"right_eye":current_region.right_eye,
"nose":current_region.nose,
"mouth_left":current_region.mouth_left,
"mouth_right":current_region.mouth_right
}
# Sanitize landmarks - set invalid ones to None
for key, value in landmarks.items():
if not is_valid_landmark(value, width, height):
landmarks[key] = None
facial_area = {
"x": x,
"y": y,
"w": w,
"h": h,
"left_eye": current_region.left_eye,
"right_eye": current_region.right_eye,
"left_eye": landmarks["left_eye"],
"right_eye": landmarks["right_eye"],
}
# optional nose, mouth_left and mouth_right fields are coming just for retinaface
if current_region.nose is not None:
facial_area["nose"] = current_region.nose
facial_area["nose"] = landmarks["nose"]
if current_region.mouth_left is not None:
facial_area["mouth_left"] = current_region.mouth_left
facial_area["mouth_left"] = landmarks["mouth_left"]
if current_region.mouth_right is not None:
facial_area["mouth_right"] = current_region.mouth_right
facial_area["mouth_right"] = landmarks["mouth_right"]
resp_obj = {
"face": current_img,

View File

@ -0,0 +1,78 @@
import numpy as np
import pytest
from deepface.modules.detection import extract_faces, DetectedFace, FacialAreaRegion
def sanitize_landmarks(region, width, height):
def is_valid_landmark(coord, width, height):
if coord is None:
return False
try:
x, y = coord
except (TypeError, ValueError):
return False
return 0 <= x < width and 0 <= y < height
landmarks = {
"left_eye": region.left_eye,
"right_eye": region.right_eye,
"nose": region.nose,
"mouth_left": region.mouth_left,
"mouth_right": region.mouth_right,
}
for key, value in landmarks.items():
if not is_valid_landmark(value, 100, 100):
landmarks[key] = None
return landmarks
def test_sanitize_landmarks():
region = FacialAreaRegion(
x=10, y=10, w=50, h=50,
left_eye=(-5, 20), # invalid
right_eye=(20, 200), # invalid
nose=(30, 30), # valid
mouth_left=(150, 20), # invalid
mouth_right=(20, -10), # invalid
confidence=0.9
)
landmarks = sanitize_landmarks(region, 100, 100)
print("Sanitized landmarks:", landmarks)
assert landmarks["left_eye"] is None
assert landmarks["right_eye"] is None
assert landmarks["nose"] == (30, 30)
assert landmarks["mouth_left"] is None
assert landmarks["mouth_right"] is None
print("Test passed: Invalid landmarks are sanitized to None.")
def test_extract_faces_sanitizes_landmarks(monkeypatch):
# Create a dummy image
img = np.zeros((100, 100, 3), dtype=np.uint8)
# Create a DetectedFace with off-image landmarks
facial_area = FacialAreaRegion(
x=10, y=10, w=50, h=50,
left_eye=(-5, 20), # invalid
right_eye=(20, 200), # invalid
nose=(30, 30), # valid
mouth_left=(150, 20), # invalid
mouth_right=(20, -10), # invalid
confidence=0.9
)
detected_face = DetectedFace(img=img, facial_area=facial_area, confidence=0.9)
# Patch detect_faces to return our test face
monkeypatch.setattr("f_deepface.deepface.modules.detection.detect_faces", lambda *args, **kwargs: [detected_face])
# Use a different backend that will call detect_faces
result = extract_faces(img, detector_backend="opencv", enforce_detection=False)
facial_area_out = result[0]["facial_area"]
print("Output facial_area:", facial_area_out) # Debug print
assert facial_area_out["left_eye"] is None
assert facial_area_out["right_eye"] is None
assert facial_area_out.get("nose") == (30, 30)
assert facial_area_out.get("mouth_left") is None
assert facial_area_out.get("mouth_right") is None
if __name__ == "__main__":
test_sanitize_landmarks()