コード例 #1
0
        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);
            }
        }
コード例 #2
0
        public static double HausdorffDistance(List <SketchStroke> strokesA, List <SketchStroke> strokesB)
        {
            List <SketchPoint> pointsA = new List <SketchPoint>();
            List <SketchPoint> pointsB = new List <SketchPoint>();

            foreach (SketchStroke stroke in strokesA)
            {
                pointsA.AddRange(stroke.Points);
            }
            foreach (SketchStroke stroke in strokesB)
            {
                pointsB.AddRange(stroke.Points);
            }

            return(SketchTools.HausdorffDistance(pointsA, pointsB));
        }
コード例 #3
0
        public bool JudgeStrokeOrder(List <SketchStroke> sample, List <SketchStroke> template)
        {
            if (this.IsCorrectStrokeCount == false)
            {
                return(false);
            }

            // the ith element is the corresponding
            this.StrokeToStrokeCorrespondenceSameCount = new int[sample.Count];
            HashSet <int> unusedTemplates = new HashSet <int>();

            for (int i = 0; i < template.Count; i++)
            {
                unusedTemplates.Add(i);
            }
            for (int i = 0; i < sample.Count; i++)
            {
                int    matchedIndex = -1;
                double minDistance  = double.MaxValue;

                foreach (int tempIdx in unusedTemplates)
                {
                    double currDistance = SketchTools.TrioDistance(sample[i], template[tempIdx]);

                    if (currDistance < minDistance)
                    {
                        minDistance  = currDistance;
                        matchedIndex = tempIdx;
                    }
                }

                this.StrokeToStrokeCorrespondenceSameCount[i] = matchedIndex;
                unusedTemplates.Remove(matchedIndex);
            }

            for (int i = 0; i < sample.Count; i++)
            {
                if (this.StrokeToStrokeCorrespondenceSameCount[i] != i)
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #4
0
        /// <summary>
        /// one sample stroke contains many template strokes
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="template"></param>
        /// <returns>stroke index -> list of template indices it contains</returns>
        public static List <List <int> > StrokeToStrokeCorrespondenceConcatenating(List <SketchStroke> sample, List <SketchStroke> template)
        {
            List <List <int> > result = new List <List <int> >();

            List <KeyValuePair <SketchStroke, int> > templateStrokeToIndex = new List <KeyValuePair <SketchStroke, int> >();

            for (int i = 0; i < template.Count; i++)
            {
                templateStrokeToIndex.Add(new KeyValuePair <SketchStroke, int>(template[i], i));
            }

            foreach (SketchStroke sampleStroke in sample)
            {
                templateStrokeToIndex.Sort((t1, t2) => SketchTools.DirectedHausdorffDistance(t1.Key.Points, sampleStroke.Points).CompareTo(SketchTools.DirectedHausdorffDistance(t2.Key.Points, sampleStroke.Points)));

                double       currHausdorffFromSampleToTemplateList = double.MaxValue;
                SketchStroke currConcatenated = new SketchStroke();
                List <int>   currListIndices  = new List <int>();
                foreach (KeyValuePair <SketchStroke, int> pair in templateStrokeToIndex)
                {
                    SketchStroke newConcatenated = SketchStroke.ConcatenateStrokes(pair.Key, currConcatenated);
                    double       newDistance     = SketchTools.HausdorffDistance(sampleStroke, newConcatenated);
                    if (newDistance < currHausdorffFromSampleToTemplateList)
                    {
                        currHausdorffFromSampleToTemplateList = newDistance;
                        currConcatenated = newConcatenated;
                        currListIndices.Add(pair.Value);
                    }
                }

                result.Add(currListIndices);

                foreach (int currIndex in currListIndices)
                {
                    templateStrokeToIndex.Remove(new KeyValuePair <SketchStroke, int>(template[currIndex], currIndex));
                }
            }

            return(result);
        }
コード例 #5
0
        /// <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);
        }
コード例 #6
0
 public static bool ValidateStroke(SketchStroke sampleStroke, SketchStroke templateStroke)
 {
     return(SketchTools.HausdorffDistance(sampleStroke, templateStroke) < SkritterHelpers.StrokeValidationDistanceThreshold);
 }
コード例 #7
0
        /// <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);
        }
コード例 #8
0
 public static double HausdorffDistance(SketchStroke strokeA, SketchStroke strokeB)
 {
     return(SketchTools.HausdorffDistance(strokeA.Points, strokeB.Points));
 }