static bool IsWithinGapLimits(SkeletonMinutia end1, SkeletonMinutia end2) { int distanceSq = (end1.Position - end2.Position).LengthSq; if (distanceSq <= Integers.Sq(Parameters.MaxRuptureSize)) { return(true); } if (distanceSq > Integers.Sq(Parameters.MaxGapSize)) { return(false); } double gapDirection = DoubleAngle.Atan(end1.Position, end2.Position); double direction1 = DoubleAngle.Atan(end1.Position, AngleSampleForGapRemoval(end1)); if (DoubleAngle.Distance(direction1, DoubleAngle.Opposite(gapDirection)) > Parameters.MaxGapAngle) { return(false); } double direction2 = DoubleAngle.Atan(end2.Position, AngleSampleForGapRemoval(end2)); if (DoubleAngle.Distance(direction2, gapDirection) > Parameters.MaxGapAngle) { return(false); } return(true); }
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); }