lilla
lilla

Reputation: 141

How can I obtain a gaussian kernel array to filter my image

For an experiment, I need a gaussian filter over an entire window such as the middle part is shown. Since I use PsychoPy, basically, I need an N x M array (N and M are the size in pixels of the window) of ones in the middle (where the underlying stimulus is visible going to -1 at the edges. I can then use this array as a mask within GratingStim. So far, I have been trying ndimage.filters.gaussian_filter(filter_input, sigma = 7)

But I am having some trouble with this funcion. If filter_input is a NxM matrix with ones or zeros, the ndimage function leaves them unchanged. If filter_input is a matrix with random numbers, it changes them all right. But I still don't get the result I am hoping for. I am aware of the fact that PsychoPy masks allow only values between -1 and 1 but as it s now in the code below, I should not be able to see anything since the mask is -1.

So, to be more specific: Why does ndimage.filters.gaussian_filter(filter_input, sigma = 7) behave like it does? How could I get it to assign to every point in the NxM matrix a value such that the assigned values have a gaussian 2d distribution? Later I could just chop off the values higher than 1 and lower than -1.

I am sorry if my question is trivial, I have been doing some programing in PsychoPy but I am new to numpy and scipy...

Thanks for your help!

Here is some example code:

# -*- coding: utf-8 -*-

from psychopy import visual, event
import numpy as np
from scipy import ndimage
win = visual.Window([500,500])

#draw rectangle
perc25 = visual.Rect(win, width = 0.6,height=0.4, lineColor='red',fillColor =    'red', pos=(0.0, 0.1))  #notloesu
perc25.draw()

#add circle with fuzzy edges
perc75 = visual.GratingStim(win, sf=0, size=0.5, color='green',pos=(0.0, -0.1), mask = 'raisedCos', maskParams={'fringeWidth':0.6}) 
perc75.draw()

#create the  matrix that should result in a gaussian filter laied centrally over the entire window
#desired Result: some red in the upper part of the visible circle in the middle, the rest beeing green
filter_input = (np.ones([500,500]))*(-1.)
gaussian = ndimage.filters.gaussian_filter(filter_input, sigma = 0.2)
print(filter_input == gaussian)

#i know it's ugly, I just can't think of another way to apply the filter to the entire image and I haven't found anything in the internet
unnecesary_stim_to_get_the_mask_over_the_window  = visual.GratingStim(win, sf=0, size=0.0000001, color='green',pos=(0, 0), mask = gaussian) 
unnecesary_stim_to_get_the_mask_over_the_window.draw()

win.flip()
event.waitKeys()

Upvotes: 1

Views: 5102

Answers (1)

Warren Weckesser
Warren Weckesser

Reputation: 114811

Your input to gaussian_filter is an array filled with -1. Whenever you filter, you have to consider how the edges are handled. The handling of the edges by gaussian_filter is determined by the mode argument. The default mode is 'reflect', which means the data "outside" your array (from the point of view of the filter) is a reflected copy of the data inside the array. So the only value that gaussian_filter sees is the constant -1. A Gaussian filter is a low-pass filter, so a constant value is passed unchanged. That is why your array gaussian contains the same values as filter_input.

To create an actual Gaussian surface, pass an array that is all zero except for a single 1 in the center. For example,

In [92]: x = np.zeros((101, 101))

In [93]: x[50, 50] = 1

In [94]: y = ndi.filters.gaussian_filter(x, sigma=16)

In [95]: imshow(y, interpolation='none', cmap=cm.gray)
Out[95]: <matplotlib.image.AxesImage at 0x1127e4390>

plot

(ndi is scipy.ndimage, and imshow is matplotlib.pyplot.imshow.)

Upvotes: 5

Related Questions