public IEnumerable<MinutiaPair> GetFilteredRoots(ProbeIndex probeIndex, Template candidateTemplate, Predicate<EdgeShape> shapeFilter) { if (LookupCounter >= MaxEdgeLookups) yield break; var edgeConstructor = new EdgeConstructor(); for (int step = 1; step < candidateTemplate.Minutiae.Length; ++step) for (int pass = 0; pass < step + 1; ++pass) for (int candidateReference = pass; candidateReference < candidateTemplate.Minutiae.Length; candidateReference += step + 1) { int candidateNeighbor = (candidateReference + step) % candidateTemplate.Minutiae.Length; var candidateEdge = edgeConstructor.Construct(candidateTemplate, candidateReference, candidateNeighbor); if (shapeFilter(candidateEdge)) { for (var match = HashLookup.Select(candidateEdge); match != null; match = HashLookup.Next()) { var pair = new MinutiaPair(match.Location.Reference, candidateReference); if (Logger.IsActive) Logger.Log(pair); yield return pair; ++LookupCounter; if (LookupCounter >= MaxEdgeLookups) yield break; } } } }
public void BuildIndex(Template probe, ProbeIndex index) { index.Template = probe; index.Edges = ParameterSet.ClonePrototype(EdgeTablePrototype); index.Edges.Reset(probe); index.EdgeHash = new EdgeHash(probe, EdgeLookup); }
public IEnumerable<MinutiaPair> GetRoots(ProbeIndex probeIndex, Template candidateTemplate) { LookupCounter = 0; HashLookup.Reset(probeIndex.EdgeHash); return GetFilteredRoots(probeIndex, candidateTemplate, shape => shape.Length >= MinEdgeLength) .Concat(GetFilteredRoots(probeIndex, candidateTemplate, shape => shape.Length < MinEdgeLength)); }
public EdgeHash(Template template, EdgeLookup lookup) { EdgeLookup = lookup; var edgeConstructor = new EdgeConstructor(); for (int referenceMinutia = 0; referenceMinutia < template.Minutiae.Length; ++referenceMinutia) for (int neighborMinutia = 0; neighborMinutia < template.Minutiae.Length; ++neighborMinutia) if (referenceMinutia != neighborMinutia) { var edge = new IndexedEdge() { Shape = edgeConstructor.Construct(template, referenceMinutia, neighborMinutia), Location = new EdgeLocation(referenceMinutia, neighborMinutia) }; foreach (var hash in lookup.HashCoverage(edge.Shape)) { object value; List<IndexedEdge> list; if (!Hash.TryGetValue(hash, out value)) Hash[hash] = edge; else { list = value as List<IndexedEdge>; if (list == null) { Hash[hash] = list = new List<IndexedEdge>(1); list.Add((IndexedEdge)value); } list.Add(edge); } } } }
public void SelectProbe(Template probe) { ProbeIndex = new PairInfo[probe.Minutiae.Length]; PairList = new PairInfo[probe.Minutiae.Length]; for (int i = 0; i < PairList.Length; ++i) PairList[i] = new PairInfo(); PairCount = 0; }
public EdgeShape Construct(Template template, int reference, int neighbor) { PolarPoint polar = Angle.ToPolar(Calc.Difference(template.Minutiae[neighbor].Position, template.Minutiae[reference].Position)); EdgeShape edge; edge.Length = (short)polar.Distance; edge.ReferenceAngle = Angle.Difference(template.Minutiae[reference].Direction, polar.Angle); edge.NeighborAngle = Angle.Difference(template.Minutiae[neighbor].Direction, Angle.Opposite(polar.Angle)); return edge; }
public void SelectCandidate(Template candidate) { if (CandidateIndex == null || CandidateIndex.Length < candidate.Minutiae.Length) CandidateIndex = new PairInfo[candidate.Minutiae.Length]; else { for (int i = 0; i < CandidateIndex.Length; ++i) CandidateIndex[i] = null; } }
public PreparedProbe Prepare(Template probe) { PreparedProbe prepared = new PreparedProbe(); MinutiaMatcher matcher = DequeueMatcher(); try { matcher.BuildIndex(probe, prepared.ProbeIndex); } finally { EnqueueMatcher(matcher); } return prepared; }
public float Match(Template candidate) { PrepareCandidate(candidate); int rootIndex = 0; int triangleIndex = 0; float bestScore = 0; MinutiaPair bestRoot = new MinutiaPair(); int bestRootIndex = -1; foreach (MinutiaPair root in RootSelector.GetRoots(Probe, candidate)) { float score = TryRoot(root, candidate); if (score > bestScore) { bestScore = score; bestRoot = root; bestRootIndex = rootIndex; } ++rootIndex; if (rootIndex >= MaxTriedRoots) break; if (Pairing.Count >= 3) { ++triangleIndex; if (triangleIndex >= MaxTriedTriangles) break; } } Logger.Log("Score", bestScore); Logger.Log("BestRootIndex", bestRootIndex); if (bestScore > 0 && Logger.IsActive) { Pairing.Reset(bestRoot); BuildPairing(candidate); Logger.Log("BestRoot", bestRoot); Logger.Log("BestPairing", Pairing); } return bestScore; }
public void Analyze(MinutiaPairing pairing, EdgeLookup lookup, Template probe, Template candidate) { MaxDistanceError = lookup.MaxDistanceError; MaxAngleError = lookup.MaxAngleError; var innerDistanceRadius = Convert.ToInt32(DistanceErrorFlatness * MaxDistanceError); var innerAngleRadius = Convert.ToInt32(AngleErrorFlatness * MaxAngleError); PairCount = pairing.Count; EdgeCount = 0; SupportedCount = 0; CorrectTypeCount = 0; DistanceErrorSum = 0; AngleErrorSum = 0; for (int i = 0; i < PairCount; ++i) { PairInfo pair = pairing.GetPair(i); if (pair.SupportingEdges >= MinSupportingEdges) ++SupportedCount; EdgeCount += pair.SupportingEdges + 1; if (probe.Minutiae[pair.Pair.Probe].Type == candidate.Minutiae[pair.Pair.Candidate].Type) ++CorrectTypeCount; if (i > 0) { var probeEdge = EdgeConstructor.Construct(probe, pair.Reference.Probe, pair.Pair.Probe); var candidateEdge = EdgeConstructor.Construct(candidate, pair.Reference.Candidate, pair.Pair.Candidate); DistanceErrorSum += Math.Abs(probeEdge.Length - candidateEdge.Length); AngleErrorSum += Math.Max(innerDistanceRadius, Angle.Distance(probeEdge.ReferenceAngle, candidateEdge.ReferenceAngle)); AngleErrorSum += Math.Max(innerAngleRadius, Angle.Distance(probeEdge.NeighborAngle, candidateEdge.NeighborAngle)); } } float probeFraction = PairCount / (float)probe.Minutiae.Length; float candidateFraction = PairCount / (float)candidate.Minutiae.Length; PairFraction = (probeFraction + candidateFraction) / 2; }
void BuildPairing(Template candidate) { while (true) { CollectEdges(candidate); PairSelector.SkipPaired(Pairing); if (PairSelector.Count == 0) break; Pairing.Add(PairSelector.Dequeue()); } Pairing.Log(); }
float TryRoot(MinutiaPair root, Template candidate) { Pairing.Reset(root); BuildPairing(candidate); MatchAnalysis.Analyze(Pairing, EdgeLookup, Probe.Template, candidate); return MatchScoring.Compute(MatchAnalysis); }
void PrepareCandidate(Template candidate) { Pairing.SelectCandidate(candidate); PairSelector.Clear(); CandidateEdges.Reset(candidate); }
void CollectEdges(Template candidate) { var reference = Pairing.LastAdded.Pair; var probeNeighbors = Probe.Edges.Table[reference.Probe]; var candidateNeigbors = CandidateEdges.Table[reference.Candidate]; var matches = EdgeLookup.FindMatchingPairs(probeNeighbors, candidateNeigbors); foreach (var match in matches) { var neighbor = match.Pair; if (!Pairing.IsCandidatePaired(neighbor.Candidate) && !Pairing.IsProbePaired(neighbor.Probe)) PairSelector.Enqueue(new EdgePair(reference, neighbor), match.Distance); else if (Pairing.IsProbePaired(neighbor.Probe) && Pairing.GetByProbe(neighbor.Probe).Pair.Candidate == neighbor.Candidate) { Pairing.AddSupportByProbe(reference.Probe); Pairing.AddSupportByProbe(neighbor.Probe); } } }