FingerprintTemplate(MutableTemplate mutable) { Size = mutable.Size; var minutiae = from m in mutable.Minutiae orderby((m.Position.X * Prime) + m.Position.Y) * Prime, m.Position.X, m.Position.Y, m.Direction, m.Type select new ImmutableMinutia(m); Minutiae = minutiae.ToArray(); // https://sourceafis.machinezoo.com/transparency/shuffled-minutiae FingerprintTransparency.Current.Log("shuffled-minutiae", () => Mutable()); Edges = NeighborEdge.BuildTable(Minutiae); }
static List <MatchingPair> FindMatchingPairs(NeighborEdge[] probeStar, NeighborEdge[] candidateStar) { byte complementaryAngleError = Angle.Complementary(FingerprintMatcher.MaxAngleError); var results = new List <MatchingPair>(); Range range = new Range(); for (int candidateIndex = 0; candidateIndex < candidateStar.Length; ++candidateIndex) { NeighborEdge candidateEdge = candidateStar[candidateIndex]; while (range.Begin < probeStar.Length && probeStar[range.Begin].Edge.Length < candidateEdge.Edge.Length - FingerprintMatcher.MaxDistanceError) { ++range.Begin; } if (range.End < range.Begin) { range.End = range.Begin; } while (range.End < probeStar.Length && probeStar[range.End].Edge.Length <= candidateEdge.Edge.Length + FingerprintMatcher.MaxDistanceError) { ++range.End; } for (int probeIndex = range.Begin; probeIndex < range.End; ++probeIndex) { var probeEdge = probeStar[probeIndex]; byte referenceDiff = Angle.Difference(probeEdge.Edge.ReferenceAngle, candidateEdge.Edge.ReferenceAngle); if (referenceDiff <= FingerprintMatcher.MaxAngleError || referenceDiff >= complementaryAngleError) { byte neighborDiff = Angle.Difference(probeEdge.Edge.NeighborAngle, candidateEdge.Edge.NeighborAngle); if (neighborDiff <= FingerprintMatcher.MaxAngleError || neighborDiff >= complementaryAngleError) { results.Add(new MatchingPair() { Pair = new MinutiaPair() { Probe = probeEdge.Neighbor, Candidate = candidateEdge.Neighbor }, Distance = candidateEdge.Edge.Length }); } } } } return(results); }
public static NeighborEdge[][] BuildTable(ImmutableMinutia[] minutiae) { var edges = new NeighborEdge[minutiae.Length][]; var star = new List <NeighborEdge>(); var allSqDistances = new int[minutiae.Length]; for (int reference = 0; reference < edges.Length; ++reference) { var referencePosition = minutiae[reference].Position; int maxSqDistance = Int32.MaxValue; if (minutiae.Length - 1 > Parameters.EdgeTableNeighbors) { for (int neighbor = 0; neighbor < minutiae.Length; ++neighbor) { allSqDistances[neighbor] = (referencePosition - minutiae[neighbor].Position).LengthSq; } Array.Sort(allSqDistances); maxSqDistance = allSqDistances[Parameters.EdgeTableNeighbors]; } for (int neighbor = 0; neighbor < minutiae.Length; ++neighbor) { if (neighbor != reference && (referencePosition - minutiae[neighbor].Position).LengthSq <= maxSqDistance) { star.Add(new NeighborEdge(minutiae, reference, neighbor)); } } star.Sort((a, b) => { int lengthCmp = a.Length.CompareTo(b.Length); if (lengthCmp != 0) { return(lengthCmp); } return(a.Neighbor.CompareTo(b.Neighbor)); }); while (star.Count > Parameters.EdgeTableNeighbors) { star.RemoveAt(star.Count - 1); } edges[reference] = star.ToArray(); star.Clear(); } // https://sourceafis.machinezoo.com/transparency/edge-table FingerprintTransparency.Current.Log("edge-table", edges); return(edges); }
void BuildEdgeTable() { const int maxDistance = 490; const int maxNeighbors = 9; EdgeTable = new NeighborEdge[Minutiae.Count][]; var edges = new List <NeighborEdge>(); var allSqDistances = new int[Minutiae.Count]; for (int reference = 0; reference < EdgeTable.Length; ++reference) { Point referencePosition = Minutiae[reference].Position; int sqMaxDistance = MathEx.Sq(maxDistance); if (Minutiae.Count - 1 > maxNeighbors) { for (int neighbor = 0; neighbor < Minutiae.Count; ++neighbor) { allSqDistances[neighbor] = (referencePosition - Minutiae[neighbor].Position).SqLength; } Array.Sort(allSqDistances); sqMaxDistance = allSqDistances[maxNeighbors]; } for (int neighbor = 0; neighbor < Minutiae.Count; ++neighbor) { if (neighbor != reference && (referencePosition - Minutiae[neighbor].Position).SqLength <= sqMaxDistance) { NeighborEdge record = new NeighborEdge(); record.Edge = new EdgeShape(this, reference, neighbor); record.Neighbor = neighbor; edges.Add(record); } } edges.Sort(NeighborEdgeComparer.Instance); if (edges.Count > maxNeighbors) { edges.RemoveRange(maxNeighbors, edges.Count - maxNeighbors); } EdgeTable[reference] = edges.ToArray(); edges.Clear(); } }
static List<MatchingPair> FindMatchingPairs(NeighborEdge[] probeStar, NeighborEdge[] candidateStar) { byte complementaryAngleError = Angle.Complementary(FingerprintMatcher.MaxAngleError); var results = new List<MatchingPair>(); Range range = new Range(); for (int candidateIndex = 0; candidateIndex < candidateStar.Length; ++candidateIndex) { NeighborEdge candidateEdge = candidateStar[candidateIndex]; while (range.Begin < probeStar.Length && probeStar[range.Begin].Edge.Length < candidateEdge.Edge.Length - FingerprintMatcher.MaxDistanceError) ++range.Begin; if (range.End < range.Begin) range.End = range.Begin; while (range.End < probeStar.Length && probeStar[range.End].Edge.Length <= candidateEdge.Edge.Length + FingerprintMatcher.MaxDistanceError) ++range.End; for (int probeIndex = range.Begin; probeIndex < range.End; ++probeIndex) { var probeEdge = probeStar[probeIndex]; byte referenceDiff = Angle.Difference(probeEdge.Edge.ReferenceAngle, candidateEdge.Edge.ReferenceAngle); if (referenceDiff <= FingerprintMatcher.MaxAngleError || referenceDiff >= complementaryAngleError) { byte neighborDiff = Angle.Difference(probeEdge.Edge.NeighborAngle, candidateEdge.Edge.NeighborAngle); if (neighborDiff <= FingerprintMatcher.MaxAngleError || neighborDiff >= complementaryAngleError) results.Add(new MatchingPair() { Pair = new MinutiaPair() { Probe = probeEdge.Neighbor, Candidate = candidateEdge.Neighbor }, Distance = candidateEdge.Edge.Length }); } } } return results; }