public NBestList Recognize(ArrayList points) // candidate points
        {
            // resample to a common number of points
            points = Utils.Resample(points, NumResamplePoints);

            // rotate so that the centroid-to-1st-point is at zero degrees
            double radians = Utils.AngleInRadians(Utils.Centroid(points), (PointR)points[0], false); // indicative angle

            points = Utils.RotateByRadians(points, -radians);                                        // undo angle

            // scale to a common (square) dimension
            points = Utils.ScaleTo(points, ResampleScale);

            // translate to a common origin
            points = Utils.TranslateCentroidTo(points, ResampleOrigin);

            NBestList nbest = new NBestList();

            foreach (Gesture p in _gestures.Values)
            {
                double[] best = GoldenSectionSearch(
                    points,                 // to rotate
                    p.Points,               // to match
                    Utils.Deg2Rad(-45.0),   // lbound
                    Utils.Deg2Rad(+45.0),   // ubound
                    Utils.Deg2Rad(2.0));    // threshold

                double score = 1d - best[0] / HalfDiagonal;
                nbest.AddResult(p.Name, score, best[0], best[1]); // name, score, distance, angle
            }
            nbest.AddResult("Try Again", tolerance, 0.0, 0.0);
            nbest.SortDescending(); // sort so that nbest[0] is best result
            return(nbest);
        }
Beispiel #2
0
        public NBestList Recognize(ArrayList points) // candidate points
        {
            // resample to a common number of points
            points = Utils.Resample(points, NumResamplePoints);

            // rotate so that the centroid-to-1st-point is at zero degrees
            double radians = Utils.AngleInRadians(Utils.Centroid(points), (PointR) points[0], false); // indicative angle
            points = Utils.RotateByRadians(points, -radians); // undo angle

            // scale to a common (square) dimension
            points = Utils.ScaleTo(points, ResampleScale);

            // translate to a common origin
            points = Utils.TranslateCentroidTo(points, ResampleOrigin);

            NBestList nbest = new NBestList();
            foreach (Gesture p in _gestures.Values)
            {
                double[] best = GoldenSectionSearch(
                    points,                 // to rotate
                    p.Points,               // to match
                    Utils.Deg2Rad(-45.0),   // lbound
                    Utils.Deg2Rad(+45.0),   // ubound
                    Utils.Deg2Rad(2.0));    // threshold

                double score = 1d - best[0] / HalfDiagonal;
                nbest.AddResult(p.Name, score, best[0], best[1]); // name, score, distance, angle
            }
            nbest.AddResult("Try Again", tolerance, 0.0, 0.0);
            nbest.SortDescending(); // sort so that nbest[0] is best result
            return nbest;
        }
        /// <summary>
        /// Tests an entire batch of files. See comments atop MainForm.TestBatch_Click().
        /// </summary>
        /// <param name="subject">Subject number.</param>
        /// <param name="speed">"fast", "medium", or "slow"</param>
        /// <param name="categories">A list of gesture categories that each contain lists of
        /// prototypes (examples) within that gesture category.</param>
        /// <param name="dir">The directory into which to write the output files.</param>
        /// <returns>True if successful; false otherwise.</returns>
        public bool TestBatch(int subject, string speed, ArrayList categories, string dir)
        {
            bool         success    = true;
            StreamWriter mainWriter = null;
            StreamWriter recWriter  = null;

            try
            {
                //
                // set up a main results file and detailed recognition results file
                //
                int    start    = Environment.TickCount;
                string mainFile = String.Format("{0}\\geometric_main_{1}.txt", dir, start);
                string recFile  = String.Format("{0}\\geometric_data_{1}.txt", dir, start);

                mainWriter = new StreamWriter(mainFile, false, Encoding.UTF8);
                mainWriter.WriteLine("Subject = {0}, Recognizer = geometric, Speed = {1}, StartTime(ms) = {2}", subject, speed, start);
                mainWriter.WriteLine("Subject Recognizer Speed NumTraining GestureType RecognitionRate\n");

                recWriter = new StreamWriter(recFile, false, Encoding.UTF8);
                recWriter.WriteLine("Subject = {0}, Recognizer = geometric, Speed = {1}, StartTime(ms) = {2}", subject, speed, start);
                recWriter.WriteLine("Correct? NumTrain Tested 1stCorrect Pts Ms Angle : (NBestNames) [NBestScores]\n");

                //
                // determine the number of gesture categories and the number of examples in each one
                //
                int    numCategories = categories.Count;
                int    numExamples   = ((Category)categories[0]).NumExamples;
                double totalTests    = (numExamples - 1) * NumRandomTests;

                //
                // outermost loop: trains on N=1..9, tests on 10-N (for e.g., numExamples = 10)
                //
                for (int n = 1; n <= numExamples - 1; n++)
                {
                    // storage for the final avg results for each category for this N
                    double[] results = new double[numCategories];

                    //
                    // run a number of tests at this particular N number of training examples
                    //
                    for (int r = 0; r < NumRandomTests; r++)
                    {
                        _gestures.Clear(); // clear any (old) loaded prototypes

                        // load (train on) N randomly selected gestures in each category
                        for (int i = 0; i < numCategories; i++)
                        {
                            Category c      = (Category)categories[i];             // the category to load N examples for
                            int[]    chosen = Utils.Random(0, numExamples - 1, n); // select N unique indices
                            for (int j = 0; j < chosen.Length; j++)
                            {
                                Gesture p = c[chosen[j]]; // get the prototype from this category at chosen[j]
                                _gestures.Add(p.Name, p); // load the randomly selected test gestures into the recognizer
                            }
                        }

                        //
                        // testing loop on all unloaded gestures in each category. creates a recognition
                        // rate (%) by averaging the binary outcomes (correct, incorrect) for each test.
                        //
                        for (int i = 0; i < numCategories; i++)
                        {
                            // pick a random unloaded gesture in this category for testing
                            // instead of dumbly picking, first find out what indices aren't
                            // loaded, and then randomly pick from those.
                            Category c         = (Category)categories[i];
                            int[]    notLoaded = new int[numExamples - n];
                            for (int j = 0, k = 0; j < numExamples; j++)
                            {
                                Gesture g = c[j];
                                if (!_gestures.ContainsKey(g.Name))
                                {
                                    notLoaded[k++] = j; // jth gesture in c is not loaded
                                }
                            }
                            int     chosen = Utils.Random(0, notLoaded.Length - 1); // index
                            Gesture p      = c[notLoaded[chosen]];                  // gesture to test
                            Debug.Assert(!_gestures.ContainsKey(p.Name));

                            // do the recognition!
                            ArrayList testPts  = Utils.RotateByDegrees(p.RawPoints, Utils.Random(0, 359));
                            NBestList result   = this.Recognize(testPts);
                            string    category = Category.ParseName(result.Name);
                            int       correct  = (c.Name == category) ? 1 : 0;

                            recWriter.WriteLine("{0} {1} {2} {3} {4} {5} {6:F1}{7} : ({8}) [{9}]",
                                                correct,                                // Correct?
                                                n,                                      // NumTrain
                                                p.Name,                                 // Tested
                                                FirstCorrect(p.Name, result.Names),     // 1stCorrect
                                                p.RawPoints.Count,                      // Pts
                                                p.Duration,                             // Ms
                                                Math.Round(result.Angle, 1), (char)176, // Angle tweaking :
                                                result.NamesString,                     // (NBestNames)
                                                result.ScoresString);                   // [NBestScores]

                            results[i] += correct;
                        }

                        // provide feedback as to how many tests have been performed thus far.
                        double testsSoFar = ((n - 1) * NumRandomTests) + r;
                        ProgressChangedEvent(this, new ProgressEventArgs(testsSoFar / totalTests)); // callback
                    }

                    //
                    // now create the final results for this N and write them to a file
                    //
                    for (int i = 0; i < numCategories; i++)
                    {
                        results[i] /= (double)NumRandomTests;  // normalize by the number of tests at this N
                        Category c = (Category)categories[i];
                        // Subject Recognizer Speed NumTraining GestureType RecognitionRate
                        mainWriter.WriteLine("{0} geometric {1} {2} {3} {4:F3}", subject, speed, n, c.Name, Math.Round(results[i], 3));
                    }
                }

                // time-stamp the end of the processing
                int end = Environment.TickCount;
                mainWriter.WriteLine("\nEndTime(ms) = {0}, Minutes = {1:F2}", end, Math.Round((end - start) / 60000.0, 2));
                recWriter.WriteLine("\nEndTime(ms) = {0}, Minutes = {1:F2}", end, Math.Round((end - start) / 60000.0, 2));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                success = false;
            }
            finally
            {
                if (mainWriter != null)
                {
                    mainWriter.Close();
                }
                if (recWriter != null)
                {
                    recWriter.Close();
                }
            }
            return(success);
        }