# How To Make Adaptive Filters For Local Noise In C#

Adaptive local noise reduction filters are useful for processing images that have too much noise to deal with with other simpler filters.

Andraz Krzisnik
How To Make Adaptive Filters For Local Noise...

I’m going to talk about adaptive filters in this post. More specifically, I’m going to talk about adaptive local noise reduction filter. Basically, it’s a spatial filter and we mainly use it to filter out noise from the images.

Spatial filter or kernel is like a small window on our image which encompasses a local set of intensity values. After we get this set, we use it to calculate an output intensity value. In order to render the output image, we need to calculate for each pixel separately.

There are a few reasons why are adaptive filters better than other filters. Firstly, other filters disregard that image characteristics may vary from one point to the other across it, these do not. And secondly, their performance is superior.

However, there are also a few downsides. For one, adaptive filters are more complicated. Therefore, they need more processing power to compute each output intensity value. And for another point, they’re still good for images which have only noise degradation.

## Adaptive local noise reduction filters

These have the simplest statistical measures for mean and variance. When we calculate new ouput values, the mean gives us the average intensity inside the filter. While variance gives us contrast information from these intensities.

Let’s take a look at the following formula and break it down.

So, first things first, g(x, y) represents the intensity value, which has a position in the center of the filter. Then, before the brackets, we have ratio between noise variance on top of the fraction and intensity variance below.

We calculate intensity variance from intensities inside the filter and we have to do it for each output pixel. And lastly, mL is the mean of intensities inside the filter region.

Despite how complex formula is, we can compute almost all values from filter set. The only unknown that remains is noise variance. We need to estimate it to be as close to variance of the noise with which our image is corrupted.

Another pointer for using this filter is to limit maximum noise variance to be less or equal to intensity variance. This way we can prevent some unwanted things happening, like negative intensity values and such.

## C# implementation

``````public static Bitmap Filter(this Bitmap image, double noise_variance)
{

int w = image.Width;
int h = image.Height;

BitmapData image_data = image.LockBits(
new Rectangle(0, 0, w, h),
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 = 3;

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];
int[][] neighborhood = new int[3][];

for (int c = 0; c < 3; c++)
{
neighborhood[c] = new int[(int)Math.Pow(2 * r + 1, 2)];
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] = neighborhood[c].Sum() / Math.Pow(2 * r + 1, 2);
double variance = 0d;
for (int i = 0; i < neighborhood[c].Length; i++)
{
variance += Math.Pow(neighborhood[c][i] - mean[c], 2);
}
variance /= Math.Pow(2 * r + 1, 2);

if (noise_variance > variance)
{
noise_variance = variance;
}

result[res_pixel_loc + c] = (byte)(buffer[pixel_location + c] - (noise_variance / variance) * (buffer[pixel_location + c] - mean[c]));
}
}
}

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

return result_image;
}``````

## Conclusion

We can use adaptive filters when we have significant noise corruption in our images. They give us a little more umpf than the rest of spatial filters.

### Related Articles

#### C# Tutorial: Contrast Stretching with Normalization

This post is a short revision of Contrast Stretch post we already worked on in the past. Where we talked about histogram equalization, which is a little more complex method than...

Posted on by Andraz Krzisnik

#### How To Make Image Erosion Work With C#

Image erosion is one of the fundamental morphological operations and this tutorial explains how it works and demonstrates it in C#.

Posted on by Andraz Krzisnik