Filters, filters, filters… Tired of them yet? Me too. After this we’ll leave them alone for a while. I promise. Until then, we have work to do.

What is a median filter? If you understand the average filter (or mean filter) then the median filter should give you no troubles at all – assuming you know what the median is. We’ll start there.

**What is the Median?**

The median is the middle number of a sample. To find it, you sort your list and pick the middle item. Yes, it really is that simple.

Here is a random set of 9 numbers:

Sort them:

Pick the middle value:

Like I said, it’s simple.

**Why use median instead of mean?**

The median is particularly effective against certain types of noise – specifically “salt and pepper” noise (black and white specks). Let’s assume this is the neighborhood we’re dealing with:

Performing the mean gives:

While the median returns:

If we expect that the 0 values are noise then the median is probably a much closer estimate.

**Code**

private WriteableBitmap MedianFilter(WriteableBitmap grayscale, int radius)

{

// we are still going to create a new image

// because we don’t want to modify the

// old image as we are processing it

WriteableBitmap filtered =

new WriteableBitmap(

grayscale.PixelWidth,

grayscale.PixelHeight);

// boiler plate code for our

// histogram stuff

int[] histogram = new int[256];

int maxIntensity = 0;

// the math is still easier if we create two loops

// instead of one

for (int y = 0; y < grayscale.PixelHeight; y++)

{

for (int x = 0; x < grayscale.PixelWidth; x++)

{

//here’s the pixel we’re centered on

int pixel = x + y * grayscale.PixelWidth;

byte intensity = (byte)grayscale.Pixels[pixel];

// if we are on an edge we are going to leave it

// as the original intensity. you will see the

// edges increasingly unsmoothed as the window

// size increases. here we are using the radius

// to determine our bounds

if (y <= radius – 1 ||

x <= radius – 1 ||

y >= grayscale.PixelHeight – radius ||

x >= grayscale.PixelWidth – radius)

{

histogram[intensity]++;

if (histogram[intensity] > maxIntensity)

{

maxIntensity = histogram[intensity];

}

continue;

}

** /////////////////////////////////////////////////////////**

** // IMPORTANT PART ///////////////////////////////////////**

** /////////////////////////////////////////////////////////**

** // this list is the key**

** // it contains all of the neighboring pixels**

** List<byte> localIntensities = new List<byte>();**

** for (int yoffset = -radius; yoffset <= radius; yoffset++)**

** {**

** for (int xoffset = -radius;**

** xoffset <= radius;**

** xoffset++)**

** {**

** localIntensities.Add((**

** (byte)grayscale.Pixels[(x + xoffset) **

** + (y + yoffset) * grayscale.PixelWidth]));**

** }**

** }**

** //sort the intensities**

** localIntensities.Sort();**

** //pick the middle value**

** int medianLocalIntensity = **

** localIntensities[(int)(localIntensities.Count/2.0+.5)];**

** /////////////////////////////////////////////////////////**

** // END IMPORTANT PART ///////////////////////////////////**

** /////////////////////////////////////////////////////////**

// and now just set the color

filtered.Pixels[pixel] = (255 << 24)

| (byte)medianLocalIntensity << 16

| (byte)medianLocalIntensity << 8

| (byte)medianLocalIntensity;

histogram[(byte)medianLocalIntensity]++;

if (histogram[(byte)medianLocalIntensity] > maxIntensity)

{

maxIntensity = histogram[(byte)medianLocalIntensity];

}

}

}

PlotHistogram(histogram, maxIntensity);

return filtered;

}

**Results**

Taking a simple gray image I added salt and pepper noise to the image then performed a median filter and an average filter to it. The results are stunning.

** flat gray image** **10% salt and pepper noise**

** after median filtering after mean filtering**

There are a few specks after applying the median filter, but the noise is removed pretty well. The average filter performed dismally to say the list.

**Summary**

If you expect salt and pepper noise then the median filter is great tool to have in your toolbox. If you want you can explore max, min, and mode filters. I don’t think we’ll cover them here unless we have a specific application for it.

**Download Code**

(code includes salt and pepper noise generation)

Up Next: Binary Images

Feel free to leave a comment or follow @azzlsoft on Twitter if you have any questions.