예제 #1
0
        /// <summary>
        /// Evaluates a list of kernels against a byte[,] image.
        /// </summary>
        /// <param name="operand">The image to parse.</param>
        /// <param name="kernels">The kernels to apply.</param>
        /// <param name="evaluateKernel">The "map" function to use. For further explaination, 
        /// refer to the documentation of Kernel2DBatch.</param>
        /// <param name="reduce">The "reduce" function to use. For further explaination, 
        /// refer to the documentation of Kernel2DBatch.</param>
        /// <returns>The transformed byte[,].</returns>
        public static byte[,] Evaluate(
                byte[,] operand,
                Kernel2D[] kernels,
                EvaluateKernelDelegate evaluateKernel,
                ReduceDelegate reduce)
        {
            int width = operand.GetLength(0);
            int height = operand.GetLength(1);

            byte[,] ret = new byte[width, height];
            List<double> evaluations = new List<double>();

            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    evaluations.Clear();

                    // -> Map
                    for (int i = 0; i < kernels.Length; ++i)
                    {
                        // Evaluate
                        evaluations.Add(evaluateKernel(kernels[i], operand, x, y));
                    }

                    // -> Reduce
                    ret[x, y] = reduce(evaluations);
                }
            }

            return ret;
        }
예제 #2
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Generate window ...
            int window_size = int.Parse(iConfigs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            Kernel2D kernel = new Kernel2D(0, 1.0, window);
            int i; double exponent = 1.0 / (1.0 * window_size * window_size);

            // Apply convolution with window
            byte[,] tmp_ret = Kernel2D.ApplyFunction(
                    kernel, imageSrc,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] operand)
                    {
                        double ret = 1.0;

                        try
                        {
                            for (i = 0; i < mappings.Length; ++i)
                            {
                                if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                                {
                                    ret *= operand[mappings[i].Item2.X, mappings[i].Item2.Y];
                                }
                            }
                        }
                        catch (OverflowException)
                        {
                            ret = double.MaxValue;
                        }
                        catch(Exception ex)
                        {
                            throw new Exception("Error while applying Geometric filter.", ex);
                        }

                        ret = Math.Pow(ret, exponent);

                        // trim
                        ret = Math.Min(byte.MaxValue, Math.Max(byte.MinValue, ret));

                        return (Byte)ret;
                    });

            return tmp_ret;
        }
예제 #3
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="configs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> configs)
        {
            // Generate window ...
            int window_size = int.Parse(configs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            // Run window throgh image
            Kernel2D kernel = new Kernel2D(0, 1, window);

            List<byte> tmp = new List<byte>(); int i;

            byte[,] tmp_ret = Kernel2D.ApplyFunction(
                    kernel, imageSrc,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] op)
                    {
                        tmp.Clear();

                        // Get all pixels
                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                tmp.Add(op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                            }
                        }

                        if (tmp.Count > 0)
                        {
                            // Sort
                            tmp.Sort();

                            // Get pixel in middle
                            return tmp[tmp.Count / 2];
                        }

                        return 0;
                    });

            return tmp_ret;
        }
예제 #4
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="configs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> configs)
        {
            // Generate window ...
            int window_size = int.Parse(configs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            // Run window throgh image
            Kernel2D kernel = new Kernel2D(0, 1, window);

            int i; byte _max, _min;

            byte[,] tmp_ret = Kernel2D.ApplyFunction(
                    kernel, imageSrc,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] op)
                    {
                        _max = byte.MinValue;
                        _min = byte.MaxValue;

                        // Get all pixels
                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                _max = Math.Max(_max, op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                                _min = Math.Min(_min, op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                            }
                        }

                        return (Byte)Math.Min(
                                byte.MaxValue,
                                Math.Max(
                                        byte.MinValue,
                                        Math.Ceiling(
                                                0.5 * (_max + _min))));
                    });

            return tmp_ret;
        }
예제 #5
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Generate window ...
            int window_size = int.Parse(iConfigs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            Kernel2D kernel = new Kernel2D(0, 1.0, window);
            int i; double numerator = (window_size * window_size);

            // Apply convolution with window
            byte[,] tmp_ret = Kernel2D.ApplyFunction(
                    kernel, imageSrc,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] operand)
                    {
                        double ret = 0.0;

                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                ret += 1.0 / (double)operand[mappings[i].Item2.X, mappings[i].Item2.Y];
                            }
                        }

                        if (ret != 0)
                        {
                            ret = numerator / ret;
                        }

                        // trim
                        ret = Math.Min(byte.MaxValue, Math.Max(byte.MinValue, ret));

                        return (Byte)ret;
                    });

            return tmp_ret;
        }
예제 #6
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="iImageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] iImageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Kernels in Gonzalez and Woods: Figure 3.39, 3.41

            //3x3:
            // 0 1 0
            // 1 -4 1
            // 0 1 0
            //
            // 0 -1 0
            // -1 4 -1
            // 0 -1 0
            //
            // 1 1 1
            // 1 -8 1
            // 1 1 1
            //
            // -1 2 -1
            // 2 -4 2
            // -1 2 -1

            double alpha = double.Parse(iConfigs["Alpha"].ToString());

            Kernel2D kernel = new Kernel2D(0, 1.0, GenerateFilter(alpha));

            byte[,] tmp_ret = Kernel2D.ApplyConvolution(kernel, iImageSrc);

            double t = double.Parse(iConfigs["Threshold"].ToString());

            if (t > 0)
            {
                // Apply High and Low Thresholding ...

                HighThreshold h = new HighThreshold();
                SortedDictionary<string, object> hConf = h.GetDefaultConfigs();
                hConf["High-Threshold"] = t + 1;

                LowThreshold l = new LowThreshold();
                SortedDictionary<string, object> lConf = l.GetDefaultConfigs();
                lConf["Low-Thresold"] = t;

                tmp_ret = h.ApplyFilter(tmp_ret, hConf);
                tmp_ret = l.ApplyFilter(tmp_ret, lConf);
            }

            return tmp_ret;
        }
예제 #7
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Generate window ...
            int window_size = int.Parse(iConfigs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            Kernel2D kernel = new Kernel2D(0, 1.0 / (window_size * window_size), window);

            // Apply convolution with window
            byte[,] tmp_ret = Kernel2D.ApplyConvolution(kernel, imageSrc);

            return tmp_ret;
        }
예제 #8
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="iImageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] iImageSrc, SortedDictionary<string, object> iConfigs)
        {
            double sigma = double.Parse(iConfigs["Sigma"].ToString());

            Kernel2D kernel = new Kernel2D(0, 1.0, GenerateFilter(sigma));

            byte[,] tmp_ret = Kernel2D.ApplyConvolution(kernel, iImageSrc);

            return tmp_ret;
        }
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="img"></param>
        /// <param name="configs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] img, SortedDictionary<string, object> configs)
        {
            // (1) Take gradient of image - Sobel operator.
            // (Compute and take separately the x and y componentes into Gx and Gy)
            Kernel2D kernel_x = new Kernel2D(0, (1 / 4.0),
                    new double[,] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } });
            Kernel2D kernel_y = new Kernel2D(0, (1 / 4.0),
                    new double[,] { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } });

            int width = img.GetLength(0), height = img.GetLength(1);
            double[,] edges_dir = new double[width, height];
            byte[,] step2 = new byte[width, height];

            const double degree_factor = 180.0 / Math.PI;

            Tuple<Point, Point>[] mappings; double g_x, g_y, dummy;
            int i;

            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    // Get neighbors to parse
                    mappings = kernel_x.ResolvePositions(x, y, width, height);
                    g_x = 0; g_y = 0;

                    // Calculate convolution
                    for (i = 0; i < mappings.Length; ++i)
                    {
                        if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                        {
                            g_x += img[mappings[i].Item2.X, mappings[i].Item2.Y] * kernel_x.Matrix[mappings[i].Item1.X, mappings[i].Item1.Y];
                            g_y += img[mappings[i].Item2.X, mappings[i].Item2.Y] * kernel_y.Matrix[mappings[i].Item1.X, mappings[i].Item1.Y];
                        }
                    }

                    g_x = g_x * kernel_x.Multiplier + kernel_x.Threeshold;
                    g_y = g_y * kernel_y.Multiplier + kernel_y.Threeshold;

                    step2[x, y] = (byte)Math.Sqrt(g_x * g_x + g_y * g_y);

                    // (2) Calculate edge direction, using Gx and Gy

                    if (0 == g_x)
                    {
                        edges_dir[x, y] = (0 == g_y ? 0 : 90);
                    }
                    else
                    {
                        // need to convert in degree
                        edges_dir[x, y] = Math.Atan(g_y / g_x) * degree_factor;
                    }

                    // (3) Relate edge direction to a direction that can be traced in the image (0º, 45º, 90º, 135º)
                    dummy = edges_dir[x, y];

                    // [0;22.5] e [157.5;180]  = 0
                    // [22.5;67.5] = 45
                    // [67.5;112.5] = 90
                    // [112.5;157.5] = 135

                    //if (dummy > 180)
                    //    throw new Exception(string.Format("Theta = {0}", dummy));

                    if (dummy >= 157.5 || dummy < 22.5)
                    {
                        edges_dir[x, y] = 0;
                    }
                    else if (dummy >= 112.5)
                    {
                        edges_dir[x, y] = 135;
                    }
                    else if (dummy >= 67.5)
                    {
                        edges_dir[x, y] = 90;
                    }
                    else if (dummy >= 22.5)
                    {
                        edges_dir[x, y] = 45;
                    }
                }
            }
            mappings = null;

            // (4) Apply non maximum suppression. Set to 0 any pixel that is not a local maximum;
            // compare with neighbourhood using edge direction ...
            //
            // for point (x,y) test:
            // dir = 0, (x, y-1) and (x, y+1)
            // dir = 45, (x+1, y+1) and (x-1, y-1)
            // dir = 90, (x-1, y) and (x+1, y)
            // dir = 135, (x+1, y-1) and (x-1, y+1)

            Point[] neighborhood;

            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    dummy = edges_dir[x, y];

                    // Ignore, PLEASE, out of bound values ...
                    neighborhood = GetNeighborhood(x, y, width, height, dummy);

                    i = 0;
                    while (step2[x, y] != 0 && i < neighborhood.Length)
                    {
                        if (step2[x, y] < step2[neighborhood[i].X, neighborhood[i].Y])
                        {
                            step2[x, y] = 0;
                        }
                        ++i;
                    }

                }
            }

            return step2;
        }
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="imageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] imageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Generate window ...
            int window_size = int.Parse(iConfigs["window size"].ToString());

            if (window_size % 2 == 0)
                throw new Exception("Window size must be odd!");

            double[,] window = new double[window_size, window_size];
            for (int x = 0; x < window_size; ++x)
            {
                for (int y = 0; y < window_size; ++y)
                {
                    window[x, y] = 1;
                }
            }

            // Run window through image
            Kernel2D kernel = new Kernel2D(0, 1, window);
            int p = int.Parse(iConfigs["p"].ToString());

            List<byte> tmp = new List<byte>(); int i; double ret;

            byte[,] tmp_ret = Kernel2D.ApplyFunction(
                    kernel, imageSrc,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] op)
                    {
                        tmp.Clear();

                        // Get all pixels
                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                tmp.Add(op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                            }
                        }

                        // Do paddings with 0s and 255s.
                        // Put more 255 on end if difference is odd
                        {
                            int diff = window_size * window_size - tmp.Count;
                            if (diff > 0)
                            {
                                byte[] zeros = new byte[diff / 2];
                                byte[] maxes = new byte[(int)Math.Ceiling(diff / 2.0)];

                                // zeros automatically initialized with zeros
                                // ...

                                // init maxes to byte.MaxValue
                                for (i = 0; i < maxes.Length; ++i)
                                    maxes[i] = byte.MaxValue;

                                tmp.InsertRange(0, zeros);
                                tmp.AddRange(maxes);
                            }
                        }

                        if (tmp.Count > 0)
                        {
                            // Sort
                            tmp.Sort();

                            ret = 0.0;

                            for (i = p; i < tmp.Count - p; ++i)
                            {
                                ret += tmp[i];
                            }

                            ret = 1.0 / ((double)tmp.Count - 2.0 * (double)p) * ret;

                            // trim
                            ret = Math.Min(byte.MaxValue, Math.Max(byte.MinValue, ret));

                            return (Byte)ret;
                        }

                        return 0;
                    });

            return tmp_ret;
        }
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="iImageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <remarks>Final implementation based on edge.m</remarks>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] iImageSrc, SortedDictionary<string, object> iConfigs)
        {
            // Generating _masksAnti: Simplified Approach to Image Processing.pdf (pdf p.99)
            // See also de Difference of Gaussians: Simplified Approach to Image Processing.pdf (pdf p.100)

            //int dim = int.Parse(iConfigs["dim"].ToString());
            //double std = double.Parse(iConfigs["std dev"].ToString());

            //if (dim % 2 == 0)
            //    throw new Exception("Dim should be odd!");

            //double[,] lap_gauss = (double[,])Array.CreateInstance(typeof(double), dim, dim);
            //double funny_const = -1.0 / (Math.PI * std * std * std * std);
            //double funny_const2;

            //for (int x = 0; x < dim; ++x)
            //{
            //    for (int y = 0; y < dim; ++y)
            //    {
            //        funny_const2 =
            //                -1.0 * (x*x + y*y) /
            //                    (2.0 * std * std);

            //        lap_gauss[x, y] = (int) (
            //                funny_const
            //                * (1.0 + funny_const2)
            //                * Math.Pow(Math.E, funny_const2));

            //    }
            //}

            //Kernel2D kernel = new Kernel2D(
            //       0,
            //       1 / (9.0 * 9.0),
            //    //lap_gauss
            //           new double[,] {
            //                { 0, 1, 1, 2, 2, 2, 1, 1, 0 },
            //                { 1, 2, 4, 5, 5, 5 , 4, 2, 1 },
            //                { 1, 4, 5, 3, 0, 3 , 5, 4, 1 },
            //                { 2, 5, 3, -12, -24, -12 , 3, 5, 2 },
            //                { 2, 5, 0, -24, -40, -24 , 0, 5, 2 },
            //                { 2, 5, 3, -12, -24, -12 , 3, 5, 2 },
            //                { 1, 4, 5, 3, 0, 3 , 5, 4, 1 },
            //                { 1, 2, 4, 5, 5, 5 , 4, 2, 1 },
            //                { 0, 1, 1, 2, 2, 2 , 1, 1, 0 }
            //           }
            //       );

            double sigma = double.Parse(iConfigs["Sigma"].ToString());

            Kernel2D kernel = new Kernel2D(0, 1.0, GenerateFilter(sigma));

            double[,] tmp = Facilities.ToDouble(iImageSrc);
            tmp = Kernel2D.ApplyConvolution(kernel, tmp);

            int x, y, width = tmp.GetLength(0), height = tmp.GetLength(1);

            double t = double.Parse(iConfigs["Threshold"].ToString()) / (double)byte.MaxValue;
            // Find zero crossings
            bool[,] edges = new bool[width, height];

            for (x = 1; x < width - 1; ++x)
            {
                for (y = 1; y < height - 1; ++y)
                {
                    if (tmp[x, y] < 0 && tmp[x, y + 1] > 0 && Math.Abs(tmp[x, y] - tmp[x, y + 1]) > t)
                    {
                        edges[x, y] = true;
                    }
                    if (tmp[x, y] < 0 && tmp[x, y - 1] > 0 && Math.Abs(tmp[x, y] - tmp[x, y - 1]) > t)
                    {
                        edges[x, y] = true;
                    }
                    if (tmp[x, y] < 0 && tmp[x + 1, y] > 0 && Math.Abs(tmp[x, y] - tmp[x + 1, y]) > t)
                    {
                        edges[x, y] = true;
                    }
                    if (tmp[x, y] < 0 && tmp[x - 1, y] > 0 && Math.Abs(tmp[x, y] - tmp[x - 1, y]) > t)
                    {
                        edges[x, y] = true;
                    }
                    if (tmp[x, y] == 0.0)
                    {
                        if (tmp[x - 1, y - 1] < 0 && tmp[x + 1, y + 1] > 0 && Math.Abs(tmp[x - 1, y - 1] - tmp[x + 1, y + 1]) > t)
                        {
                            edges[x, y] = true;
                        }
                        if (tmp[x - 1, y - 1] > 0 && tmp[x + 1, y + 1] < 0 && Math.Abs(tmp[x - 1, y - 1] - tmp[x + 1, y + 1]) > t)
                        {
                            edges[x, y] = true;
                        }
                        if (tmp[x + 1, y - 1] < 0 && tmp[x - 1, y + 1] > 0 && Math.Abs(tmp[x + 1, y - 1] - tmp[x - 1, y + 1]) > t)
                        {
                            edges[x, y] = true;
                        }
                        if (tmp[x + 1, y - 1] > 0 && tmp[x - 1, y + 1] < 0 && Math.Abs(tmp[x + 1, y - 1] - tmp[x - 1, y + 1]) > t)
                        {
                            edges[x, y] = true;
                        }
                    }
                }
            }

            byte[,] tmp_ret = Facilities.To8bppGreyScale(edges);

            return tmp_ret;
        }
예제 #12
0
        /// <summary>
        /// Apply filter to a byte[,].
        /// </summary>
        /// <param name="iImageSrc"></param>
        /// <param name="iConfigs"></param>
        /// <returns></returns>
        public override byte[,] ApplyFilter(byte[,] iImageSrc, SortedDictionary<string, object> iConfigs)
        {
            int width = iImageSrc.GetLength(0), height = iImageSrc.GetLength(1);
            byte threshold = byte.Parse(iConfigs["Threshold"].ToString());

            Kernel2D[] kernels = new Kernel2D[] {
                            new Kernel2D(0, (1/15.0), new double[,] { { 5,5,5 }, { -3,0,-3 }, { -3,-3,-3 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { 5,5,-3 }, { 5,0,-3 }, { -3,-3,-3 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { 5,-3,-3 }, { 5,0,-3 }, { 5,-3,-3 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { -3,-3,-3 }, { 5,0,-3 }, { 5,5,-3 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { -3,-3,-3 }, { -3,0,-3 }, { 5,5,5 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { -3,-3,-3 }, { -3,0,5 }, { -3,5,5 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { -3,-3,5 }, { -3,0,5 }, { -3,-3,5 } }),
                            new Kernel2D(0, (1/15.0), new double[,] { { -3,5,5 }, { -3,0,5 }, { -3,-3,-3 } })
                        };

            byte[,] tmp_ret = Kernel2DBatch.Evaluate(
                    iImageSrc,
                    kernels,
                    delegate(Kernel2D k, byte[,] op, int x, int y)
                    {
                        double total = 0;
                        Tuple<Point, Point>[] mappings = k.ResolvePositions(x, y, width, height);

                        for (int i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                total += (
                                        op[mappings[i].Item2.X, mappings[i].Item2.Y]
                                        *
                                        k.Matrix[mappings[i].Item1.X, mappings[i].Item1.Y]
                                    );
                            }
                        }

                        total = total * k.Multiplier + k.Threeshold;

                        return total;
                        // subtle bug discovered at 02-06-2011
                        //return Math.Min(byte.MaxValue, Math.Max(byte.MinValue, total));
                    },
                    delegate(List<double> values)
                    {
                        double tot = values[0];
                        //for (int i = 0; i < values.Count; ++i)
                        //{
                        //    tot += Math.Pow(values[i], 2);
                        //}
                        //tot = Math.Sqrt(tot);

                        for (int i = 0; i < values.Count; ++i)
                        {
                            tot += Math.Abs(values[i]);
                        }

                        // Values smaller than the threshold are forced to zero
                        if (tot < threshold)
                        {
                            tot = 0;
                        }

                        return (byte)Math.Min(byte.MaxValue, Math.Max(byte.MinValue, tot));
                    });

            return tmp_ret;
        }
예제 #13
0
        /// <summary>
        /// Apply a function to a byte[,] image, using the Kernel2D kernel.
        /// </summary>
        /// <param name="kernel">The kernel to use in the parsing.</param>
        /// <param name="operand">The image to apply the function.</param>
        /// <param name="callback">The function to apply.</param>
        /// <returns>The transformed byte[,].</returns>
        public static byte[,] ApplyFunction(Kernel2D kernel, byte[,] operand, ByteKernel2DCallBack callback)
        {
            int width = operand.GetLength(0); int height = operand.GetLength(1);

            byte[,] ret = new byte[width, height];
            Tuple<Point, Point>[] mappings = null;
            int x, y;

            for (x = 0; x < width; ++x)
            {
                for (y = 0; y < height; ++y)
                {
                    try
                    {
                        mappings = kernel.ResolvePositions(x, y, width, height);

                        ret[x, y] = callback(mappings, operand);
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Exception at Kernel2D.ApplyFunction", e);
                    }
                }
            }

            return ret;
        }
예제 #14
0
        /// <summary>
        /// Apply a convolution to the byte[,] image using the Kernel2D kernel.
        /// </summary>
        /// <remarks>
        /// As the output is a byte[,], the temporary result is stored in a double, but it will
        /// be clamped to be stored in a byte variable [0 .. 255].
        /// </remarks>
        /// <param name="kernel">The kernel to use in the convolution.</param>
        /// <param name="operand">The image to apply the convolution.</param>
        /// <returns>The transformed byte[,].</returns>
        public static byte[,] ApplyConvolution(Kernel2D kernel, byte[,] operand)
        {
            double tot; int i; byte normalized;

            return ApplyFunction(
                    kernel, operand,
                    delegate(Tuple<Point, Point>[] mappings, byte[,] op)
                    {
                        tot = 0; normalized = byte.MinValue;

                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                tot += (
                                    kernel._2d_matrix[mappings[i].Item1.X, mappings[i].Item1.Y] *
                                    op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                            }
                        }
                        tot = tot * kernel._multiplier + kernel._threeshold;

                        normalized = (byte)Math.Max(byte.MinValue, Math.Min(byte.MaxValue, tot));

                        return normalized;
                    });
        }
예제 #15
0
        /// <summary>
        /// Apply a convolution to the double[,] image using the Kernel2D kernel.
        /// </summary>
        /// <remarks>
        /// The output will not be clamped to be stored as byte [0 .. 255].
        /// </remarks>
        /// <param name="kernel">The kernel to use in the convolution.</param>
        /// <param name="operand">The image to apply the convolution.</param>
        /// <returns>The transformed double[,].</returns>
        public static double[,] ApplyConvolution(Kernel2D kernel, double[,] operand)
        {
            double tot; int i; double normalized;

            DoubleKernel2DCallBack function =
                    delegate(Tuple<Point, Point>[] mappings, double[,] op)
                    {
                        tot = 0; normalized = 0;

                        for (i = 0; i < mappings.Length; ++i)
                        {
                            if (mappings[i].Item2.X != -1 && mappings[i].Item2.Y != -1)
                            {
                                tot += (
                                    kernel._2d_matrix[mappings[i].Item1.X, mappings[i].Item1.Y] *
                                    op[mappings[i].Item2.X, mappings[i].Item2.Y]);
                            }
                        }
                        tot = tot * kernel._multiplier + kernel._threeshold;

                        normalized = tot;

                        return normalized;
                    };

            return ApplyFunction(kernel, operand, function);
        }