Navigation

Related Articles

Back to Latest Articles

C# Tutorial: How To Create Gaussian Blur


Andraz Krzisnik
C# Tutorial: How To Create Gaussian Blur

Gaussian blur is an image processing operation, that reduces noise in images. It does so by a convolution process, using a matrix that contains values calculated by a Gaussian formula. By using a convolutional filter of Gaussian blur, edges in our processed image are preserved better. This is a very crucial if we intend to use edge detection processes, such as Sobel operation.

Equation used for Gaussian blur

gaussian_formula

Where x represents distance from the origin on horizontal axis, y represents distance from the origin on vertical axis and sigma is the standard deviation of Gaussian distribution.

Origin is represented by the center pixel of the kernel we are using to convolve our image. Center pixel recieves the highest Gaussian value, while the neighboring pixels receive the smaller values as the distance from the origin increases.

Gaussian function in C#

public static double[,] GaussianBlur(int lenght, double weight)
{
    double[,] kernel = new double[lenght, lenght];
    double kernelSum = 0;
    int foff = (lenght - 1) / 2;
    double distance = 0;
    double constant = 1d / (2 * Math.PI * weight * weight);
    for (int y = -foff; y <= foff; y++)
    {
        for (int x = -foff; x <= foff; x++)
        {
            distance = ((y * y) + (x * x)) / (2 * weight * weight);
            kernel[y + foff, x + foff] = constant * Math.Exp(-distance);
            kernelSum += kernel[y + foff, x + foff];
        }
    }
    for (int y = 0; y < lenght; y++)
    {
        for (int x = 0; x < lenght; x++)
        {
            kernel[y, x] = kernel[y, x] * 1d / kernelSum;
        }
    }
    return kernel;
}

 

Lenght and weight variables are input parameters for the function. The entire function outputs a kernel, with values calculated according to Gaussian function.

Function for image convolution

public static Bitmap Convolve(Bitmap srcImage, double[,] kernel)
{
    int width = srcImage.Width;
    int height = srcImage.Height;
    BitmapData srcData = srcImage.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    int bytes = srcData.Stride * srcData.Height;
    byte[] buffer = new byte[bytes];
    byte[] result = new byte[bytes];
    Marshal.Copy(srcData.Scan0, buffer, 0, bytes);
    srcImage.UnlockBits(srcData);
    int colorChannels = 3;
    double[] rgb = new double[colorChannels];
    int foff = (kernel.GetLength(0) - 1) / 2;
    int kcenter = 0;
    int kpixel = 0;
    for (int y = foff; y < height - foff; y++)
    {
        for (int x = foff; x < width - foff; x++)
        {
            for (int c = 0; c < colorChannels; c++)
            {
                rgb[c] = 0.0;
            }
            kcenter = y * srcData.Stride + x * 4;
            for (int fy = -foff; fy <= foff; fy++)
            {
                for (int fx = -foff; fx <= foff; fx++)
                {
                    kpixel = kcenter + fy * srcData.Stride + fx * 4;
                    for (int c = 0; c < colorChannels; c++)
                    {
                        rgb[c] += (double)(buffer[kpixel + c]) * kernel[fy + foff, fx + foff];
                    }
                }
            }
            for (int c = 0; c < colorChannels; c++)
            {
                if (rgb[c] > 255)
                {
                    rgb[c] = 255;
                }
                else if (rgb[c] < 0)
                {
                    rgb[c] = 0;
                }
            }
            for (int c = 0; c < colorChannels; c++)
            {
                result[kcenter + c] = (byte)rgb[c];
            }
            result[kcenter + 3] = 255;
        }
    }
    Bitmap resultImage = new Bitmap(width, height);
    BitmapData resultData = resultImage.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    Marshal.Copy(result, 0, resultData.Scan0, bytes);
    resultImage.UnlockBits(resultData);
    return resultImage;
}

This tutorial is accompanied by project source code

Download

Please leave a comment below, I’d love to see what you have to say on this matter.

Show Comments (1)

Comments

  • LucianaStall

    I see your blog needs some fresh content. Writing manually is time consuming, but there is
    solution for this hard task. Just search for; Miftolo’s tools rewriter

    • Article Author
    • Reply

Related Articles

C# Basics

C# Basics – Writing Code – Part 2

When we create a project, first thing we will see are a bunch of windows. Let’s talk about what each of these windows do: Editor is a window meant for writing code Solution...

Posted on by Andraz Krzisnik
C# Basics

C# Basics – Loops – Part 6

Loops Let’s say we want to display a message box for each number from 0 to 20. With the knowledge, we have thus far acquired, we can easily achieve this. But what about, if we...

Posted on by Andraz Krzisnik