Median Filter with Python and OpenCV

mas_bejo picture mas_bejo · Aug 25, 2013 · Viewed 34.4k times · Source

I try make python program for do median filter. I got this article http://www.programming-techniques.com/2013/02/median-filter-using-c-and-opencv-image.html , so I try to translate that code to python code.

this the code in python

from cv2 import * #Import functions from OpenCV
import cv2

if __name__ == '__main__':
    source = cv2.imread("Medianfilterp.png", CV_LOAD_IMAGE_GRAYSCALE)
    final = source[:]
    for y in range(len(source)):
        for x in range(y):
            final[y,x]=source[y,x]

    members=[source[0,0]]*9
    for y in range(1,len(source)-1):
        for x in range(1,y-1):
            members[0] = source[y-1,x-1]
            members[1] = source[y,x-1]
            members[2] = source[y+1,x-1]
            members[3] = source[y-1,x]
            members[4] = source[y,x]
            members[5] = source[y+1,x]
            members[6] = source[y-1,x+1]
            members[7] = source[y,x+1]
            members[8] = source[y+1,x+1]

            members.sort()
            final[y,x]=members[4]

    cv.NamedWindow('Source_Picture', cv.CV_WINDOW_AUTOSIZE)
    cv.NamedWindow('Final_Picture', cv.CV_WINDOW_AUTOSIZE)
    cv2.imshow('Source_Picture', source) #Show the image
    cv2.imshow('Final_Picture', final) #Show the image
    cv2.waitKey()

This is a picture before the median filter: source picture

but I got strange results, the results of the program : final picture

Answer

Aurelius picture Aurelius · Aug 26, 2013

First, I recommend that you not re-invent the wheel. OpenCV already contains a method to perform median filtering:

final = cv2.medianBlur(source, 3)

That said, the problem with your implementation lies in your iteration bounds. Your y range is correct. However, for x in range(1,y-1): only iterates up to the current y value, and not the entire x range of the image. This explains why the filter is only applied to a triangular region in the lower-left of the image. You can use the shape field of the image (which is really just a numpy array) to get the image dimensions, which can then be iterated over:

for y in range(1,source.shape[0]-1):
    for x in range(1,source.shape[1]-1):

This will apply the filter to the entire image:

Median filter result