public static byte[] getDifferenceOfGaussins(byte[] imageBytes, int k = 7)
        {
            double[] image = setGrayScale(doubleArray(imageBytes));

            /*double[,] gaussKer = new double[,] { { 1 / 16.0, 1 / 8.0, 1 / 16.0 },
             *                                   { 1 / 8.0,  1 / 4.0, 1 / 8.0 },
             *                                   { 1 / 16.0, 1 / 8.0, 1 / 16.0 }};*/

            double[,] gaussKer = Kernels.getGaussian(0.7);

            double[][] smoothedImages = new double[Height][];

            smoothedImages[0] = image.Clone() as double[];
            for (int i = 1; i < Height; i++)
            {
                smoothedImages[i] = applyMatrix(smoothedImages[i - 1], gaussKer);
            }

            double[][] lapassedImages = new double[Height - 1][];
            for (int i = 0; i < Height - 1; i++)
            {
                lapassedImages[i] = substractArrays(smoothedImages[i + 1], smoothedImages[i]);
            }

            return(byteArray(Array.ConvertAll(lapassedImages[k], x => x / 2 + 120)));
        }
        public static List <double[]> getBlobCoordsUsingLaplacianKernel(byte[] imageBytes)
        {
            List <double[]> BLOBS = new List <double[]>();

            double[] image = setGrayScale(doubleArray(imageBytes));

            double[][] lapassedImages = new double[Height - 1][];
            lapassedImages[0] = applyMatrix(image, Kernels.getLaplacian(0.7));
            for (int i = 1; i < Height - 1; i++)
            {
                lapassedImages[i] = applyMatrix(image, Kernels.getLaplacian(1.4 * (i + 1)));
            }

            /*double[][] gaussedImages = new double[Height][];
             * gaussedImages[0] = applyMatrix(image, Kernels.getGaussian(0.7));
             *
             * for (int i = 1; i < Height; i++) {
             *  gaussedImages[i] = applyMatrix(gaussedImages[0], Kernels.getGaussian(1.4 * (i)));
             * }
             *
             * for (int i = 0; i < Height - 1; i++) {
             *  lapassedImages[i] = substractArrays(gaussedImages[i + 1] , gaussedImages[i]);
             * }*/

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

            for (int w = 10; w < W - 10; w++)
            {
                for (int h = 10; h < H - 10; h++)
                {
                    for (int t = 1; t < Height - 2; t++)
                    {
                        bool   isLocalMinma    = true;
                        bool   isLocalMaxima   = true;
                        double current         = lapassedImages[t][h * W + w];
                        double currentMinBound = current > 0 ? current * 1.01 : current * 0.99;
                        double currentMaxBound = current > 0 ? current * 0.99 : current * 1.01;
                        for (int dw = -1; dw <= 1; dw++)
                        {
                            for (int dh = -1; dh <= 1; dh++)
                            {
                                for (int dt = -1; dt <= 1; dt++)
                                {
                                    if ((dt != 0 || dh != 0 || dw != 0))
                                    {
                                        if ((lapassedImages[t + dt][(h + dh) * W + (w + dw)]) <= current)
                                        {
                                            isLocalMinma = false;
                                        }
                                        if ((lapassedImages[t + dt][(h + dh) * W + (w + dw)]) >= current)
                                        {
                                            isLocalMaxima = false;
                                        }
                                    }
                                }
                            }
                        }

                        if (isLocalMaxima || isLocalMinma)
                        {
                            bool hasLocalMinimaOnScale = false;
                            bool hasLocalMaximaOnScale = false;
                            int  pix = h * W + w;
                            for (int T = 1; T < Height - 2; T++)
                            {
                                if (lapassedImages[T][pix] > lapassedImages[T + 1][pix] && lapassedImages[T][pix] > lapassedImages[T - 1][pix])
                                {
                                    hasLocalMaximaOnScale = true;
                                }

                                if (lapassedImages[T][pix] < lapassedImages[T + 1][pix] && lapassedImages[T][pix] < lapassedImages[T - 1][pix])
                                {
                                    hasLocalMinimaOnScale = true;
                                }
                            }

                            if (hasLocalMaximaOnScale ^ hasLocalMinimaOnScale)
                            {
                                OUTPUTBLOBS.Add(new double[4] {
                                    w / (W + 0.0), h / (H + 0.0), 2 * (t + 1) / (W + 0.0), Math.Abs(current)
                                });
                            }
                        }
                    }
                }
            }

            OUTPUTBLOBS = OUTPUTBLOBS.Where(blob => {
                double x = blob[0];
                return(true);
            }).ToList();

            return(OUTPUTBLOBS);
        }