How To Use Geometric Mean Filter On Image – C# Guide

Geometric mean filter is one of mean filters we can use processing images in spatial domain. We use C# programming language to apply it here.


Andraz Krzisnik
How To Use Geometric Mean Filter On Image...

We’re going to use geometric mean filter to process image data in the spatial domain. In general, the effect it has on image is pretty similar to that of arithmetic mean filter.

Mean filters are most useful for processing images which only have noise corruption. Their effect in general is to smooth or blur our image. This is also where geometric mean filter differs arithmetic one. While smoothing, it doesn’t lose as much image detail data.

Filtering data in the spatial domain means we will need to use convolution and a kernel. Firstly, convolution is the process in which we’re going to move our kernel along the entire image. And secondly, kernel is a small window we place on top of our image pixel values.

Geometric mean filter

We usually use filter specific coefficients to multiply with pixel values and sum them together. But in our case, we will multiply all values inside the kernel together. And after that we will raise it to the power of 1/mn, m and n being the dimensions of our kernel.

Let’s take a look at the formula that does all the work.

Geometric mean filter formula
Geometric mean filter formula

Formula above presents us how to calculate a new pixel value, which we will place in the center of our kernel. The process inside the brackets is what we described above. Therefore, g(s, t) represents the location of each pixel value inside the kernel located at coordinates s and t.

We should also mention that our image will reduce in size after processing it, unless we would use zero padding to compensate for those lost pixels.

C# function

I’ve written a function that applies the geometric mean filter. However, I had to make some modifications to the zero padding function. I changed so it pads the image with pixels that have value of 1. Therefore, if we’re technically correct, it becomes function for one padding rather than zero padding.

public static Bitmap GeometricMean(this Bitmap image)
     {
         int w = image.Width;
         int h = image.Height;

         BitmapData image_data = image.LockBits(
             new Rectangle(0, 0, w, h),
             ImageLockMode.ReadOnly,
             PixelFormat.Format24bppRgb);
         int bytes = image_data.Stride * image_data.Height;
         byte[] buffer = new byte[bytes];
         Marshal.Copy(image_data.Scan0, buffer, 0, bytes);
         image.UnlockBits(image_data);

         int r = 1;
         int wres = w - 2 * r;
         int hres = h - 2 * r;

         Bitmap result_image = new Bitmap(wres, hres);
         BitmapData result_data = result_image.LockBits(
             new Rectangle(0, 0, wres, hres),
             ImageLockMode.WriteOnly,
             PixelFormat.Format24bppRgb);
         int res_bytes = result_data.Stride * result_data.Height;
         byte[] result = new byte[res_bytes];

         for (int x = r; x < w - r; x++)
         {
             for (int y = r; y < h - r; y++)
             {
                 int pixel_location = x * 3 + y * image_data.Stride;
                 int res_pixel_loc = (x - r) * 3 + (y - r) * result_data.Stride;
                 double[] mean = new double[3];

                 for (int i = 0; i < mean.Length; i++)
                 {
                     mean[i] = 1;
                 }

                 for (int kx = -r; kx <= r; kx++)
                 {
                     for (int ky = -r; ky <= r; ky++)
                     {
                         int kernel_pixel = pixel_location + kx * 3 + ky * image_data.Stride;

                         for (int c = 0; c < 3; c++)
                         {
                             mean[c] *= buffer[kernel_pixel + c];
                         }
                     }
                 }

                 for (int c = 0; c < 3; c++)
                 {
                     result[res_pixel_loc + c] = (byte)Math.Pow(mean[c], 1 / Math.Pow(2 * r + 1, 2));
                 }
             }
         }

         Marshal.Copy(result, 0, result_data.Scan0, res_bytes);
         result_image.UnlockBits(result_data);
         return result_image;
     }

Conclusion

Geometric mean filter is just one of many mean filters we use for filtering image data in spatial domain. It blurs the image slightly, having a similar effect than arithmetic mean filter, but without losing as much details.

You can also download the project and try it out on your images. I hope this tutorial was helpful and understanding.

Related Articles

Frequency Domain Filtering

How To Use Bandpass Filters – C# Guide

Bandpass filters are the counterpart of bandreject filters. Therefore, they attenuate every frequency outside the ring. In case you’re just tuning in, let me clarify what I...

Posted on by Andraz Krzisnik
Morphological Processes

How To Make Thickening In Image Processing Work In C#

Thickening is a morphological operation in image processing, which adds foreground or white pixels to objects in order to thicken them.

Posted on by Andraz Krzisnik