vigilar/tests/unit/test_face.py
Aaron D. Lee a5ddc53cf0 feat(S3): FaceRecognizer with in-memory embedding matching
Add FaceRecognizer class that loads face encodings from the database,
supports runtime add_encoding(), and matches new encodings by L2 distance.
face_recognition import is deferred so the class works without dlib installed.
FaceResult dataclass carries profile_id, name, confidence, crop, and bbox.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 18:59:07 -04:00

49 lines
1.2 KiB
Python

import numpy as np
import pytest
from vigilar.detection.face import FaceRecognizer, FaceResult
def test_face_recognizer_init():
fr = FaceRecognizer(match_threshold=0.6)
assert fr._threshold == 0.6
assert fr.is_loaded is False
def test_load_profiles_empty(test_db):
fr = FaceRecognizer()
fr.load_profiles(test_db)
assert fr.is_loaded is True
assert len(fr._known_encodings) == 0
def test_add_encoding():
fr = FaceRecognizer()
fr.is_loaded = True
enc = np.random.rand(128).astype(np.float32)
fr.add_encoding(1, enc)
assert len(fr._known_encodings) == 1
def test_find_match():
fr = FaceRecognizer(match_threshold=0.6)
fr.is_loaded = True
enc = np.random.rand(128).astype(np.float32)
fr.add_encoding(1, enc)
result = fr._find_match(enc)
assert result is not None
assert result[0] == 1
def test_no_match():
fr = FaceRecognizer(match_threshold=0.6)
fr.is_loaded = True
fr.add_encoding(1, np.ones(128, dtype=np.float32))
result = fr._find_match(-np.ones(128, dtype=np.float32))
assert result is None
def test_face_result_dataclass():
crop = np.zeros((100, 100, 3), dtype=np.uint8)
r = FaceResult(1, "Bob", 0.85, crop, (10, 20, 50, 50))
assert r.profile_id == 1