Beispiel #1
0
        /// <summary>
        /// Loads all images from a chosen folder and computes all features for it.
        /// </summary>
        /// <param name="folder_path"></param>
        /// <returns></returns>
        public static double[][] FeaturesFromFolder(string folder_path, DetectorParameters detector_params)
        {
            DirectoryInfo d = new DirectoryInfo(folder_path);

            string[] extensions = new[] { ".jpg", ".bmp", ".png" };

            FileInfo[] files =
                d.GetFiles()
                .Where(f => extensions.Contains(f.Extension.ToLower()))
                .ToArray();

            List <double[]> features_all = new List <double[]>();

            bool debug_enabled = true;

            if (debug_enabled)
            {
                Directory.CreateDirectory("aug_imgs");
            }

            int img_it = 0;

            foreach (var file in files)
            {
                Bitmap bmp = new Bitmap(file.FullName);
                img_it++;
                for (int i = 0; i < NumberOfAugmentedImages; ++i)
                {
                    //Make 32 bit ARGB bitmap
                    Bitmap clone = new Bitmap(bmp.Width, bmp.Height,
                                              System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                    Random rng = new Random();

                    int x_off_random = rng.Next((-clone.Width / 20), (clone.Width / 20) + 1);
                    int y_off_random = rng.Next((-clone.Height / 20), (clone.Height / 20) + 1);

                    int x_size_random = rng.Next((-clone.Width / 10), (clone.Width / 10) + 1);
                    int y_size_random = rng.Next((-clone.Height / 10), (clone.Height / 10) + 1);

                    int do_blur = rng.Next(0, 2);

                    using (Graphics gr = Graphics.FromImage(clone))
                    {
                        gr.DrawImage(bmp, new Rectangle(0, 0, clone.Width, clone.Height));
                        gr.DrawImage(bmp, new Rectangle(x_off_random, y_off_random, clone.Width + x_size_random, clone.Height + y_size_random));
                    }


                    /*if(resize_factor == 2)
                     * {
                     *      ResizeBilinear filter = new ResizeBilinear(clone.Width / 2, clone.Height / 2);
                     *      var resized = filter.Apply(clone);
                     *
                     *      filter = new ResizeBilinear(clone.Width, clone.Height);
                     *      clone = filter.Apply(resized);
                     * }
                     *
                     * if (resize_factor == 3)
                     * {
                     *      ResizeNearestNeighbor filter = new ResizeNearestNeighbor(clone.Width / 2, clone.Height / 2);
                     *      var resized = filter.Apply(clone);
                     *
                     *      filter = new ResizeNearestNeighbor(clone.Width, clone.Height);
                     *      clone = filter.Apply(resized);
                     * }
                     *
                     * if (resize_factor == 4)
                     * {
                     *      ResizeBilinear filter = new ResizeBilinear(clone.Width / 4, clone.Height / 4);
                     *      var resized = filter.Apply(clone);
                     *
                     *      filter = new ResizeBilinear(clone.Width, clone.Height);
                     *      clone = filter.Apply(resized);
                     * }
                     */

                    int resamplingFactor = Math.Min((1 + i / 2), 10);

                    ResizeBilinear filter  = new ResizeBilinear(clone.Width / resamplingFactor, clone.Height / resamplingFactor);
                    var            resized = filter.Apply(clone);

                    filter = new ResizeBilinear(clone.Width, clone.Height);
                    clone  = filter.Apply(resized);



                    List <double> features = FeatureDetector.featuresFromBitmapDouble(clone, detector_params, 5);

                    features_all.Add(features.ToArray());
                    if (img_it < 2 && debug_enabled)
                    {
                        clone.Save("aug_imgs/aug_" + img_it + "_" + i + ".jpg", ImageFormat.Jpeg);
                    }
                    clone.Dispose();
                }

                bmp.Dispose();
            }

            return(features_all.ToArray());
        }
Beispiel #2
0
        public static DetectorParameters PerformTraining(double[][] positive_data, double[][] negative_data, DetectorParameters current_detector_params)
        {
            // Create a new One-class SVM learning algorithm
            var teacher = new OneclassSupportVectorLearning <Gaussian>()
            {
                UseKernelEstimation = true,
                Nu = 0.1
            };


            // Learn a support vector machine
            var svm = teacher.Learn(positive_data);

            current_detector_params.SVM = svm;

            int trues  = 0;
            int falses = 0;

            foreach (double[] d_val in positive_data)
            {
                var prob           = svm.Probability(d_val);
                var log_likelihood = svm.LogLikelihood(d_val);
                var decision       = log_likelihood > current_detector_params.LogLikelihoodThreshold;

                current_detector_params.MinLogLikelihoodPositive = Math.Min(log_likelihood, current_detector_params.MinLogLikelihoodPositive);

                if (decision == true)
                {
                    trues++;
                }
                else
                {
                    falses++;
                }
            }

            System.Console.WriteLine("Positive Trues: " + trues.ToString() + " Falses: " + falses.ToString() + " (Min log-likelihood: " + current_detector_params.MinLogLikelihoodPositive.ToString() + ")");


            trues  = 0;
            falses = 0;


            foreach (double[] d_val in negative_data)
            {
                var prob           = svm.Probability(d_val);
                var log_likelihood = svm.LogLikelihood(d_val);
                var decision       = log_likelihood > current_detector_params.LogLikelihoodThreshold;

                current_detector_params.MaxLogLikelihoodNegative = Math.Max(log_likelihood, current_detector_params.MaxLogLikelihoodNegative);

                if (decision == true)
                {
                    trues++;
                }
                else
                {
                    falses++;
                }
            }


            System.Console.WriteLine("Negative Trues: " + trues.ToString() + " Falses: " + falses.ToString() + " (Max log-likelihood: " + current_detector_params.MaxLogLikelihoodNegative.ToString() + ")");

            // We want the threshold to be more on the side of "not loading", as errors during gameplay are worse.
            current_detector_params.LogLikelihoodThreshold = (3.5 * current_detector_params.MaxLogLikelihoodNegative + 2.5 * current_detector_params.MinLogLikelihoodPositive) / 6.0;
            current_detector_params.DetectsPerfectly       = current_detector_params.MaxLogLikelihoodNegative < current_detector_params.MinLogLikelihoodPositive;
            current_detector_params.LogLikelihoodDistance  = current_detector_params.MinLogLikelihoodPositive - current_detector_params.MaxLogLikelihoodNegative;

            return(current_detector_params);
        }
Beispiel #3
0
        /// <summary>
        /// Opens 2 folders (loading / non-loading examples), and automatically trains and tunes the hyperparameters of the SVM detection.
        /// </summary>
        public static DetectorParameters OptimizeDetectorFromFolders(ImageCaptureInfo info, string settingsPath)
        {
            // TODO: determine if accord+svm is fast enough for real-time detection
            // TODO: implement "record" tab in livesplit plugin to record data, which can then be used/sorted for training.


            // TODO: cleanup. load both datasets. fill them with more data (especially the regular gameplay case), then find best model with largest separation
            //			      we can easily do this be passing the number of bins, and patch sizes via grid search, compute features, etc.
            //				  the optimization criterion is largest difference between min and max log likelihood. we then simply choose the middle one.
            //				  these settings will then be stored in a JSON file so it's optimized per game.

            DetectorParameters best_detector_params    = new DetectorParameters();
            DetectorParameters current_detector_params = new DetectorParameters();

            FolderBrowserDialog fbd = new FolderBrowserDialog();

            fbd.RootFolder   = System.Environment.SpecialFolder.MyComputer;
            fbd.SelectedPath = settingsPath;

            fbd.Description = "Choose a folder containing image patches captured during LOADING.";
            if (fbd.ShowDialog() != DialogResult.OK)
            {
                return(null);
            }
            string positive_path = fbd.SelectedPath;

            fbd              = new FolderBrowserDialog();
            fbd.RootFolder   = System.Environment.SpecialFolder.MyComputer;
            fbd.SelectedPath = settingsPath;

            fbd.Description = "Choose a folder containing image patches captured during regular gameplay.";
            if (fbd.ShowDialog() != DialogResult.OK)
            {
                return(null);
            }
            string negative_path = fbd.SelectedPath;



            // Setup grid search parameters

            int[] patch_sizes_x            = { info.featureSizeX, info.featureSizeX / 2, info.featureSizeX / 4, info.featureSizeX / 8 }; //{ 10, 20, 25, 50, 100, 300 };
            int[] patch_sizes_y            = { info.featureSizeY, info.featureSizeY / 2, info.featureSizeY / 4, info.featureSizeY / 8 }; //{ 10, 20, 25, 50, 100 };
            int[] number_of_histogram_bins = { 4, 8, 16 };

            foreach (var patch_size_x in patch_sizes_x)
            {
                foreach (var patch_size_y in patch_sizes_y)
                {
                    foreach (var histogram_bins in number_of_histogram_bins)
                    {
                        System.Console.WriteLine("Training: pX = " + patch_size_x + ", pY = " + patch_size_y + ", bins = " + histogram_bins);

                        current_detector_params = new DetectorParameters();
                        current_detector_params.HistogramPatchSizeX   = patch_size_x;
                        current_detector_params.HistogramPatchSizeY   = patch_size_y;
                        current_detector_params.HistogramNumberOfBins = histogram_bins;

                        var positive_data = FeaturesFromFolder(positive_path, current_detector_params);
                        var negative_data = FeaturesFromFolder(negative_path, current_detector_params);

                        current_detector_params = PerformTraining(positive_data, negative_data, current_detector_params);

                        if (current_detector_params.DetectsPerfectly && current_detector_params.LogLikelihoodDistance > best_detector_params.LogLikelihoodDistance)
                        {
                            best_detector_params = (DetectorParameters)current_detector_params.Clone();
                        }
                    }
                }
            }



            System.Console.WriteLine("Best parameters: ");
            System.Console.WriteLine("HistogramPatchSizeX: " + best_detector_params.HistogramPatchSizeX);
            System.Console.WriteLine("HistogramPatchSizeY: " + best_detector_params.HistogramPatchSizeY);
            System.Console.WriteLine("HistogramNumberOfBins: " + best_detector_params.HistogramNumberOfBins);
            System.Console.WriteLine("MinLogLikelihoodPositive: " + best_detector_params.MinLogLikelihoodPositive);
            System.Console.WriteLine("MaxLogLikelihoodNegative: " + best_detector_params.MaxLogLikelihoodNegative);
            System.Console.WriteLine("LogLikelihoodDistance: " + best_detector_params.LogLikelihoodDistance);
            System.Console.WriteLine("LogLikelihoodThreshold: " + best_detector_params.LogLikelihoodThreshold);

            return(best_detector_params);
        }
Beispiel #4
0
        public static DetectorParameters PerformTrainingBinarySVM(double[][] positive_data, double[][] negative_data, DetectorParameters current_detector_params)
        {
            var teacher = new SequentialMinimalOptimization <Gaussian>()
            {
                UseKernelEstimation    = true,
                UseComplexityHeuristic = true
            };

            var data = new double[positive_data.GetLength(0) + negative_data.GetLength(0)][];

            List <double[]> data_examples = new List <double[]>();
            List <double>   targets       = new List <double>();


            for (int i = 0; i < positive_data.GetLength(0); ++i)
            {
                data_examples.Add(positive_data[i]);
                targets.Add(0);
            }

            for (int i = 0; i < negative_data.GetLength(0); ++i)
            {
                data_examples.Add(negative_data[i]);
                targets.Add(1);
            }


            var all_examples = data_examples.ToArray();
            var all_targets  = targets.ToArray();



            // Learn a support vector machine
            var svm = teacher.Learn(all_examples, all_targets);

            current_detector_params.SVM = svm;

            int trues  = 0;
            int falses = 0;

            foreach (double[] d_val in positive_data)
            {
                var prob           = svm.Probability(d_val);
                var log_likelihood = svm.LogLikelihood(d_val);
                var decision       = log_likelihood > current_detector_params.LogLikelihoodThreshold;

                current_detector_params.MinLogLikelihoodPositive = Math.Min(log_likelihood, current_detector_params.MinLogLikelihoodPositive);

                if (decision == true)
                {
                    trues++;
                }
                else
                {
                    falses++;
                }
            }

            System.Console.WriteLine("Positive Trues: " + trues.ToString() + " Falses: " + falses.ToString() + " (Min log-likelihood: " + current_detector_params.MinLogLikelihoodPositive.ToString() + ")");


            trues  = 0;
            falses = 0;


            foreach (double[] d_val in negative_data)
            {
                var prob           = svm.Probability(d_val);
                var log_likelihood = svm.LogLikelihood(d_val);
                var decision       = log_likelihood > current_detector_params.LogLikelihoodThreshold;

                current_detector_params.MaxLogLikelihoodNegative = Math.Max(log_likelihood, current_detector_params.MaxLogLikelihoodNegative);

                if (decision == true)
                {
                    trues++;
                }
                else
                {
                    falses++;
                }
            }


            System.Console.WriteLine("Negative Trues: " + trues.ToString() + " Falses: " + falses.ToString() + " (Max log-likelihood: " + current_detector_params.MaxLogLikelihoodNegative.ToString() + ")");

            // We want the threshold to be more on the side of "not loading", as errors during gameplay are worse.
            current_detector_params.LogLikelihoodThreshold = (3.5 * current_detector_params.MaxLogLikelihoodNegative + 2.5 * current_detector_params.MinLogLikelihoodPositive) / 6.0;
            current_detector_params.DetectsPerfectly       = current_detector_params.MaxLogLikelihoodNegative < current_detector_params.MinLogLikelihoodPositive;
            current_detector_params.LogLikelihoodDistance  = current_detector_params.MinLogLikelihoodPositive - current_detector_params.MaxLogLikelihoodNegative;

            return(current_detector_params);
        }