Reputation: 11
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
noise image
median filter image
Upvotes: 0
Views: 6382
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
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