How To Make Midpoint Filter For Images – C# Guide

Midpoint filter is a order-statistic filter and we use it to process image data in spatial domain. This guide shows how to make it with C#.


Andraz Krzisnik
How To Make Midpoint Filter For Images...

We use midpoint filter for processing image data in spatial domain. Therefore, we need to compute output pixel intensity values using local neighborhoods of pixel values from input image.

Each spatial filter works by taking a set of pixel values and outputing a single pixel value. Furthemore, it acts like a small window we place on top of an image. In order to filter the entire image, we have to move this window across the entire input image.

However, processing images with spatial filters will produce image with slightly smaller dimensions. So, if we want to counteract this, we should use zero padding on the input image before we filter it. This way we will compensate the loss of pixels and end up with the same sized image as input one.

Midpoint filter

This filter is one of the order-statistic filters, which are all spatial filters. Furthermore, the output intensity values they produce aren’t computed, but chosen from ordered existing image data.

We already talked about median, max and min filters, which belong among order-statistic filters. Midpoint filter is kind of a mixture of max and min filter and arithmetic mean filter, which we also talked about in another post.

What it does, it basically takes minimum and maximum values from the local set, encompassed by the filter, and divides it by 2. To put this in more mathematical terms, let’s take a look at the following formula.

midpoint filter formula
Midpoint filter formula

The g(s, t) in the formula represents intensity value, which has a position on coordinates s and t. These coordinates are relative to the filter. In other words, position of the filter doesn’t affect the intensity value of each output pixel, only values it encompasses do.

C# code

Function that does all the work consists of a few nested for loops. As you will see in the code, other two for loops are there for moving the filter across the image. While inner three are there for processing image data inside the filter.

Each spatial filter outputs intensity values in the center position of the filter and we apply it three times, once for each color channel.

public static Bitmap Filter(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[] median = new double[3];
                 byte[][] neighborhood = new byte[3][];

                 for (int c = 0; c < 3; c++)
                 {
                     neighborhood[c] = new byte[(int)Math.Pow(2 * r + 1, 2)];
                     int added = 0;
                     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;
                             neighborhood[c][added] = buffer[kernel_pixel + c];
                             added++;
                         }
                     }
                 }

                 for (int c = 0; c < 3; c++)
                 {
                     result[res_pixel_loc + c] = (byte)((neighborhood[c].Min() + neighborhood[c].Max()) / 2);
                 }
             }
         }

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

Conclusion

Midpoint filter is useful for randomly distributed noise like Gaussian or uniform noise. However it will slightly blur the image while doing its thing.

I hope this tutorial was helpful. You can also download the entire project and try it out on your own image.

Related Articles

C# Tutorial

Intensity Level Slicing With C# – Explore Image Processing

In this tutorial we will be talking about intensity level slicing in image processing. What is Intensity Level Slicing It’s a process that highlights pixels in an arbitrary...

Posted on by Andraz Krzisnik
Morphological Processes

How To Make Thinning In Image Processing Work With C#

Thinning is a morphological operation in image processing, which eats away at the foregorund pixels and leaves only lines shaping objects.

Posted on by Andraz Krzisnik