/// [1:N] /// <summary> /// Compara uma <see cref="Pessoa"/> contra um conjunto de outras <see cref="Pessoa"/>s e retorna o(s) melhore(s) match(s) /// </summary> /// <param name="probe">pessoa para procurar na base de dados</param> /// <param name="candidates">base de dados de pessoas a ser pesquisado</param> /// <returns>Todo objeto <see cref="Pessoa"/> correspondente na base de dados ou vazio se /// não existir match. Os resultados são classificados por pontuação em ordem decrescente. Se voce precisar apenas do melhor match, /// chame o método <see cref="Enumerable.FirstOrDefault{T}(IEnumerable{T})"/> na base de dados retornada.</returns> /// <remarks> /// <para> /// Compare o probe<see cref="Pessoa"/> para todos os candidatos <see cref="Pessoa"/>s e retorne o candidato mais similar. /// Chamando <see cref="Identificar"/>é quase a mesma coisa que chamar o <see cref="Verificar"/> em um loop /// exceto que o <see cref="Identificar"/> é bem mais rapido que o loop do <see cref="Verificar"/>. /// Se não houver candidato ou pontuação igual ou maior que o <see cref="Threshold"/>, <see cref="Identificar"/> retorna /// uma base de dados vazia. /// </para> /// <para> /// A maioria das aplicações precisam apenas do melhor match que pode ser obtido chamando o método /// <see cref="Enumerable.FirstOrDefault{T}(IEnumerable{T})"/> na base de dados retornada. /// Pontuação correspondente para cada<see cref="Pessoa"/> retornado pode ser obtido chamando o /// <see cref="Verificar"/> no probe <see cref="Pessoa"/> e o matching <see cref="Pessoa"/>. /// </para> /// <para> /// <see cref="Pessoa"/>s que passar por esse método deve ter o <see cref="Fingerprint.Template"/> valido. /// para cada <see cref="Fingerprint"/>, i.e. eles precisam ter passado pelo método <see cref="Extrair"/> antes. /// </para> /// </remarks> /// <seealso cref="Threshold"/> /// <seealso cref="MinMatches"/> /// <seealso cref="Verificar"/> public IEnumerable <Pessoa> Identificar(Pessoa probe, IEnumerable <Pessoa> candidates) { probe.CheckForNulls(); Pessoa[] candidateArray = candidates.ToArray(); BestMatchSkipper.PersonsSkipScore[] results; lock (this) { BestMatchSkipper collector = new BestMatchSkipper(candidateArray.Length, MinMatches - 1); Parallel.ForEach(probe.Fingerprints, probeFp => { List <int> personsByFingerprint = new List <int>(); List <Template> candidateTemplates = FlattenHierarchy(candidateArray, probeFp.Dedo, out personsByFingerprint); ParallelMatcher.PreparedProbe probeIndex = Matcher.Prepare(probeFp.Decoded); float[] scores = Matcher.Match(probeIndex, candidateTemplates); lock (collector) for (int i = 0; i < scores.Length; ++i) { collector.AddScore(personsByFingerprint[i], scores[i]); } }); results = collector.GetSortedScores(); } return(GetMatchingCandidates(candidateArray, results)); }
/// [1:1] /// <summary> /// Calcular o score de similaridade entre duas <see cref="Pessoa"/>s. /// </summary> /// <param name="probe">Primeira das duas pessoas para comparar</param> /// <param name="candidate">Segunda das duas pessoas para comparar</param> /// <returns> o índice de Similaridade indicando semelhança entre as duas pessoas ou 0 if se não existir match.</returns> /// <remarks> /// <para> /// O método <see cref="Verificar"/> compara duas <see cref="Pessoa"/>s, <see cref="Fingerprint"/> pela <see cref="Fingerprint"/>, e retorna /// um [float] indice de similaridade que indica o grau de semelhança entre /// as duas <see cref="Pessoa"/>s. Se esse score ficar abaixo do <see cref="Threshold"/>, o método <see cref="Verificar"/> retorna zero matchs. /// </para> /// <para> /// <see cref="Pessoa"/>s que passam por esse método devem ter o <see cref="Fingerprint.Template"/> valido /// para toda <see cref="Fingerprint"/>, i.e. devem ser passados pelo método <see cref="Extrair"/> antes. /// </para> /// </remarks> /// <seealso cref="Threshold"/> /// <seealso cref="MinMatches"/> /// <seealso cref="Identificar"/> public float Verificar(Pessoa probe, Pessoa candidate) { lock (this) { probe.CheckForNulls(); candidate.CheckForNulls(); BestMatchSkipper collector = new BestMatchSkipper(1, MinMatches - 1); Parallel.ForEach(probe.Fingerprints, probeFp => { var candidateTemplates = (from candidateFp in candidate.Fingerprints where IsCompatibleFinger(probeFp.Dedo, candidateFp.Dedo) select candidateFp.Decoded).ToList(); ParallelMatcher.PreparedProbe probeIndex = Matcher.Prepare(probeFp.Decoded); float[] scores = Matcher.Match(probeIndex, candidateTemplates); lock (collector) foreach (float score in scores) { collector.AddScore(0, score); } }); return(ApplyThreshold(collector.GetSkipScore(0))); } }