Convolution filter.

The filter implements convolution operator, which calculates each pixel of the result image as weighted sum of the correspond pixel and its neighbors in the source image. The weights are set by convolution kernel. The weighted sum is divided by Divisor before putting it into result image and also may be thresholded using Threshold value.

Convolution is a simple mathematical operation which is fundamental to many common image processing filters. Depending on the type of provided kernel, the filter may produce different results, like blur image, sharpen it, find edges, etc.

The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp color images for processing. Note: depending on the value of ProcessAlpha property, the alpha channel is either copied as is or processed with the kernel.

Sample usage:

// define emboss kernel int[,] kernel = { { -2, -1, 0 }, { -1, 1, 1 }, { 0, 1, 2 } }; // create filter Convolution filter = new Convolution( kernel ); // apply the filter filter.ApplyInPlace( image );

Initial image:

Result image:

Inheritance: BaseUsingCopyPartialFilter
Example #1
0
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int width  = sourceData.Width;
            int height = sourceData.Height;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;

            int srcStride = sourceData.Stride;
            int dstStride = destinationData.Stride;

            int srcOffset = srcStride - width * pixelSize;
            int dstOffset = dstStride - width * pixelSize;

            byte *src = (byte *)sourceData.ImageData.ToPointer();
            byte *dst = (byte *)destinationData.ImageData.ToPointer();

            // TODO: Move or cache the creation of those filters
            int[,] kernel = Accord.Math.Matrix.Create(radius * 2 + 1, radius * 2 + 1, 1);
            Convolution  conv = new Convolution(kernel);
            FastVariance fv   = new FastVariance(radius);

            // Mean filter
            UnmanagedImage mean = conv.Apply(sourceData);

            // Variance filter
            UnmanagedImage var = fv.Apply(sourceData);

            // do the processing job
            if (sourceData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                byte *srcVar  = (byte *)var.ImageData.ToPointer();
                byte *srcMean = (byte *)mean.ImageData.ToPointer();

                // Store maximum value from variance.
                int maxV = Max(width, height, srcVar, srcOffset);

                // Store minimum value from image.
                int minG = Min(width, height, src, srcOffset);

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++, src++, srcMean++, srcVar++, dst++)
                    {
                        double mP = *srcMean;
                        double vP = *srcVar;

                        double threshold = (mP + k * ((Math.Sqrt(vP) / (double)maxV - 1.0) * (mP - (double)minG)));

                        *dst = (byte)(*src > threshold ? 255 : 0);
                    }

                    src     += srcOffset;
                    srcMean += srcOffset;
                    srcVar  += srcOffset;
                    dst     += dstOffset;
                }
            }
        }
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int         width     = sourceData.Width;
            int         height    = sourceData.Height;
            PixelFormat format    = sourceData.PixelFormat;
            int         pixelSize = System.Drawing.Bitmap.GetPixelFormatSize(format) / 8;

            sourceData.Clone();

            UnmanagedImage temp = UnmanagedImage.Create(width, height, format);

            int lineWidth = width * pixelSize;

            int srcStride = temp.Stride;
            int srcOffset = srcStride - lineWidth;
            int dstStride = destinationData.Stride;
            int dstOffset = dstStride - lineWidth;

            byte *srcStart = (byte *)temp.ImageData.ToPointer();
            byte *dstStart = (byte *)destinationData.ImageData.ToPointer();


            // first
            Convolution c = new Convolution(masks[0]);

            c.Apply(sourceData, destinationData);

            // others
            for (int i = 1; i < masks.Length; i++)
            {
                c.Kernel = masks[i];
                c.Apply(sourceData, temp);

                byte *src = srcStart;
                byte *dst = dstStart;

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < lineWidth; x++, src++, dst++)
                    {
                        if (*src > *dst)
                        {
                            *dst = *src;
                        }
                    }

                    dst += dstOffset;
                    src += srcOffset;
                }
            }
        }
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// 
        protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int width = sourceData.Width;
            int height = sourceData.Height;
            PixelFormat format = sourceData.PixelFormat;
            int pixelSize = System.Drawing.Bitmap.GetPixelFormatSize(format) / 8;

            sourceData.Clone();

            UnmanagedImage temp = UnmanagedImage.Create(width, height, format);

            int lineWidth = width * pixelSize;

            int srcStride = temp.Stride;
            int srcOffset = srcStride - lineWidth;
            int dstStride = destinationData.Stride;
            int dstOffset = dstStride - lineWidth;

            byte* srcStart = (byte*)temp.ImageData.ToPointer();
            byte* dstStart = (byte*)destinationData.ImageData.ToPointer();


            // first
            Convolution c = new Convolution(masks[0]);
            c.Apply(sourceData, destinationData);

            // others
            for (int i = 1; i < masks.Length; i++)
            {
                c.Kernel = masks[i];
                c.Apply(sourceData, temp);

                byte* src = srcStart;
                byte* dst = dstStart;

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < lineWidth; x++, src++, dst++)
                    {
                        if (*src > *dst)
                            *dst = *src;
                    }

                    dst += dstOffset;
                    src += srcOffset;
                }
            }
        }
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// 
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int width = sourceData.Width;
            int height = sourceData.Height;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;

            int srcStride = sourceData.Stride;
            int dstStride = destinationData.Stride;

            int srcOffset = srcStride - width * pixelSize;
            int dstOffset = dstStride - width * pixelSize;

            byte* src = (byte*)sourceData.ImageData.ToPointer();
            byte* dst = (byte*)destinationData.ImageData.ToPointer();

            // TODO: Move or cache the creation of those filters
            int[,] kernel = Accord.Math.Matrix.Create(radius * 2 + 1, radius * 2 + 1, 1);
            Convolution conv = new Convolution(kernel);
            FastVariance fv = new FastVariance(radius);

            // Mean filter
            UnmanagedImage mean = conv.Apply(sourceData);

            // Variance filter
            UnmanagedImage var = fv.Apply(sourceData);

            // do the processing job
            if (sourceData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                byte* srcVar = (byte*)var.ImageData.ToPointer();
                byte* srcMean = (byte*)mean.ImageData.ToPointer();

                // Store maximum value from variance.
                int maxV = Max(width, height, srcVar, srcOffset);

                // Store minimum value from image.
                int minG = Min(width, height, src, srcOffset);

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++, src++, srcMean++, srcVar++, dst++)
                    {
                        double mP = *srcMean;
                        double vP = *srcVar;

                        double threshold = (mP + k * ((Math.Sqrt(vP) / (double)maxV - 1.0) * (mP - (double)minG)));

                        *dst = (byte)(*src > threshold ? 255 : 0);
                    }

                    src += srcOffset;
                    srcMean += srcOffset;
                    srcVar += srcOffset;
                    dst += dstOffset;
                }
            }
        }