Implement a Median Filter with OpenCV

Published by: 0

Median filter is a low pass bandwidth filter which uses a kernel function over the image matrix to manipulate it. The kernel may be defined as 3×3, 5×5 or based on the user preference. Then it uses the discrete convolution to calculate the result matrix.

What is discrete convolution?

Discrete convolution is a method that multiplies 2 arrays (here one is the image matrix and other one is the kernel) and calculate an output matrix. The output matrix will have the same dimensionality as the input matrices and but the size may vary.

conv

When we use a square kernel over the image, border pixels may get clipped. Therefore, the size of the resulting image will be dropped.

Median Filter

MedianAlgorithmFirst we get the pixel values of the image to the kernel. Then they will be sorted to get the median value to the middle pixel of the kernel. Then the middle value will be written back to the complying pixel of the image and kernel will be shifted by one pixel to manipulate the next pixel of the image. This is the process where you lose borderline pixels of the source image.

 

OpenCV Implementation

The method I have used here is a bit straightforward than the convolution theory. Instead of worrying about 3×3 2D array for the kernel, I have created a 1D array of size 9 and then stored the pixel values in it. Then it has sorted and written back the middle value to the image’s considering pixel.

[cpp]#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <iostream>

using namespace cv;
using namespace std;

int main() {

/**Load the image in grayscale*/
Mat noisyimg = imread("noisy_Farm.jpg", CV_LOAD_IMAGE_GRAYSCALE);
/**Create a kernel of size 9*/
int kernal[9];

Mat filtered(noisyimg.rows, noisyimg.cols, CV_8UC1);
/**For each pixel in noisy image starting from 1 to N-1 on each direction,
get the pixel values of 3×3 area (i-1->i+1,j-1->j+1) and store them in the kernel array.*/
for (int i = 1; i < noisyimg.rows – 1; i++) {
for (int j = 1; j < noisyimg.cols – 1; j++) {
int kernalIndex = 0;
for (int a = -1; a <= 1; a++) {
for (int b = -1; b <= 1; b++) {
kernal[kernalIndex] = noisyimg.at<uchar>(i + a, j + b);
kernalIndex++;
}
}
/**Sort the kernel array*/
sort(kernal, kernal + 9);
filtered.at<uchar>(i, j) = kernal[4];
/**Get the value of the middle index and apply it back to the image*/
}
}
imshow("original", noisyimg);
imshow("filtered", filtered);
waitKey(0);
}[/cpp]

 

Results

2 Capture1

 

The median filter has that attribute, it does not blur the image like in gaussian or Mean filtering methods. Therefore, the pixel and edge locations are preserved.