J
File size: 3,992 Bytes
85fa7d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""
Face Comparator - Comparaci贸n de embeddings con niveles de confianza adaptativos
"""

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from loguru import logger


class FaceComparator:
    """
    Compara embeddings faciales con umbrales adaptativos.
    Implementa el sistema de 3 niveles: Seguro, Probable, Descartado.
    """
    
    def __init__(self, threshold=0.75):
        """
        Args:
            threshold: Umbral base de similitud (0.0-1.0)
        """
        self.threshold = threshold
        
        # Umbrales adaptativos
        self.SECURE_MATCH = 0.85  # >85% = Match Seguro
        self.PROBABLE_MATCH = 0.72  # 72-85% = Coincidencia Probable
        # <72% = Descartado
    
    def calculate_similarity(self, embedding1, embedding2):
        """
        Calcula la similitud coseno entre dos embeddings.
        
        Args:
            embedding1: Vector de embedding 1
            embedding2: Vector de embedding 2
            
        Returns:
            Similitud entre 0.0 y 1.0
        """
        emb1 = np.array(embedding1).reshape(1, -1)
        emb2 = np.array(embedding2).reshape(1, -1)
        
        similarity = cosine_similarity(emb1, emb2)[0][0]
        
        return float(similarity)
    
    def verify_identity(self, source_emb, target_emb):
        """
        Verifica identidad con an谩lisis de confianza adaptativo.
        
        Returns:
            Tupla (nivel_confianza: str, similitud: float)
        """
        similarity = self.calculate_similarity(source_emb, target_emb)
        
        if similarity > self.SECURE_MATCH:
            confidence_level = "Match Seguro"
            logger.info(f"Match Seguro: {similarity:.3f}")
        elif similarity > self.PROBABLE_MATCH:
            confidence_level = "Coincidencia Probable (Requiere revisi贸n)"
            logger.info(f"Coincidencia Probable: {similarity:.3f}")
        else:
            confidence_level = "Descartado"
            logger.debug(f"Descartado: {similarity:.3f}")
        
        return confidence_level, similarity
    
    def compare_embeddings(self, query_embedding, candidate_results):
        """
        Compara el embedding query con m煤ltiples candidatos.
        
        Args:
            query_embedding: Embedding de la imagen query
            candidate_results: Lista de resultados con embeddings
            
        Returns:
            Lista de matches verificados ordenados por similitud
        """
        verified_matches = []
        
        for candidate in candidate_results:
            if 'embedding' not in candidate:
                continue
            
            # Calcular similitud
            similarity = self.calculate_similarity(
                query_embedding,
                candidate['embedding']
            )
            
            # Solo incluir si supera el umbral
            if similarity >= self.threshold:
                # Determinar nivel de confianza
                if similarity > self.SECURE_MATCH:
                    confidence_level = "Match Seguro"
                elif similarity > self.PROBABLE_MATCH:
                    confidence_level = "Coincidencia Probable"
                else:
                    confidence_level = "Baja confianza"
                
                candidate['similarity'] = similarity
                candidate['confidence_level'] = confidence_level
                candidate['embedding_distance'] = 1 - similarity
                candidate['verified'] = True
                
                verified_matches.append(candidate)
                
                logger.debug(f"Match verificado: {similarity:.3f} - {confidence_level}")
        
        # Ordenar por similitud descendente
        verified_matches.sort(key=lambda x: x['similarity'], reverse=True)
        
        logger.info(f"Comparaci贸n completada: {len(verified_matches)}/{len(candidate_results)} verificados")
        
        return verified_matches