C# How to: Calculating Gaussian Kernels

Article Purpose

This purpose of this article is to explain and illustrate in detail the requirements involved in calculating Gaussian Kernels intended for use in image convolution when implementing Gaussian Blur filters. This article’s discussion spans from exploring concepts in theory and continues on to implement concepts through C# sample source code.

Ant: Gaussian Kernel 5×5 Weight 19

Ant Gaussian Kernel 5x5 Weight 19

Sample Source Code

This article is accompanied by a sample source code Visual Studio project which is available for download here

Calculating Gaussian Kernels Sample Source code

Using the Sample Application

A Sample Application forms part of the accompanying sample source code, intended to implement the topics discussed and also provides the means to replicate and test the concepts being illustrated.

The sample application is a Windows Forms based application which provides functionality enabling users to generate/calculate Gaussian Kernels. Calculation results are influenced through user specified options in the form of: Kernel Size and Weight.

Ladybird: Gaussian Kernel 5×5 Weight 5.5

Gaussian Kernel 5x5 Weight 5.5

In the sample application and related sample source code when referring to Kernel Size, a reference is being made relating to the physical size dimensions of the kernel/matrix used in convolution. When higher values are specified in setting the Kernel Size, the resulting output image will reflect a greater degree of blurring. Kernel Sizes being specified as lower values result in the output image reflecting a lesser degree of blurring.

In a similar fashion to the Kernel size value, the Weight value provided when generating a Kernel results in smoother/more blurred images when specified as higher values. Lower values assigned to the Weight value has the expected result of less blurring being evident in output images.

Prey Mantis: Gaussian Kernel 13×13 Weight 13

Prey Mantis Gaussian Kernel 13x13 Weight 13

The sample application has the ability to provide the user with a visual representation implementing the calculated kernel value blurring. Users are able to select source/input image from the local file system by clicking the Load Image button. When desired, users are able to save blurred/filtered images to the local file system by clicking the Save Image button.

The image below is screenshot of the Gaussian Kernel Calculator sample application in action:

Gaussian Kernel Calculator Sample Application

Calculating Gaussian Convolution Kernels

The formula implemented in calculating Gaussian Kernels can be implemented in C# source code fairly easily. Once the method in which the formula operates has been grasped the actual code implementation becomes straight forward.

The Gaussian Kernel formula can be expressed as follows:

Gaussian Kernel formula

The formula contains a number of symbols, which define how the filter will be implemented. The symbols forming part of the Gaussian Kernel formula are described in the following list:

  • G(x y) – A value calculated using the Gaussian Kernel formula. This value forms part of a Kernel, representing a single element.
  • π – Pi, one of the better known members of the Greek alphabet. The mathematical constant defined as 22 / 7.
  • σ – The lower case version of the Greek alphabet letter Sigma. This symbol simply represents a threshold or factor value, as specified by the user.
  • e – The formula references a lower case e symbol. The symbol represents Euler’s number. The value of Euler’s number has been defined as a mathematical constant equating to 2.71828182846.
  • x, y – The variables referenced as x and y relate to pixel coordinates within an image. y Representing the vertical offset or row and x represents the horizontal offset or column.

Note: The formula’s implementation expects x and y to equal zero values when representing the coordinates of the pixel located in the middle of the kernel.

Ladybird: Gaussian Kernel 13×13 Weight 9.5

Gaussian Kernel 13x13 Weight 9.5

When calculating the kernel elements, the coordinate values expressed by x and y should reflect the distance in pixels from the middle pixel. All coordinate values must be greater than zero.

In order to gain a better grasp on the Gaussian kernel formula we can implement the formula in steps. If we were to create a 3×3 kernel and specified a weighting value of 5.5 our calculations can start off as indicated by the following illustration:

Gaussian Kernel Formula

The formula has been implement on each element forming part of the kernel, 9 values in total. Coordinate values have now been replaced with actual values, differing for each position/element. Calculating zero to the power of two equates to zero. In the scenario above indicating zeros which express exponential values might help to ease initial understanding, as opposed to providing simplified values and potentially causing confusing scenarios. The following image illustrates the calculated values of each kernel element:

Gaussian Kernel Values non summed

Ant: Gaussian Kernel 9×9 Weight 19

Ant Gaussian Kernel 9x9 Weight 19

An important requirement to take note of at this point being that the sum total of all the elements contained as part of a kernel/matrix must equate to one. Looking at our calculated results that is not the case. The kernel needs to be modified in order to satisfy the requirement of having a sum total value of 1 when adding together all the elements of the kernel.

At this point the sum total of the kernel equates to 0.046322548968. We can correct the kernel values, ensuring the sum total of all kernel elements equate to 1. The kernel values should be updated by multiplying each element by one divided by the current kernel sum. In other words each item should be multiplied by:

1.0 / 0.046322548968

After updating the kernel by multiplying each element with the values mentioned above, the result as follows:

Calculated Gaussian Kernel Values

We have now successfully calculated a 3×3 Gaussian Blur kernel matrix which implements a weight value of 5.5. Implementing the Gaussian blur has the following effect:

Rose: Gaussian Kernel 3×3 Weight 5.5

Rose Gaussian Kernel 3x3 Weight 5.5

The Original Image

Rose_Amber_Flush_20070601

The calculated Gaussian Kernel can now be implemented when performing image convolution.

Implementing Gaussian Kernel Calculations

In this section of the article we will be exploring how to implement Gaussian Blur kernel calculations in terms of C# code. Defined as part of the sample source code the definition of the static MatrixCalculator class, exposing the static Calculate method. All of the formula calculation tasks discussed in the previous section have been implemented within this method.

As parameter values the method expects a value indicating the kernel size and a value representing the Weight value. The Calculate method returns a two dimensional array of type double. The return value array represents the calculated kernel.

The definition of the MatrixCalculator.Calculate method as follows:

public static double[,] Calculate(int length, double weight) 
{
    double[,] Kernel = new double [length, lenght]; 
    double sumTotal = 0; 

  
    int kernelRadius = lenght / 2; 
    double distance = 0; 

  
    double calculatedEuler = 1.0 /  
    (2.0 * Math.PI * Math.Pow(weight, 2)); 

  
    for (int filterY = -kernelRadius; 
         filterY <= kernelRadius; filterY++) 
    {
        for (int filterX = -kernelRadius; 
            filterX <= kernelRadius; filterX++) 
        {
            distance = ((filterX * filterX) +  
                       (filterY * filterY)) /  
                       (2 * (weight * weight)); 

  
            Kernel[filterY + kernelRadius,  
                   filterX + kernelRadius] =  
                   calculatedEuler * Math.Exp(-distance); 

  
            sumTotal += Kernel[filterY + kernelRadius,  
                               filterX + kernelRadius]; 
        } 
    } 

  
    for (int y = 0; y < lenght; y++) 
    { 
        for (int x = 0; x < lenght; x++) 
        { 
            Kernel[y, x] = Kernel[y, x] *  
                           (1.0 / sumTotal); 
        } 
    } 

  
    return Kernel; 
}

Ladybird: Gaussian Kernel 19×19 Weight 9.5

Gaussian Kernel 19x19 Weight 9.5

The sample source code provides the definition of the ConvolutionFilter extension method, targeting the Bitmap class. This method accepts as a parameter a two dimensional array representing the matrix kernel to implement when performing image convolution. The matrix kernel value passed to this function originates from the calculated Gaussian kernel.

Detailed below is the definition of the ConvolutionFilter extension method:

public static Bitmap ConvolutionFilter(this Bitmap sourceBitmap,  
                                         double[,] filterMatrix,  
                                              double factor = 1,  
                                                   int bias = 0)  
{ 
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, 
                            sourceBitmap.Width, sourceBitmap.Height), 
                                              ImageLockMode.ReadOnly,  
                                        PixelFormat.Format32bppArgb); 

   
    byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height]; 
    byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height]; 

   
    Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length); 
    sourceBitmap.UnlockBits(sourceData); 

   
    double blue = 0.0; 
    double green = 0.0; 
    double red = 0.0; 

   
    int filterWidth = filterMatrix.GetLength(1); 
    int filterHeight = filterMatrix.GetLength(0); 

   
    int filterOffset = (filterWidth-1) / 2; 
    int calcOffset = 0; 

   
    int byteOffset = 0; 

   
    for (int offsetY = filterOffset; offsetY <  
        sourceBitmap.Height - filterOffset; offsetY++) 
    {
        for (int offsetX = filterOffset; offsetX <  
            sourceBitmap.Width - filterOffset; offsetX++) 
        {
            blue = 0; 
            green = 0; 
            red = 0; 

   
            byteOffset = offsetY *  
                         sourceData.Stride +  
                         offsetX * 4; 

   
            for (int filterY = -filterOffset;  
                filterY <= filterOffset; filterY++) 
            { 
                for (int filterX = -filterOffset; 
                    filterX <= filterOffset; filterX++) 
                { 

   
                    calcOffset = byteOffset +  
                                 (filterX * 4) +  
                                 (filterY * sourceData.Stride); 

   
                    blue += (double  )(pixelBuffer[calcOffset]) * 
                            filterMatrix[filterY + filterOffset,  
                                                filterX + filterOffset]; 

   
                    green += (double  )(pixelBuffer[calcOffset + 1]) * 
                             filterMatrix[filterY + filterOffset,  
                                                filterX + filterOffset]; 

   
                    red += (double  )(pixelBuffer[calcOffset + 2]) * 
                           filterMatrix[filterY + filterOffset,  
                                              filterX + filterOffset]; 
                } 
            } 

   
            blue = factor * blue + bias; 
            green = factor * green + bias; 
            red = factor * red + bias; 

   
            blue = (blue > 255 ? 255 : (blue < 0 ? 0 : blue)); 
            green = (green > 255 ? 255 : (green < 0 ? 0 : green)); 
            red = (red > 255 ? 255 : (red < 0 ? 0 : blue)); 

   
            resultBuffer[byteOffset] = (byte)(blue); 
            resultBuffer[byteOffset + 1] = (byte)(green); 
            resultBuffer[byteOffset + 2] = (byte)(red); 
            resultBuffer[byteOffset + 3] = 255; 
        }
    }

   
    Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height); 

   
    BitmapData resultData = resultBitmap.LockBits(new Rectangle (0, 0, 
                             resultBitmap.Width, resultBitmap.Height), 
                                              ImageLockMode.WriteOnly, 
                                         PixelFormat.Format32bppArgb); 

   
    Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length); 
    resultBitmap.UnlockBits(resultData); 

   
    return resultBitmap; 
}

Ant: Gaussian Kernel 7×7 Weight 19

Ant Gaussian Kernel 7x7 Weight 19

Sample Images

This article features a number of sample images. All featured images have been licensed allowing for reproduction.

The sample images featuring an image of a prey mantis is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from Wikipedia.

The sample images featuring an image of an ant has been released into the public domain by its author, Sean.hoyland. This applies worldwide. In some countries this may not be legally possible; if so: Sean.hoyland grants anyone the right to use this work for any purpose, without any conditions, unless such conditions are required by law. The original image can be downloaded from Wikipedia.

The sample images featuring an image of a ladybird (ladybug or lady beetle) is licensed under the Creative Commons Attribution-Share Alike 2.0 Generic license and can be downloaded from Wikipedia.

The sample images featuring an image of a wasp is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from Wikimedia.org.

The Original Image

1280px-Gemeiner_Widderbock_4483

Wasp Gaussian Kernel 3×3 Weight 9.25

Wasp Gaussian Kernel 3x3 Weight 9.25

Wasp Gaussian Kernel 5×5 Weight 9.25

Wasp Gaussian Kernel 5x5 Weight 9.25

Wasp Gaussian Kernel 7×7 Weight 9.25

Wasp Gaussian Kernel 7x7 Weight 9.25

Wasp Gaussian Kernel 9×9 Weight 9.25

Wasp Gaussian Kernel 9x9 Weight 9.25

Wasp Gaussian Kernel 11×11 Weight 9.25

Wasp Gaussian Kernel 11x11 Weight 9.25

Wasp Gaussian Kernel 13×13 Weight 9.25

Wasp Gaussian Kernel 13x13 Weight 9.25

Wasp Gaussian Kernel 15×15 Weight 9.25

Wasp Gaussian Kernel 15x15 Weight 9.25

Wasp Gaussian Kernel 17×17 Weight 9.25

Wasp Gaussian Kernel 17x17 Weight 9.25

Wasp Gaussian Kernel 19×19 Weight 9.25

Wasp Gaussian Kernel 19x19 Weight 9.25

Related Articles and Feedback

Feedback and questions are always encouraged. If you know of an alternative implementation or have ideas on a more efficient implementation please share in the comments section.

Dewald Esterhuizen

I’ve published a number of articles related to imaging and images of which you can find URL links here:

31 Responses to “C# How to: Calculating Gaussian Kernels”


  1. 1 Masab October 10, 2015 at 1:25 PM

    i am doing my project in image processing. i want to smooth vessels of retina of the eye so that i can detect diabetes. can i use your gaussian blur code for this purpose??


  1. 1 C# How to: Image Blur | Software by Default Trackback on June 9, 2013 at 10:20 PM
  2. 2 C# How to: Image Transform Rotate | Software by Default Trackback on June 16, 2013 at 10:40 AM
  3. 3 C# How to: Image Transform Shear | Software by Default Trackback on June 16, 2013 at 5:45 PM
  4. 4 C# How to: Compass Edge Detection | Software by Default Trackback on June 22, 2013 at 9:35 PM
  5. 5 C# How to: Oil Painting and Cartoon Filter | Software by Default Trackback on June 30, 2013 at 10:48 AM
  6. 6 C# How to: Stained Glass Image Filter | Software by Default Trackback on June 30, 2013 at 10:50 AM
  7. 7 C# How to: Image Cartoon Effect | Software by Default Trackback on June 30, 2013 at 1:45 PM
  8. 8 C# How to: Boolean Edge Detection | Software by Default Trackback on June 30, 2013 at 1:56 PM
  9. 9 C# How to: Morphological Edge Detection | Software by Default Trackback on June 30, 2013 at 2:02 PM
  10. 10 C# How to: Image Erosion and Dilation | Software by Default Trackback on June 30, 2013 at 2:11 PM
  11. 11 C# How to: Image Colour Average | Software by Default Trackback on June 30, 2013 at 2:20 PM
  12. 12 C# How to: Image Unsharp Mask | Software by Default Trackback on June 30, 2013 at 2:28 PM
  13. 13 C# How to: Image Median Filter | Software by Default Trackback on June 30, 2013 at 3:16 PM
  14. 14 C# How to: Difference Of Gaussians | Software by Default Trackback on June 30, 2013 at 3:28 PM
  15. 15 C# How to: Image Edge Detection | Software by Default Trackback on June 30, 2013 at 3:33 PM
  16. 16 C# How to: Image Convolution | Software by Default Trackback on June 30, 2013 at 3:55 PM
  17. 17 C# How to: Generate a Web Service from WSDL | Software by Default Trackback on June 30, 2013 at 4:08 PM
  18. 18 C# How to: Decoding/Converting Base64 strings to Bitmap images | Software by Default Trackback on June 30, 2013 at 4:14 PM
  19. 19 C# How to: Bitmap Colour Substitution implementing thresholds | Software by Default Trackback on July 6, 2013 at 4:33 PM
  20. 20 C# How to: Swapping Bitmap ARGB Colour Channels | Software by Default Trackback on July 6, 2013 at 5:02 PM
  21. 21 C# How to: Image filtering by directly manipulating Pixel ARGB values | Software by Default Trackback on July 8, 2013 at 2:58 AM
  22. 22 C# How to: Image ASCII Art | Software by Default Trackback on July 14, 2013 at 7:23 AM
  23. 23 C# How to: Weighted Difference of Gaussians | Software by Default Trackback on July 14, 2013 at 8:12 PM
  24. 24 C# How to: Image Boundary Extraction | Software by Default Trackback on July 21, 2013 at 10:24 AM
  25. 25 C# How to: Image Abstract Colours Filter | Software by Default Trackback on July 28, 2013 at 7:41 PM
  26. 26 C# How to: Fuzzy Blur Filter | Software by Default Trackback on August 9, 2013 at 6:39 AM
  27. 27 C# How to: Image Distortion Blur | Software by Default Trackback on August 9, 2013 at 10:13 PM
  28. 28 C# How to: Standard Deviation Edge Detection | Software by Default Trackback on August 8, 2015 at 8:10 AM
  29. 29 C# How to: Min/Max Edge Detection | Software by Default Trackback on August 9, 2015 at 11:30 AM

Leave a comment




Dewald Esterhuizen

Blog Stats

  • 869,810 hits

Enter your email address to follow and receive notifications of new posts by email.

Join 228 other subscribers

Archives

RSS SoftwareByDefault on MSDN

  • An error has occurred; the feed is probably down. Try again later.