public void run(List <SketchStroke> sample) { List <Tuple <string, double> > results = new List <Tuple <string, double> >(); List <SketchStroke> normalizedSample = SketchPreprocessing.Normalize(sample, N, Size, Origin); foreach (KeyValuePair <string, Sketch> entry in this.Templates) { List <SketchStroke> templateStrokes = entry.Value.Strokes; List <SketchStroke> normalizedTemplate = SketchPreprocessing.Normalize(templateStrokes, N, Size, Origin); double d1 = SketchTools.HausdorffDistance(normalizedSample, normalizedTemplate); double d2 = SketchTools.Distance(normalizedTemplate, normalizedSample); double distance = d1 < d2 ? d1 : d2; results.Add(new Tuple <string, double>(entry.Key, distance)); } results.Sort((x, y) => y.Item2.CompareTo(x.Item2)); labels = new List <string>(); scores = new List <double>(); for (int i = 0; i < results.Count; i++) { string label = results[i].Item1; double score = results[i].Item2; labels.Add(label); scores.Add(score); } }
private void LoadQuestion(int questionIndex) { this.currentQuestion = this.questions[questionIndex]; this.InstructionTextBlock.Text = this.currentQuestion.Text; this.currentTemplateSketch = this.strokeTemplates[this.currentQuestion.Answer]; this.currentTemplateSketchStrokes = SketchPreprocessing.ScaleToFrame(currentTemplateSketch, writingFrameLength); this.LoadTemplateImage(this.currentQuestion.Answer); InteractionTools.ShowTemplateImage(this.SmallTemplateImage, this.currentImageTemplate); }
/// <summary> /// When sample and template have same numbers of strokes /// </summary> /// <param name="sample">sample strokes</param> /// <param name="template">template strokes</param> /// <returns>An array where corr[i] = j denotes the ith stroke from the sample corresponds to the jth stroke from the template.</returns> public static int[] StrokeToStrokeCorrespondenceSameCount(List <SketchStroke> sample, List <SketchStroke> template) { int numStroke = sample.Count; int[] correspondence = new int[numStroke]; bool[] hasCompared = new bool[numStroke]; List <SketchStroke> sampleNormalized = SketchPreprocessing.Normalize(sample, 128, 500, new SketchPoint(0.0, 0.0)); List <SketchStroke> templateNormalized = SketchPreprocessing.Normalize(template, 128, 500, new SketchPoint(0.0, 0.0)); for (int i = 0; i < numStroke; i++) { double minDis = double.MaxValue; int matchedIdx = -1; for (int j = 0; j < numStroke; j++) { if (hasCompared[j]) { continue; } double dis = SketchTools.HausdorffDistance(sampleNormalized[i], templateNormalized[j]); if (dis < minDis) { minDis = dis; matchedIdx = j; } } correspondence[i] = matchedIdx; hasCompared[matchedIdx] = true; } return(correspondence); }
/// <summary> /// one to one, one to many, or many to one, result is from template to sample strokes /// </summary> /// <param name="sample"></param> /// <param name="template"></param> /// <returns></returns> public static List <List <int>[]> StrokeToStrokeCorrespondenceDifferentCountStartFromSample(List <SketchStroke> sample, List <SketchStroke> template) { List <List <int>[]> result = new List <List <int>[]>(); HashSet <int> usedSampleIndices = new HashSet <int>(); HashSet <int> usedTemplateIndices = new HashSet <int>(); List <SketchStroke> sampleNormalized = SketchPreprocessing.Normalize(sample, 128, 500, new SketchPoint(0.0, 0.0)); List <SketchStroke> templateNormalized = SketchPreprocessing.Normalize(template, 128, 500, new SketchPoint(0.0, 0.0)); int si = 0; while (si < sample.Count && usedTemplateIndices.Count < template.Count) { Debug.WriteLine("si = " + si); if (usedSampleIndices.Contains(si)) { si++; continue; } double oneToOneDis = double.MaxValue; int matchedIdx = -1; for (int ti = 0; ti < template.Count; ti++) { if (usedTemplateIndices.Contains(ti)) { continue; } double dis = SketchTools.HausdorffDistance(sampleNormalized[si], templateNormalized[ti]); if (dis < oneToOneDis) { oneToOneDis = dis; matchedIdx = ti; } } usedSampleIndices.Add(si); usedTemplateIndices.Add(matchedIdx); List <int> oneToManyIndices = new List <int>(); oneToManyIndices.Add(matchedIdx); List <int> manyToOneIndices = new List <int>(); manyToOneIndices.Add(si); SketchStroke currSampleStroke = sampleNormalized[si]; double oneToManyDis = oneToOneDis; int preSample = si - 1; int postSample = si + 1; while (preSample >= 0) { if (usedSampleIndices.Contains(preSample)) { break; } SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(sampleNormalized[preSample], currSampleStroke); double dis = SketchTools.HausdorffDistance(concatenatedStroke, templateNormalized[matchedIdx]); if (dis < oneToManyDis) { oneToManyDis = dis; oneToManyIndices.Insert(0, preSample); currSampleStroke = concatenatedStroke; } else { break; } preSample--; } while (postSample < sample.Count) { if (usedSampleIndices.Contains(postSample)) { break; } SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(currSampleStroke, sampleNormalized[postSample]); double dis = SketchTools.HausdorffDistance(concatenatedStroke, templateNormalized[matchedIdx]); if (dis < oneToManyDis) { oneToManyDis = dis; oneToManyIndices.Add(postSample); currSampleStroke = concatenatedStroke; } else { break; } postSample++; } SketchStroke currTemplateStroke = templateNormalized[matchedIdx]; double manyToOneDis = oneToOneDis; int preTemplate = matchedIdx - 1; int postTemplate = matchedIdx + 1; while (preTemplate >= 0) { if (usedTemplateIndices.Contains(preTemplate)) { break; } SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(templateNormalized[preTemplate], currTemplateStroke); double dis = SketchTools.HausdorffDistance(concatenatedStroke, sampleNormalized[si]); if (dis < manyToOneDis) { manyToOneDis = dis; manyToOneIndices.Insert(0, preTemplate); currTemplateStroke = concatenatedStroke; } else { break; } preTemplate--; } while (postTemplate < template.Count) { if (usedTemplateIndices.Contains(postTemplate)) { break; } SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(currTemplateStroke, templateNormalized[postTemplate]); double dis = SketchTools.HausdorffDistance(concatenatedStroke, sampleNormalized[si]); if (dis < manyToOneDis) { manyToOneDis = dis; manyToOneIndices.Add(postTemplate); currTemplateStroke = concatenatedStroke; } else { break; } postTemplate++; } Debug.WriteLine("matched index = " + matchedIdx); int flag = -2; // -1 for oneToMany, 0 for oneToOne, 1 for manyToOne if (oneToManyDis < oneToOneDis && manyToOneDis < oneToOneDis) { if (oneToManyDis < manyToOneDis) { flag = -1; } else { flag = 1; } } else if (oneToManyDis < oneToOneDis) { flag = -1; } else if (manyToOneDis < oneToOneDis) { flag = 1; } else { flag = 0; } if (flag == 0) { List <int> oneTemplate = new List <int>(); List <int> oneSample = new List <int>(); oneTemplate.Add(matchedIdx); oneSample.Add(si); result.Add(new List <int>[] { oneTemplate, oneSample }); usedTemplateIndices.Add(matchedIdx); usedSampleIndices.Add(matchedIdx); si++; } else if (flag == -1) // one to many { List <int> one = new List <int>(); List <int> many = new List <int>(); one.Add(matchedIdx); usedTemplateIndices.Add(matchedIdx); foreach (int index in oneToManyIndices) { usedSampleIndices.Add(index); many.Add(index); } result.Add(new List <int>[] { one, many }); si = many[many.Count - 1] + 1; } else if (flag == 1) // many to one { List <int> many = new List <int>(); List <int> one = new List <int>(); foreach (int index in manyToOneIndices) { usedTemplateIndices.Add(index); many.Add(index); } one.Add(si); result.Add(new List <int>[] { many, one }); usedSampleIndices.Add(matchedIdx); si++; } } return(result); }