internal List <MtripletPair> FindNoRotateAllSimilar(MTriplet queryMTp) { // Indexing by MaxDistance double dThr = MTriplet.DistanceThreshold; double d = queryMTp.MaxDistance - dThr; int iniIdx = BinarySearch(MTriplets, d); d = queryMTp.MaxDistance + dThr; var result = new List <MtripletPair>(); for (int j = iniIdx; j < MTriplets.Count && MTriplets[j].MaxDistance <= d; j++) { MTriplet currMTp = MTriplets[j]; byte[] currOrder; double currSim = queryMTp.NoRotateMatch(currMTp, out currOrder); if (currSim > 0) { result.Add(new MtripletPair { queryMTp = queryMTp, templateMTp = currMTp, matchingValue = currSim, templateMtiaOrder = currOrder } ); } } if (result.Count > 0) { return(result); } return(null); }
private double MatchBetaAngles(MTriplet compareTo, byte[] order) { var idxArr = new[] { 0, 1, 2, 0 }; double maxdiff = 0; for (int i = 0; i < 3; i++) { int j = idxArr[i + 1]; Minutia qMtiai = minutiae[MtiaIdxs[i]]; Minutia qMtiaj = minutiae[MtiaIdxs[j]]; double qbeta = Angle.Difference2Pi(qMtiai.Angle, qMtiaj.Angle); Minutia tMtiai = compareTo.minutiae[compareTo.MtiaIdxs[order[i]]]; Minutia tMtiaj = compareTo.minutiae[compareTo.MtiaIdxs[order[j]]]; double tbeta = Angle.Difference2Pi(tMtiai.Angle, tMtiaj.Angle); double diff1 = Math.Abs(tbeta - qbeta); double diff = Math.Min(diff1, 2 * Math.PI - diff1); if (diff >= aThr) { return(0); } if (diff > maxdiff) { maxdiff = diff; } } return(1 - maxdiff / aThr); }
private int[] GetAlphaCodes(MTriplet mtp) { int[] alpha = new int[3]; for (int i = 0; i < 3; i++) { int j; if (i == 2) { j = 0; } else { j = i + 1; } Minutia qMtiai = mtp[i]; Minutia qMtiaj = mtp[j]; double x = qMtiai.X - qMtiaj.X; double y = qMtiai.Y - qMtiaj.Y; double angleij = Angle.ComputeAngle(x, y); double qAlpha = Angle.Difference2Pi(qMtiai.Angle, angleij); alpha[i] = DiscretizeAngle(qAlpha); } return(alpha); }
/// <summary> /// Extract features of type <see cref="MtripletsFeature"/> from the specified minutiae. /// </summary> /// <param name="minutiae"> /// The list of <see cref="Minutia"/> to extract the features from. /// </param> /// <returns> /// Features of type <see cref="MtripletsFeature"/> extracted from the specified minutiae. /// </returns> public MtripletsFeature ExtractFeatures(List <Minutia> minutiae) { List <MTriplet> result = new List <MTriplet>(); Dictionary <int, int> triplets = new Dictionary <int, int>(); var nearest = new short[minutiae.Count, neighborsCount]; var distance = new double[minutiae.Count, neighborsCount]; // Initializing distances for (int i = 0; i < minutiae.Count; i++) { for (int j = 0; j < neighborsCount; j++) { distance[i, j] = double.MaxValue; nearest[i, j] = -1; } } // Computing m-triplets for (short i = 0; i < minutiae.Count; i++) { // Updating nearest minutiae UpdateNearest(minutiae, i, nearest, distance); // Building m-triplets for (int j = 0; j < neighborsCount - 1; j++) { for (int k = j + 1; k < neighborsCount; k++) { if (nearest[i, j] != -1 && nearest[i, k] != -1) { if (i == nearest[i, j] || i == nearest[i, k] || nearest[i, j] == nearest[i, k]) { throw new Exception("Wrong mtp"); } MTriplet newMTriplet = new MTriplet(new short[] { i, nearest[i, j], nearest[i, k] }, minutiae); int newHash = newMTriplet.GetHashCode(); if (!triplets.ContainsKey(newHash)) { triplets.Add(newHash, 0); result.Add(newMTriplet); } } } } } result.TrimExcess(); return(new MtripletsFeature(result, minutiae)); }
public double NoRotateMatch(MTriplet target, out byte[] mtiaOrder) { byte[] matchOrder = null; double maxSimil = 0; if (Math.Abs(MaxDistance - target.MaxDistance) < dThr && Math.Abs(MidDistance - target.MidDistance) < dThr && Math.Abs(MinDistance - target.MinDistance) < dThr /* && Angle.AngleDif180(maxBeta, target.maxBeta) < aThr*/) { foreach (byte[] order in Orders) { double dirSim = MatchMtiaDirections(target, order); if (dirSim == 0) { continue; } double distSim = MatchDistances(target, order); if (distSim == 0) { continue; } double betaSim = MatchBetaAngles(target, order); if (betaSim == 0) { continue; } double alphaSim = MatchAlphaAngles(target, order); if (alphaSim == 0) { continue; } double currentSimil = 1 - (1 - distSim) * (1 - alphaSim) * (1 - betaSim); if (currentSimil > maxSimil) { matchOrder = order; maxSimil = currentSimil; } } } mtiaOrder = matchOrder; return(maxSimil); }
private int[] GetAllRotationsHashes(MTriplet mtp) { // Computing hash for alpha angles int[] alphaCodes = GetAlphaCodes(mtp); // Generating all possible hashes int[] hashes = new int[3]; int i = 0; foreach (byte[] order in MTriplet.Orders) { int a0 = alphaCodes[order[0]]; int a1 = alphaCodes[order[1]]; int a2 = alphaCodes[order[2]]; hashes[i++] = MergeHashes(a0, a1, a2); } return(hashes); }
private double MatchAlphaAngles(MTriplet compareTo, byte[] order) { double maxdiff = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i != j) { Minutia qMtiai = minutiae[MtiaIdxs[i]]; Minutia qMtiaj = minutiae[MtiaIdxs[j]]; double x = qMtiai.X - qMtiaj.X; double y = qMtiai.Y - qMtiaj.Y; double angleij = Angle.ComputeAngle(x, y); double qAlpha = Angle.Difference2Pi(qMtiai.Angle, angleij); Minutia tMtiai = compareTo.minutiae[compareTo.MtiaIdxs[order[i]]]; Minutia tMtiaj = compareTo.minutiae[compareTo.MtiaIdxs[order[j]]]; x = tMtiai.X - tMtiaj.X; y = tMtiai.Y - tMtiaj.Y; angleij = Angle.ComputeAngle(x, y); double tAlpha = Angle.Difference2Pi(tMtiai.Angle, angleij); double diff1 = Math.Abs(tAlpha - qAlpha); double diff = Math.Min(diff1, 2 * Math.PI - diff1); if (diff >= aThr) { return(0); } if (diff > maxdiff) { maxdiff = diff; } } } } return(1 - maxdiff / aThr); }
private double MatchDistances(MTriplet compareTo, byte[] order) { double diff0 = Math.Abs(d[0] - compareTo.d[order[0]]); if (diff0 > dThr) { return(0); } double diff1 = Math.Abs(d[1] - compareTo.d[order[1]]); if (diff1 > dThr) { return(0); } double diff2 = Math.Abs(d[2] - compareTo.d[order[2]]); if (diff2 > dThr) { return(0); } return(1 - (Math.Max(diff0, Math.Max(diff1, diff2))) / dThr); }
private double MatchMtiaDirections(MTriplet compareTo, byte[] order) { double maxdiff = 0; for (int i = 0; i < 3; i++) { Minutia qMtiai = minutiae[MtiaIdxs[i]]; Minutia tMtiai = compareTo.minutiae[compareTo.MtiaIdxs[order[i]]]; double alpha = qMtiai.Angle; double beta = tMtiai.Angle; double diff1 = Math.Abs(beta - alpha); double diff = Math.Min(diff1, 2 * Math.PI - diff1); if (diff >= Math.PI / 4) { return(0); } if (diff > maxdiff) { maxdiff = diff; } } return(1); }