| """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): |
| |
| 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" |
| assert face_size_label(BBox(0, 0, 80, 80)) == "medium" |
| assert face_size_label(BBox(0, 0, 120, 120)) == "large" |
|
|
|
|
| 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): |
| |
| 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): |
| |
| landmarks = { |
| "left_eye": (40, 50), |
| "right_eye": (60, 50), |
| "nose": (75, 60), |
| } |
| 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) |
| |
| assert qs_sharp > qs_uniform |
|
|
|
|
| class TestSelectBestFace: |
| def test_selects_frontal(self): |
| |
| 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 |
| 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}, |
| ] |
| 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) == [] |
|
|