/// <inheridoc/> public ISignerModel Train(List <Signature> signatures) { var genuines = signatures.Where(s => s.Origin == Origin.Genuine) .Select(s => new { s.ID, Features = s.GetAggregateFeature(Features).ToArray() }).ToList(); var distanceMatrix = new DistanceMatrix <string, string, double>(); foreach (var i in genuines) { foreach (var j in genuines) { if (distanceMatrix.ContainsKey(j.ID, i.ID)) { distanceMatrix[i.ID, j.ID] = distanceMatrix[j.ID, i.ID]; } else if (i == j) { distanceMatrix[i.ID, j.ID] = 0; } else { distanceMatrix[i.ID, j.ID] = DtwPy.Dtw(i.Features, j.Features, DistanceFunction); } } } var distances = distanceMatrix.GetValues().Where(v => v != 0); var mean = distances.Average(); var stdev = Math.Sqrt(distances.Select(d => (d - mean) * (d - mean)).Sum() / distances.Count()); double med; var orderedDistances = new List <double>(distances).OrderBy(d => d); if (orderedDistances.Count() % 2 == 0) { int i = orderedDistances.Count() / 2; med = (orderedDistances.ElementAt(i - 1) + orderedDistances.ElementAt(i)) / 2.0; } else { int i = orderedDistances.Count() / 2; med = orderedDistances.ElementAt(i); } return(new DtwSignerModel { GenuineSignatures = genuines.Select(g => new KeyValuePair <string, double[][]>(g.ID, g.Features)).ToList(), DistanceMatrix = distanceMatrix, Threshold = mean + MultiplicationFactor * stdev //Threshold = med + (distances.Max() - med) * 1 / 2 }); }
/// <inheridoc/> public double Test(ISignerModel model, Signature signature) { var dtwModel = (DtwSignerModel)model; var testSignature = signature.GetAggregateFeature(Features).ToArray(); var distances = new double[dtwModel.GenuineSignatures.Count]; for (int i = 0; i < dtwModel.GenuineSignatures.Count; i++) { distances[i] = DtwPy.Dtw(dtwModel.GenuineSignatures[i].Value, testSignature, DistanceFunction); dtwModel.DistanceMatrix[signature.ID, dtwModel.GenuineSignatures[i].Key] = distances[i]; } // returns value between 0 and 1, how confident is the decision about genuineness // 1 -> conident genuine, 0 -> not confident genuine = confident forged return(Math.Max(1 - (distances.Average() / dtwModel.Threshold) / 2, 0)); }
public double[,] Calculate() { var distances = new double[InputSignatures.Count, InputSignatures.Count]; for (int i = 0; i < InputSignatures.Count; i++) { for (int j = 0; j < InputSignatures.Count; j++) { distances[i, j] = DtwPy.Dtw <double[]>( InputSignatures[i].GetAggregateFeature(InputFeatures), InputSignatures[j].GetAggregateFeature(InputFeatures), InputFunc); } } return(distances); }
private Tuple <int, Stroke, double, int> CalculateIdx(Stroke stroke, List <Vertex> trajectory, int window, int jump = 1) { int resIdx = int.MaxValue; double resVal = Double.MaxValue; for (int i = 0; i < trajectory.Count - window; i += jump) { double val = DtwPy.Dtw <double[]>(stroke.GetDtwPairingFeature(InputScale), trajectory.GetRange(i, window).GetDtwPairingFeature(InputScale), DtwPairingDistance); if (val < resVal) { resVal = val; resIdx = i; } } return(new Tuple <int, Stroke, double, int>(resIdx, stroke, resVal, window)); }
public List <Tuple <string, string, double> > Calculate() { var distances = new double[OfflineSignatures.Count]; Parallel.For(0, OfflineSignatures.Count, idx => { var offlineSig = OfflineSignatures[idx]; var offlineTrajectory = offlineSig.GetFeature <List <Vertex> >(InputOfflineTrajectory); var onlineSig = OnlineSignatures.Find(sig => sig.ID == offlineSig.ID && sig.Signer.ID == offlineSig.Signer.ID); var onlineTrajectory = onlineSig.GetFeature <List <Vertex> >(InputOnlineTrajectory); distances[idx] = DtwPy.Dtw(offlineTrajectory.GetOriginalXYs(), onlineTrajectory.GetOriginalXYs(), PenDistance); } ); var res = new List <Tuple <string, string, double> >(); for (int i = 0; i < OfflineSignatures.Count; i++) { res.Add(new Tuple <string, string, double>(OfflineSignatures[i].Signer.ID, OfflineSignatures[i].ID, distances[i])); } return(res); }
public static double GetCost(Signature sig1, Signature sig2, DtwType dtwType, List <FeatureDescriptor> features) { switch (dtwType) { case DtwType.DtwPy: return(DtwPy.Dtw(sig1.GetAggregateFeature(features), sig2.GetAggregateFeature(features), DtwPy.EuclideanDistance)); case DtwType.NDtw: //hatalmas hack, csak egy-egy featurere működik, kombinációra nem return(new NDtw.Dtw(sig1.GetFeature <List <double> >(features[0]).ToArray(), sig2.GetFeature <List <double> >(features[0]).ToArray(), DistanceMeasure.Manhattan).GetCost()); case DtwType.FrameworkDtw: return(new SigStat.Common.Algorithms.Dtw(Accord.Math.Distance.Manhattan) .Compute(sig1.GetAggregateFeature(features).ToArray(), sig2.GetAggregateFeature(features).ToArray())); case DtwType.MyDtw: return(new Common.Dtw(sig1, sig2, features).CalculateDtwScore()); default: throw new ArgumentException(nameof(dtwType) + typeof(DtwType) + "not exists"); } }