Reputation: 1536
My assignment is to apply a median filter of size 50x50 pixels to an image. I know how to apply the filter, but how can I specify the size of the filter when it is even? My code so far is below.
import matplotlib.pyplot as plt
from astropy.io import fits
import scipy.signal as sg
# Open data files
hdulist = fits.open('xbulge-w1.fits')
w1data = hdulist[0].data
hdulist2 = fits.open('xbulge-w2.fits')
w2data = hdulist2[0].data
# Apply median filter to each image
w1_med = sg.medfilt(w1data)
w2_med = sg.medfilt(w2data)
# Set maximum sampled galactic lat (b) and long (l)
l_max = 15
b_max = 15
# Plot median filtered images, rescaled to galactic coordinates
plt.subplot2grid((2,1), (0,0))
plt.imshow(w1_med, origin='lower',
extent=[l_max, -l_max, -b_max, b_max],
cmap = 'gray')
plt.title('W1 median filter')
plt.subplot2grid((2, 1), (1,0))
plt.imshow(w2_med, origin='lower',
extent=[l_max, -l_max, -b_max, b_max],
cmap = 'gray')
plt.title('W2 median filter')
plt.tight_layout()
plt.show()
Upvotes: 0
Views: 5732
Reputation: 3332
[EDIT] Sorry for the misunderstanding in my previous answer. Median filtering is a noise suppression technique. The result depends on the kernel dimension, which is typically a "small" odd number e.g. 3,5,7. The kernel size will give the dimension on which median gets applied. For example, with a square kernel of size 3, the algorithm carries out the operation depicted in the figure below.
So I would suggest to just try a few different kernels (e.g. 3, 5) independently on your figure size (well, almost). Then pick the one that yields the best result. This will depend on your figures.
sg.medfilt(w1data,kernel_size=5)
In addition I see this definition for medfilt:
Signature: sg.medfilt(volume, kernel_size=None) Docstring: Perform a median filter on an N-dimensional array. Apply a median filter to the input array using a local window-size given by kernel_size. The array will automatically be zero-padded. Parameters ---------- volume : array_like An N-dimensional input array. kernel_size : array_like, optional A scalar or an N-length list giving the size of the median filter window in each dimension. Elements of `kernel_size` should be odd. If `kernel_size` is a scalar, then this scalar is used as the size in each dimension. Default size is 3 for each dimension. ....
Notice the "The array will automatically be zero-padded". This is needed to fix your even sized images
Upvotes: 1
Reputation: 8378
The key in your question is the even-sizedness of the kernel. scipy.signal.medfilt
constrains you to use odd-sized kernels. Do a search on the Web and you will find plenty of information as to why kernels are usually odd-sized. The main reason, I believe, is centering.
For example, if you convolve an image containing a Gaussian with an even-sized Gaussian kernel - you will end-up with an image with a Gaussian with a shifted (by 1/2 pixels) center compared to the original, not convolved, image.
With regard to the median filter specifically, there is an additional reason why one may consider odd-sized kernels: having an odd number of pixels produces a unique median while having an even number of pixels would require deciding, e.g., on which pixel to use as the result: pixel[int(size/2)]
, pixel[int(size/2)+1]
, or the average of the two.
You cannot use scipy.signal.medfilt
for even-sezed kernels. However, you can always write a loop to go through all pixels of the input image and extract an even-sized window "around" each pixel, and then compute the median of the pixels in that window. I quote "around" because it is not clear (=unique) how to center that window on a pixel: it will be up to you to make a decision.
Upvotes: 0
Reputation: 8954
Based on the docs I think all you need to change is
# Apply median filter to each image
w1_med = sg.medfilt(w1data)
w2_med = sg.medfilt(w2data)
to
# Apply median filter to each image
w1_med = sg.medfilt(w1data, kernel_size=50)
w2_med = sg.medfilt(w2data, kernel_size=50)
...does that work for you?
Upvotes: 0