face-intel / tests /unit /test_face_analysis.py
Marwan
Restructure + add reverse face search (PimEyes-style)
f5eeb1c
Raw
History Blame Contribute Delete
4.96 kB
"""Unit tests for cores.face.analysis — quality, blur, pose, clustering."""
from __future__ import annotations
import numpy as np
import pytest
import cv2
from cores.face import (
blur_score, is_blurry, face_size, face_size_label,
estimate_pose_landmark, face_orientation, face_quality_score,
select_best_face, cluster_faces, find_duplicate_faces,
)
from cores.vision.geometry import BBox
class TestBlurScore:
def test_sharp_image_high_score(self):
# Random noise is "sharp"
img = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
assert blur_score(img) > 50
def test_uniform_image_low_score(self):
img = np.full((100, 100, 3), 128, dtype=np.uint8)
assert blur_score(img) < 1.0
def test_is_blurry_threshold(self):
sharp = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
blurry = np.full((100, 100, 3), 128, dtype=np.uint8)
assert is_blurry(sharp, threshold=10) is False
assert is_blurry(blurry, threshold=10) is True
class TestFaceSize:
def test_face_size(self):
assert face_size(BBox(0, 0, 100, 50)) == 5000
def test_face_size_label(self):
assert face_size_label(BBox(0, 0, 40, 40)) == "small" # 1600
assert face_size_label(BBox(0, 0, 80, 80)) == "medium" # 6400
assert face_size_label(BBox(0, 0, 120, 120)) == "large" # 14400
class TestPoseEstimation:
def test_no_landmarks_returns_unknown(self):
yaw, pitch, roll, label = estimate_pose_landmark(None)
assert label == "unknown"
assert yaw == 0.0
def test_frontal_pose(self):
# Symmetric landmarks → near-zero yaw
landmarks = {
"left_eye": (40, 50),
"right_eye": (60, 50),
"nose": (50, 60),
}
yaw, pitch, roll, label = estimate_pose_landmark(landmarks)
assert abs(yaw) < 5.0
assert label == "frontal"
def test_profile_pose(self):
# Nose offset to one side → high yaw
landmarks = {
"left_eye": (40, 50),
"right_eye": (60, 50),
"nose": (75, 60), # shifted right
}
yaw, _, _, label = estimate_pose_landmark(landmarks)
assert yaw > 15.0
assert label in ("profile", "extreme")
class TestFaceQuality:
def test_quality_score_in_range(self):
img = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
bbox = BBox(0, 0, 100, 100)
qs = face_quality_score(img, bbox)
assert 0.0 <= qs <= 1.0
def test_uniform_image_low_quality(self):
"""A uniform (blurry) image should have lower quality than a sharp one."""
uniform = np.full((100, 100, 3), 128, dtype=np.uint8)
sharp = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
bbox = BBox(0, 0, 100, 100)
qs_uniform = face_quality_score(uniform, bbox)
qs_sharp = face_quality_score(sharp, bbox)
# Sharp should score higher than uniform
assert qs_sharp > qs_uniform
class TestSelectBestFace:
def test_selects_frontal(self):
# Two faces: one frontal, one profile
idx = select_best_face(
quality_scores=[0.5, 0.5],
face_sizes=[10000, 10000],
pose_labels=["frontal", "profile"],
)
assert idx == 0
def test_selects_larger(self):
idx = select_best_face(
quality_scores=[0.5, 0.5],
face_sizes=[5000, 15000],
pose_labels=["frontal", "frontal"],
)
assert idx == 1
class TestClusterFaces:
def test_clusters_identical_embeddings(self):
emb = np.random.randn(128).astype(np.float32)
embeddings = [emb, emb, emb]
clusters = cluster_faces(embeddings, threshold=0.9)
assert len(clusters) == 1
assert clusters[0]["num_faces"] == 3
def test_separates_different_embeddings(self):
emb1 = np.random.randn(128).astype(np.float32)
emb2 = -emb1 # opposite direction
embeddings = [emb1, emb2]
clusters = cluster_faces(embeddings, threshold=0.9)
assert len(clusters) == 2
def test_empty_embeddings(self):
assert cluster_faces([]) == []
class TestDuplicateFaces:
def test_overlapping_boxes_detected(self):
boxes = [
{"x": 0, "y": 0, "w": 100, "h": 100},
{"x": 10, "y": 10, "w": 100, "h": 100}, # overlaps heavily
]
dups = find_duplicate_faces(boxes, iou_threshold=0.5)
assert 1 in dups
def test_non_overlapping_not_duplicates(self):
boxes = [
{"x": 0, "y": 0, "w": 50, "h": 50},
{"x": 200, "y": 200, "w": 50, "h": 50},
]
dups = find_duplicate_faces(boxes)
assert dups == []
def test_single_face_no_duplicates(self):
boxes = [{"x": 0, "y": 0, "w": 100, "h": 100}]
assert find_duplicate_faces(boxes) == []