How To Make Max And Min Filter In Image Processing
Max and min filter is one of the order-statistic filter we can use to process image data in spatial domain. This tutorial shows it with C#.
Filter by Category
We can use max and min filter to process image data in spatial domain. Furthermore, they belong among order-statistic filters along with median filter. As for spatial domain filtering, our filter is basically a small window we place on top of our image.
When we place our filter somewhere on the image, it’s going to encompass pixel intesity values, which we’ll use to store them into a set. After that we’ll pick out the value according to which filter we’ll use.
To form the entire output image, we’ll need to move the filter one pixel at the time. This way, we’ll be able to form the whole image pixel by pixel. However, filtering in spatial domain will produce images with slightly smaller dimensions.
We can compensate for the lost pixels with zero padding and expand our image for the same amount as we’re going to lose.
I’ve made a post about median filter already, but I’d like to mention it here again. When we use median filter we pick the middle intensity in the set. However when we’re using max and min filter, we pick the highest or the lowest intensity value in the set.
If we use max filter, we’ll bring out the brightest points in the image. And if we’re using min filter, we’ll find the darkest points in the image.
Following formulas do what we described above.
The g(s, t) in the formulas represents pixel intensity values encompassed by filter, where s and t are coordinates of each pixel inside.
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++)
{
//if you want to change it to max filter, change .Min() to .Max()
result[res_pixel_loc + c] = (byte)(neighborhood[c].Min());
}
}
}
Marshal.Copy(result, 0, result_data.Scan0, res_bytes);
result_image.UnlockBits(result_data);
return result_image;
}
Max and min filters are basically just usable options among order-statistic filters. But that doesn’t mean it makes them really useful in practice.
I hope this tutorial was helpful. You can also download the project with which you can see the demonstration of these filters.