private static double[] GetTrainingImage(FeatureRecognizer_Image image, ConvolutionBase2D kernel)
        {
            // Enlarge the initial image by the kernel's reduction so that after convolution, it is the desired size
            VectorInt reduction = kernel.GetReduction();
            if (reduction.X != reduction.Y)
            {
                throw new ApplicationException(string.Format("Kernel should be square: {0}x{1}", reduction.X, reduction.Y));
            }

            BitmapSource bitmap = new BitmapImage(new Uri(image.Filename));
            bitmap = UtilityWPF.ResizeImage(bitmap, IMAGESIZE + reduction.X, true);

            Convolution2D retVal = UtilityWPF.ConvertToConvolution(bitmap, 1d);
            if (retVal.Width != retVal.Height)
            {
                retVal = Convolutions.ExtendBorders(retVal, IMAGESIZE + reduction.X, IMAGESIZE + reduction.X);        //NOTE: width or height is already the desired size, this will just enlarge the other to make it square
            }

            retVal = Convolutions.Convolute(retVal, kernel);
            retVal = Convolutions.Abs(retVal);

            // It looks better when it's black on white
            double[] inverted = retVal.Values.
                Select(o => 1d - o).
                ToArray();

            return inverted;
        }
        private static ReducedExtract[] GetExtractSizes(BitmapSource bitmap, ConvolutionBase2D filter, RectInt rect, int minExtractSize = 10)
        {
            List<ReducedExtract> retVal = new List<ReducedExtract>();

            VectorInt filterReduce = filter == null ? new VectorInt(0, 0) : filter.GetReduction();

            Rect percents = new Rect()
            {
                X = rect.X.ToDouble() / bitmap.PixelWidth.ToDouble(),
                Y = rect.Y.ToDouble() / bitmap.PixelHeight.ToDouble(),
                Width = rect.Width.ToDouble() / bitmap.PixelWidth.ToDouble(),
                Height = rect.Height.ToDouble() / bitmap.PixelHeight.ToDouble(),
            };

            double percent = 1d;

            while (true)
            {
                VectorInt imageSize = new VectorInt()
                {
                    X = (bitmap.PixelWidth * percent).ToInt_Round(),
                    Y = (bitmap.PixelHeight * percent).ToInt_Round(),
                };

                VectorInt postSize = imageSize - filterReduce;

                RectInt newRect = new RectInt()
                {
                    X = (percents.X * postSize.X).ToInt_Round(),
                    Y = (percents.Y * postSize.Y).ToInt_Round(),
                    Width = (percents.Width * postSize.X).ToInt_Round(),
                    Height = (percents.Height * postSize.Y).ToInt_Round(),
                };

                if (newRect.Width < minExtractSize || newRect.Height < minExtractSize)
                {
                    break;
                }

                retVal.Add(new ReducedExtract()
                {
                    Percent = percent,
                    ImageSize = imageSize,
                    Extract = newRect,
                });

                percent *= .75;
            }

            return retVal.ToArray();
        }