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>
49 lines
1.2 KiB
Python
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
|