
Median Filtering¶
Faisal Qureshi
Professor
Faculty of Science
Ontario Tech University
Oshawa ON Canada
http://vclab.science.ontariotechu.ca
Copyright information¶
© Faisal Qureshi
License¶
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
Lesson Plan¶
- Median filtering
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
im = cv.imread('data/bambi.jpg',0).astype(np.uint8)
plt.figure(figsize=(10,10))
plt.imshow(im, cmap='gray');
Lets add some salt and pepper noise
black = 10
white = 250
mask = np.empty(im.shape, np.uint8)
mask = cv.randu(mask, 0, 255)
im[mask < black] = 0
im[mask > white] = 255
plt.figure(figsize=(10,10))
plt.imshow(im, cmap='gray');
Gaussian smoothing to get rid of salt-and-pepper noise¶
The following example supports the assertion that Gaussian smoothing fails to get rid of the salt-and-pepper noise.
half_width = 2
sigma = 1
plt.figure(figsize=(10,10))
plt.imshow(cv.GaussianBlur(im, (2*half_width+1, 2*half_width+1), sigma), cmap='gray');
Median filtering¶
This is a non-linear filtering technique. (What does that mean?) It is widely used in digital image processing and signal processing to get rid of speckle and salt-and-pepper noise while preserving edges.
From Wikipedia article on median filtering
For small to moderate levels of Gaussian noise, the median filter is demonstrably better than Gaussian blur at removing noise whilst preserving edges for a given, fixed window size. However, its performance is not that much better than Gaussian blur for high levels of noise, whereas, for speckle noise and salt-and-pepper noise (impulsive noise), it is particularly effective. Because of this, median filtering is very widely used in digital image processing.
Aside: Speckle is a granular interference that inherently exists in and degrades the quality of the active radar, synthetic aperture radar (SAR), medical ultrasound and optical coherence tomography images. See here) for more information.

(Image from Meskine, Fatiha & Miloud, chikr el-mezouar & Taleb, Nasreddine. (2010). A Rigid Image Registration Based on the Nonsubsampled Contourlet Transform and Genetic Algorithms. Sensors. 10. 8553-8571.)
Median filtering in 1D¶
Replace a value at location $i$ with the median of its neighbourhood values.
(Treat neighbourhood in a similar vein as the filter width in the case of linear filtering.)
x = np.random.rand(10)*255
x = x.astype(np.uint8)
print(f'x = {x}')
x = [247 155 24 1 79 108 94 67 87 66]
Code examples¶
Picking values around $i$
# %load solutions/median-filtering/solution-01.py
half_width = 2
s = half_width
e = len(x)-half_width
for i in range(s,e):
print(f'center = {i}, values={x[i-half_width:i+half_width+1]}')
center = 2, values=[247 155 24 1 79] center = 3, values=[155 24 1 79 108] center = 4, values=[ 24 1 79 108 94] center = 5, values=[ 1 79 108 94 67] center = 6, values=[ 79 108 94 67 87] center = 7, values=[108 94 67 87 66]
Picking median values for $i$ using its neighbourhood
# %load solutions/median-filtering/solution-02.py
result = np.copy(x)
for i in range(s,e):
neighbourhood = x[i-half_width:i+half_width+1]
result[i] = np.median(neighbourhood)
print(f'result = {result}')
result = [247 155 79 79 79 79 87 87 87 66]
Median filtering in 2D¶
half_width = 1
plt.figure(figsize=(20,15))
plt.subplot(121)
plt.title('Gaussian smoothing')
plt.imshow(cv.GaussianBlur(im, (2*half_width+1, 2*half_width+1), sigma), cmap='gray')
plt.subplot(122)
plt.title('Median filtering')
plt.imshow(cv.medianBlur(im, 2*half_width+1), cmap='gray');
