Filter: Median Blur

Source: modified from [PITA00:141-143]; [LIND91:378-382]

As mentioned in the previous filter, one use of a blurring filter is to remove noise, or errors, in an image. To return to the previous example of taking one’s glasses off to see a blurred image…imagine that there are crumbs of food on your kitchen table. If you take your glasses off, do you still see the crumbs? No! The blur has ‘filtered them out’ because they were small in comparison to what was around them. In the same way, the blur will remove error in an image (e.g. dust or scratches on a scanned photograph or negative), but the detail once in the image will be lost in the process. It would be nice if the details remained after the blur but the errors were gone, which is what the median blur attempts to do. I implemented this filter just to see how well it matched up to a regular blur in this respect.

The median blur is similar in implementation to the regular blur. However, instead of simply averaging the surrounding pixels in order to get a new value, this filter uses the fact that the pixel values of an error in data are probably very different from the surrounding ‘good’ pixel values. Therefore, if we take each pixel in the square area around our current center pixel, and somehow sort the values, the error should be on one end of the sorted list. For small errors, the likelihood that the middle pixel value in this list is an error pixel value is very low. If we choose the middle, or median, value in this list, we probably will not be choosing an error value, so we assign the median pixel value to the center pixel. If we do this for every pixel in the image, theoretically, the errors will be eliminated and resulting image should be close to the original. 

How do we sort color though? If I have 25 pixels of RGB components how do I sort them? By intensity! Recall the discussion in the grayscale filter that argued that intensity is the common basis for image analysis. The algorithm therefore is simple and the only real implementation problem is in finding a fast way sort the pixels’ intensities, keeping in mind that assignment of the filtered pixel is not done by intensity alone, but we also need the RGB values of that intensity. 

My MedianPixel() function takes as arguments an array of intensities and an a corresponding array of RGB pixels. The function creates a temporary array of integers that represent indices to the arrays of intensities and pixels. To save computation time, only the indices are sorted.

Figure 2: Median Blur Filter, [LIND91:381]

The Quicksort sorting algorithm described in [PARS95:98-103] was used. MedianPixel() returns the median RGB pixel.

Here is the algorithm for the filter. The reader interested in the details of the MedianPixel() implementation is referred to the code in filters.cpp from the downloadable project.

   for every pixel in the image do
   {
      numpixels = 0;
      for every pixel in radius r surrounding the center pixel do
      {
         intensity = currentpixel.intensity;
         intbuffer[nextlocation] = intensity;
         colorbuffer[nextlocation] = currentpixel;
         numpixels++;
      }
      filterpixel = MedianPixel(intbuffer, colorbuffer, numpixels);
   }

In practice, the median blur filter is better than the general blur in terms of removing errors and preserving edges. As expected, it is extremely good when errors are small and differ greatly in value from the surrounding pixels.


Original image with noise added (not a filter)


Median blur (radius 2) on original with noise
(Compare edge quality to that of the standard blurred image.)


Return to the list of filters
 


© 2001 Jason Waltman