user8711105
user8711105

Reputation: 11

How to perform median filter for noise image in opencv with python

I am new to OpenCV and Python. I want to perform both Gaussian filter and median filter by first adding noise to the image. I have got successful output for the Gaussian filter but I could not get median filter.Can anyone please explain how to perform median filtering in OpenCV with Python for noise image. Following is my code:

 import numpy as np

 import cv2

 img = cv2.imread('lizard.jpg').astype(np.float32)



 gaussian_blur = np.array([[1,2,1],[2,4,2],[1,2,1]],dtype=np.float32)
 gaussian_blur = gaussian_blur/np.sum(gaussian_blur)


 img_noise = img + np.random.uniform(-20,20,size=np.shape(img))

 cv2.imwrite('gt3_plus_noise.jpg',img_noise)
 median = cv2.medianBlur(img_noise.astype(np.float32),(3),0)
 cv2.imshow('Median Blur',median)
 cv2.waitKey()
 cv2.destroyAllWindows()
 img_blur_g = cv2.filter2D(img_noise.astype(np.float32), -1,gaussian_blur)

 cv2.imwrite('gt3_noise_filtered_gaussian.jpg',img_blur_g)

Output:

noise filtered gaussian

enter image description here

noise image

enter image description here

median filter image

enter image description here

Upvotes: 0

Views: 6382

Answers (2)

alkasm
alkasm

Reputation: 23062

When OpenCV has a float image, it assumes that the range is between 0 and 1. However, your image still has values between 0 and 255 (and maybe a little above and below that). This is fine for manipulation, but in order to view your image you'll either need to normalize it to the range 0 and 1, or, you'll have to convert back to a uint8 image and saturate the values. Currently your image is just overflowing past 1, which is the assumed max value for a float image. The colors are only showing in the darker regions of the image since the values are very small; specifically, less than 1.

Saturating the values for a uint8 image means anything below 0 is fixed at 0 and anything above 255 is fixed at 255. Normal numpy operations do not saturate values, they overflow and roll over (so np.array(-1).astype(np.uint8) ==> 255, meaning any dark values that have some bit subtracted off will turn bright). See here for more about saturation.

This problem isn't too hard to solve, and there are a number of solutions. An explicit way is to simply fix the values greater than 255 at 255 and fix the values less than 0 to 0 and convert to a uint8 image:

>>> img = np.array([[150, 0], [255, 150]], dtype=np.float32)
>>> noise = np.array([[20, -20], [20, -20]], dtype=np.float32)
>>> noisy_img = img+noise
>>> noisy_img
array([[ 170.,  -20.],
       [ 275.,  130.]], dtype=float32)
>>> noisy_img[noisy_img>255] = 255
>>> noisy_img[noisy_img<0] = 0
>>> noisy_img = np.uint8(noisy_img)
>>> noisy_img
array([[170,   0],
       [255, 130]], dtype=uint8)

You can also use cv2.convertScaleAbs() to cast with saturation, which is simpler but less explicit:

>>> img = np.array([[150, 0], [255, 150]], dtype=np.float32)
>>> noise = np.array([[20, -20], [20, -20]], dtype=np.float32)
>>> noisy_img = img+noise
>>> cv2.convertScaleAbs(noisy_img)
array([[170,  20],
       [255, 130]], dtype=uint8)

Upvotes: 1

Jazz
Jazz

Reputation: 946

OpneCV has function medianBlur in Python and C++ to perform median filtering. You can get details from here: http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html#medianblur

To use this function, follow following code snippet:

n=3; #where n*n is the size of filter
output_image = cv2.medianBlur(input_image, n)

Upvotes: 1

Related Questions