public double Match() { try { Transparency = FingerprintTransparency.Current; ReportSupport = Transparency.AcceptsPairing(); int totalRoots = EnumerateRoots(); // https://sourceafis.machinezoo.com/transparency/root-pairs Transparency.LogRootPairs(totalRoots, Roots); double high = 0; int best = -1; for (int i = 0; i < totalRoots; ++i) { double score = TryRoot(Roots[i]); if (best < 0 || score > high) { high = score; best = i; } ClearPairing(); } // https://sourceafis.machinezoo.com/transparency/best-match Transparency.LogBestMatch(best); return(high); } catch (Exception) { CurrentInstance = new MatcherThread(); throw; } finally { Transparency = null; } }
public void Compute(MatcherThread thread) { MinutiaCount = thread.Count; MinutiaScore = Parameters.MinutiaScore * MinutiaCount; MinutiaFractionInProbe = thread.Count / (double)thread.Probe.Minutiae.Length; MinutiaFractionInCandidate = thread.Count / (double)thread.Candidate.Minutiae.Length; MinutiaFraction = 0.5 * (MinutiaFractionInProbe + MinutiaFractionInCandidate); MinutiaFractionScore = Parameters.MinutiaFractionScore * MinutiaFraction; SupportingEdgeSum = 0; SupportedMinutiaCount = 0; MinutiaTypeHits = 0; for (int i = 0; i < thread.Count; ++i) { var pair = thread.Tree[i]; SupportingEdgeSum += pair.SupportingEdges; if (pair.SupportingEdges >= Parameters.MinSupportingEdges) { ++SupportedMinutiaCount; } if (thread.Probe.Minutiae[pair.Probe].Type == thread.Candidate.Minutiae[pair.Candidate].Type) { ++MinutiaTypeHits; } } EdgeCount = thread.Count + SupportingEdgeSum; EdgeScore = Parameters.EdgeScore * EdgeCount; SupportedMinutiaScore = Parameters.SupportedMinutiaScore * SupportedMinutiaCount; MinutiaTypeScore = Parameters.MinutiaTypeScore * MinutiaTypeHits; int innerDistanceRadius = Doubles.RoundToInt(Parameters.DistanceErrorFlatness * Parameters.MaxDistanceError); double innerAngleRadius = Parameters.AngleErrorFlatness * Parameters.MaxAngleError; DistanceErrorSum = 0; AngleErrorSum = 0; for (int i = 1; i < thread.Count; ++i) { var pair = thread.Tree[i]; var probeEdge = new EdgeShape(thread.Probe.Minutiae[pair.ProbeRef], thread.Probe.Minutiae[pair.Probe]); var candidateEdge = new EdgeShape(thread.Candidate.Minutiae[pair.CandidateRef], thread.Candidate.Minutiae[pair.Candidate]); DistanceErrorSum += Math.Max(innerDistanceRadius, Math.Abs(probeEdge.Length - candidateEdge.Length)); AngleErrorSum += Math.Max(innerAngleRadius, DoubleAngle.Distance(probeEdge.ReferenceAngle, candidateEdge.ReferenceAngle)); AngleErrorSum += Math.Max(innerAngleRadius, DoubleAngle.Distance(probeEdge.NeighborAngle, candidateEdge.NeighborAngle)); } DistanceAccuracyScore = 0; AngleAccuracyScore = 0; int distanceErrorPotential = Parameters.MaxDistanceError * Math.Max(0, thread.Count - 1); DistanceAccuracySum = distanceErrorPotential - DistanceErrorSum; DistanceAccuracyScore = Parameters.DistanceAccuracyScore * (distanceErrorPotential > 0 ? DistanceAccuracySum / (double)distanceErrorPotential : 0); double angleErrorPotential = Parameters.MaxAngleError * Math.Max(0, thread.Count - 1) * 2; AngleAccuracySum = angleErrorPotential - AngleErrorSum; AngleAccuracyScore = Parameters.AngleAccuracyScore * (angleErrorPotential > 0 ? AngleAccuracySum / angleErrorPotential : 0); TotalScore = MinutiaScore + MinutiaFractionScore + SupportedMinutiaScore + EdgeScore + MinutiaTypeScore + DistanceAccuracyScore + AngleAccuracyScore; ShapedScore = Shape(TotalScore); }