public Signature(SignatureFeatures features, SignatureFrame frame, IEnumerable <SignatureStroke> strokes, DateTime timestamp) { Features = features; Frame = frame; Strokes = new ReadOnlyCollection <SignatureStroke> (strokes.ToList()); Timestamp = timestamp; }
public static List <SignatureFeatures> GetFeaturesFromFile(string aFileName) { List <SignatureFeatures> lFeaturesList = new List <SignatureFeatures>(); using (StreamReader lReader = new StreamReader(aFileName)) { SignatureFeatures lFeatures = new SignatureFeatures(); string lLine = lReader.ReadLine(); while ((lLine = lReader.ReadLine()) != null) { var lSplittedLine = lLine.Split(','); lFeatures["TotalSignatureDuration"] = double.Parse(lSplittedLine[0], System.Globalization.CultureInfo.InvariantCulture); lFeatures["NumberOfStrokes"] = double.Parse(lSplittedLine[1], System.Globalization.CultureInfo.InvariantCulture); lFeatures["TTouch"] = double.Parse(lSplittedLine[2], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanX"] = double.Parse(lSplittedLine[3], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanX1"] = double.Parse(lSplittedLine[4], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanY"] = double.Parse(lSplittedLine[5], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanY1"] = double.Parse(lSplittedLine[6], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanP"] = double.Parse(lSplittedLine[7], System.Globalization.CultureInfo.InvariantCulture); lFeatures["MeanP1"] = double.Parse(lSplittedLine[8], System.Globalization.CultureInfo.InvariantCulture); lFeaturesList.Add(lFeatures); } } return(lFeaturesList); }
public int SaveSignature([FromBody] SignatureDTO aSig) { //Get signature from the Base64Encoded string SignatureData lSignatureData = SignatureUtils.SignatureUtils.GetSignatureFromBase64String(aSig.Signature, aSig.Email); var lDirectory = "d:\\Signatures\\" + lSignatureData.Email + "\\"; if (!System.IO.Directory.Exists(lDirectory)) { System.IO.Directory.CreateDirectory(lDirectory); } var fileName = lDirectory + DateTime.Now.Ticks.ToString() + ".csv"; var lFeaturesFileName = lDirectory + "\\SignatureFeatures\\" + "SignatureFeatures.csv"; //Calculate characteristics of the received signature and standardize it Signature lSigWithCharacteristics = SignatureUtils.SignatureUtils.CalculateCharacteristics(lSignatureData.Signature); lSigWithCharacteristics = SignatureUtils.SignatureUtils.StandardizeSignature(lSigWithCharacteristics); //Create DTW configuration for the quality evaluation DTWConfiguration lDTWConfig = new DTWConfiguration() .UseXY() .UseX1Y1(); //Check the quality of the signature. If it is a poor quality signature, request it once again bool lResult = SignatureQualityEvaluation.CheckQuality(lDirectory, lSigWithCharacteristics, lDTWConfig); if (lResult) { //Save function based data to csv file SignatureFileUtils.SaveSignatureWithCharacteristicsToFile(lSigWithCharacteristics, fileName); try { //Save feature based data to csv file SignatureFeatures lFEatures = FeatureCalculator.CalculateFeatures(lSigWithCharacteristics); if (!System.IO.Directory.Exists(lDirectory + "\\SignatureFeatures\\")) { System.IO.Directory.CreateDirectory(lDirectory + "\\SignatureFeatures\\"); } SignatureFileUtils.SaveFeatureSetToFile(lFEatures, lFeaturesFileName); } catch (Exception ex) { //If an error occurs, do nothing //An error can occur in case of the pressure related features, beacause some devices don't return the pressure value } return(1); } else { return(0); } }
public override double CalculateScores(SignatureFeatures aTrainedFeatures, SignatureFeatures aFeaturesOfSigToVerify) { double sum = 0; for (int i = 0; i < aTrainedFeatures.Count; ++i) { sum += Math.Pow(aTrainedFeatures.ElementAt(i).Value - aFeaturesOfSigToVerify.ElementAt(i).Value, 2); } return(Math.Sqrt(sum)); }
public override double CalculateScores(SignatureFeatures aTrainedFeatures, SignatureFeatures aFeaturesOfSigToVerify) { double score = 0; for (int i = 0; i < aTrainedFeatures.Count; ++i) { score += Math.Abs(aTrainedFeatures.ElementAt(i).Value - aFeaturesOfSigToVerify.ElementAt(i).Value); } return(score); }
/// <summary> /// Applies min-max normalization to the feature set /// </summary> /// <param name="aFeatureList"></param> /// <returns>The return value contains the normalized Feature set, as well the min and max values used for normaziation</returns> public static NormalizedFeatures NormalizeFeatures(List <SignatureFeatures> aFeatureList) { //Initialize Normalized With list. This will contain the min anf max values used at the normalization of the features List <NormalizedWith> lNormalizedWith = new List <NormalizedWith>(); for (var i = 0; i < aFeatureList.ElementAt(0).Count; ++i) { lNormalizedWith.Add(new NormalizedWith(9999, -9999)); } for (int i = 0; i < aFeatureList.Count; ++i) { SignatureFeatures lFeatures = new SignatureFeatures(); for (int j = 0; j < aFeatureList.ElementAt(i).Count; ++j) { var lCurrentFeatureValue = aFeatureList.ElementAt(i).ElementAt(j).Value; if (lNormalizedWith.ElementAt(j).Min > lCurrentFeatureValue) { lNormalizedWith.ElementAt(j).Min = lCurrentFeatureValue; } if (lNormalizedWith.ElementAt(j).Max < lCurrentFeatureValue) { lNormalizedWith.ElementAt(j).Max = lCurrentFeatureValue; } } } for (int i = 0; i < aFeatureList.Count; ++i) { SignatureFeatures lNormalizedFeatures = new SignatureFeatures(); for (int j = 0; j < aFeatureList.ElementAt(i).Count; ++j) { var lCurrentFeature = aFeatureList.ElementAt(i).ElementAt(j); if (lNormalizedWith.ElementAt(j).Min != lNormalizedWith.ElementAt(j).Max) { lNormalizedFeatures[lCurrentFeature.Key] = 2 * ((lCurrentFeature.Value - lNormalizedWith.ElementAt(j).Min) / (lNormalizedWith.ElementAt(j).Max - lNormalizedWith.ElementAt(j).Min)) - 1; } else { lNormalizedFeatures[lCurrentFeature.Key] = lCurrentFeature.Value; } } aFeatureList.RemoveAt(i); aFeatureList.Insert(i, lNormalizedFeatures); } NormalizedFeatures lNormalized = new NormalizedFeatures(aFeatureList, lNormalizedWith); return(lNormalized); }
public static SignatureFeatures NormalizeFeaturesSingleSignature(SignatureFeatures aFeatures, List <NormalizedWith> aNormalizedWith) { SignatureFeatures lFeatures = new SignatureFeatures(); int lCounter = 0; foreach (var key in lFeatures.Keys.ToList()) { if (aNormalizedWith.ElementAt(lCounter).Max != aNormalizedWith.ElementAt(lCounter).Min) { lFeatures[key] = 2 * ((aFeatures[key] - aNormalizedWith.ElementAt(lCounter).Min) / (aNormalizedWith.ElementAt(lCounter).Max - aNormalizedWith.ElementAt(lCounter).Min)) - 1; } else { lFeatures[key] = aFeatures[key]; } lCounter++; } return(lFeatures); }
public static void SaveFeatureSetToFile(SignatureFeatures aFeatures, string aFileName) { if (!File.Exists(aFileName)) { StreamWriter file = new StreamWriter(aFileName); file.WriteLine("T" + "," + "NumberOfStrokes" + "," + "TTouch" + "," + "MeanX" + "," + "MeanX1" + "," + "MeanY" + "," + "MeanY1" + "," + "MeanP" + "," + "MeanP1"); file.WriteLine(aFeatures["TotalSignatureDuration"] + "," + aFeatures["NumberOfStrokes"] + "," + aFeatures["TTouch"] + "," + aFeatures["MeanX"] + "," + aFeatures["MeanX1"] + "," + aFeatures["MeanY"] + "," + aFeatures["MeanY1"] + "," + aFeatures["MeanP"] + "," + aFeatures["MeanP1"]); file.Close(); } else { StreamWriter file = new StreamWriter(aFileName, append: true); file.WriteLine(aFeatures["TotalSignatureDuration"] + "," + aFeatures["NumberOfStrokes"] + "," + aFeatures["TTouch"] + "," + aFeatures["MeanX"] + "," + aFeatures["MeanX1"] + "," + aFeatures["MeanY"] + "," + aFeatures["MeanY1"] + "," + aFeatures["MeanP"] + "," + aFeatures["MeanP1"]); file.Close(); } }
/// <summary> /// /// </summary> /// <param name="aSig"></param> /// <returns></returns> public static SignatureFeatures CalculateFeatures(Signature aSig) { SignatureFeatures lFeatures = new SignatureFeatures(); lFeatures["TotalSignatureDuration"] = CalculateT(aSig); //lFeatures["MeanX"] = aSig.Select(element => element.X).ToList().Average(); lFeatures["AverageVelocityX"] = aSig.Select(element => element.X1).ToList().Average(); lFeatures["MaxVelocityX"] = aSig.Select(element => element.X1).ToList().Max(); //lFeatures["MeanX2"] = aSig.Select(element => element.X2).ToList().Average(); //lFeatures["MeanY"] = aSig.Select(element => element.Y).ToList().Average(); lFeatures["AverageVelocityY"] = aSig.Select(element => element.Y1).ToList().Average(); lFeatures["MaxVelocityY"] = aSig.Select(element => element.Y1).ToList().Max(); //lFeatures["MeanY2"] = aSig.Select(element => element.Y2).ToList().Average(); lFeatures["MeanP"] = aSig.Select(element => element.Force).ToList().Average(); //lFeatures["MeanP1"] = aSig.Select(element => element.Force1).ToList().Average(); lFeatures["MaxVelocity"] = aSig.Select(element => element.PathVelocity).ToList().Max(); lFeatures["MaxP"] = aSig.Select(element => element.Force).ToList().Max(); lFeatures["AveragePointWiseVelocity"] = aSig.Select(element => element.PathVelocity).ToList().Average(); lFeatures["AveragePointWiseAcceleration"] = aSig.Select(element => element.PathVelocity1).ToList().Average(); CalculateAdditionalFeatures(aSig, ref lFeatures); return(lFeatures); }
private static void CalculateAdditionalFeatures(Signature aSig, ref SignatureFeatures aFeatures) { int lNumberOfStorkes = 0; double lTTouch = aFeatures["TotalSignatureDuration"]; for (int i = 1; i < aSig.Count; ++i) { // double lTimeDiff = aSig.ElementAt(i).Time - aSig.ElementAt(i - 1).Time; if (lTimeDiff > 70) { lNumberOfStorkes++; lTTouch -= lTimeDiff; } if (i > 2 && i < aSig.Count - 1) { if ((aSig.ElementAt(i).X - aSig.ElementAt(i - 1).X) > 0) { if ((aSig.ElementAt(i + 1).X - aSig.ElementAt(i).X) < 0) { aFeatures["SignChangesX"]++; } } else { if ((aSig.ElementAt(i + 1).X - aSig.ElementAt(i).X) > 0) { aFeatures["SignChangesX"]++; } } if ((aSig.ElementAt(i).X1 - aSig.ElementAt(i - 1).X1) > 0) { if ((aSig.ElementAt(i + 1).X1 - aSig.ElementAt(i).X1) < 0) { aFeatures["SignChangesX1"]++; } } else { if ((aSig.ElementAt(i + 1).X1 - aSig.ElementAt(i).X1) > 0) { aFeatures["SignChangesX1"]++; } } if ((aSig.ElementAt(i).X2 - aSig.ElementAt(i - 1).X2) > 0) { if ((aSig.ElementAt(i + 1).X2 - aSig.ElementAt(i).X2) < 0) { aFeatures["SignChangesX2"]++; } } else { if ((aSig.ElementAt(i + 1).X2 - aSig.ElementAt(i).X2) > 0) { aFeatures["SignChangesX2"]++; } } if ((aSig.ElementAt(i).Y - aSig.ElementAt(i - 1).Y) > 0) { if ((aSig.ElementAt(i + 1).Y - aSig.ElementAt(i).Y) < 0) { aFeatures["SignChangesY"]++; } } else { if ((aSig.ElementAt(i + 1).Y1 - aSig.ElementAt(i).Y1) > 0) { aFeatures["SignChangesY1"]++; } } if ((aSig.ElementAt(i).Y1 - aSig.ElementAt(i - 1).Y1) > 0) { if ((aSig.ElementAt(i + 1).Y1 - aSig.ElementAt(i).Y1) < 0) { aFeatures["SignChangesY1"]++; } } else { if ((aSig.ElementAt(i + 1).Y1 - aSig.ElementAt(i).Y1) > 0) { aFeatures["SignChangesY1"]++; } } if ((aSig.ElementAt(i).Y2 - aSig.ElementAt(i - 1).Y2) > 0) { if ((aSig.ElementAt(i + 1).Y2 - aSig.ElementAt(i).Y2) < 0) { aFeatures["SignChangesY2"]++; } } else { if ((aSig.ElementAt(i + 1).Y2 - aSig.ElementAt(i).Y2) > 0) { aFeatures["SignChangesY2"]++; } } if ((aSig.ElementAt(i).Force - aSig.ElementAt(i - 1).Force) > 0) { if ((aSig.ElementAt(i + 1).Force - aSig.ElementAt(i).Force) < 0) { aFeatures["SignChangesP"]++; } } else { if ((aSig.ElementAt(i + 1).Force - aSig.ElementAt(i).Force) > 0) { aFeatures["SignChangesP"]++; } } } } aFeatures["NumberOfStrokes"] = lNumberOfStorkes; //aFeatures["TTouch"] = lTTouch; }
public List <double> CalculateScoreList(List <SignatureFeatures> aTrainedFeatures, SignatureFeatures aFeaturesOfSigToVerify) { List <double> lScoreList = new List <double>(); foreach (var featureSet in aTrainedFeatures) { lScoreList.Add(CalculateScores(featureSet, aFeaturesOfSigToVerify)); } return(lScoreList); }
public virtual double CalculateScores(SignatureFeatures aTrainedFeatures, SignatureFeatures aFeaturesOfSigToVerify) { throw new NotImplementedException(); }