File size: 1,687 Bytes
9b76f08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
"""In-memory FAISS gallery assigning persistent person IDs to face embeddings.

Duplicated from ../app/identity_store.py for this standalone web demo deployable
(see face_engine.py for why). Here, one instance lives per browser session
(held in gr.State), not per process - nothing persists between visitors.
"""
from typing import List

import faiss
import numpy as np


class IdentityStore:
    """Cosine-similarity gallery over L2-normalized ArcFace embeddings.

    Uses FAISS IndexFlatIP (inner product), which equals cosine similarity
    when all stored and query vectors are L2-normalized.
    """

    def __init__(self, embedding_dim: int = 512, match_threshold: float = 0.38) -> None:
        self.embedding_dim = embedding_dim
        self.match_threshold = match_threshold
        self.index = faiss.IndexFlatIP(embedding_dim)
        self._next_person_id = 1
        self.person_ids: List[int] = []

    def match_or_register(self, normed_embedding: np.ndarray) -> int:
        """Finds the closest known identity; registers a new one if none is close enough."""
        query = normed_embedding.astype(np.float32).reshape(1, -1)

        if self.index.ntotal > 0:
            similarities, indices = self.index.search(query, 1)
            best_similarity = float(similarities[0, 0])
            best_index = int(indices[0, 0])
            if best_similarity >= self.match_threshold:
                return self.person_ids[best_index]

        person_id = self._next_person_id
        self._next_person_id += 1
        self.index.add(query)
        self.person_ids.append(person_id)
        return person_id

    def __len__(self) -> int:
        return self.index.ntotal