| """ | |
| Face verification utilities. | |
| This module provides functions to compare face embeddings and decide | |
| whether two faces belong to the same person. It relies on | |
| ``extract_embeddings.extract_embedding`` to obtain the embeddings. | |
| """ | |
| from typing import Tuple, Optional | |
| import numpy as np | |
| from PIL import Image | |
| from .extract_embeddings import extract_embedding | |
| def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float: | |
| """Compute the cosine similarity between two vectors. | |
| Parameters | |
| ---------- | |
| a, b: np.ndarray | |
| 1D vectors of the same length. | |
| Returns | |
| ------- | |
| float | |
| The cosine similarity ranging from -1 (opposite) to 1 (identical). | |
| """ | |
| return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))) | |
| def verify_images(img1: Image.Image, img2: Image.Image, threshold: float = 0.8, device: str = "cpu") -> Tuple[Optional[float], bool, str]: | |
| """Verify whether two images depict the same person. | |
| This function detects faces in each image, extracts embeddings and | |
| computes the cosine similarity. A threshold decides whether the | |
| similarity represents the same identity. | |
| Parameters | |
| ---------- | |
| img1, img2: PIL.Image.Image | |
| The two images to compare. | |
| threshold: float, optional | |
| Similarity threshold above which the faces are considered the | |
| same person. Defaults to 0.8. | |
| device: str, optional | |
| Device to run the embedding extraction on. Defaults to ``"cpu"``. | |
| Returns | |
| ------- | |
| Tuple[Optional[float], bool, str] | |
| A tuple of (similarity score, decision, message). If no face is | |
| detected in either image, the similarity is ``None`` and the | |
| decision is ``False``. | |
| """ | |
| emb1 = extract_embedding(img1, device=device) | |
| emb2 = extract_embedding(img2, device=device) | |
| if emb1 is None or emb2 is None: | |
| return None, False, "Face not detected in one or both images." | |
| sim = cosine_similarity(emb1, emb2) | |
| is_same = sim >= threshold | |
| return sim, is_same, "Same person" if is_same else "Different people" | |
| __all__ = ["verify_images", "cosine_similarity"] |