Change gaussian blur level of image continuously by changing slider position

OS (e.g. Win10): Mac OS
PsychoPy version (e.g. 1.84.x): 2021.2.3
**What are you trying to achieve?:

Hello,

I’m new to PsychoPy. I am currently trying to change the gaussian blur level of an image depending on the current slider position.

What have I tried so far?

I created a slider and put an image above it.

With a code component, I am trying to adjust the gaussian blur level of the image depending on the position of the slider:


I can see the slider, the image. The slider works, but I have a problem with programming, I can not change the gaussian blur level of the image.

Dinny

Hello!

Do you want your blur level to be continuous or are there a discrete number of blur settings? Do you want it to run locally or online as well?

Becca

Hi Becca!

Thank you so much for your reply.

I hope the blur level will be continuous from 1-10, and the experiment will be run on the Pavlovia, do you have any ideas?

Dinny

final_exp.psyexp (41.6 KB)
here are my builder file, but i cannot run it on the pavlovia.

:image: Image components don’t have an innate method to set gaussian blur, but you can do it! What you’ll need to do is read in your image as a PIL image, convert it to a numpy array, then apply a gaussian transformation to it. So, at the start of your experiment, you’d do this:

from PIL import Image

# Get image as a PIL
imgPil = Image.open("C:\\Users\\Work\\Downloads\\man.jpg")
# Convert to a numpy array
imgData = np.flip(np.asarray(imgPil), 0)
# Split into red, green and blue channels and convert to rgb1 color space
r = imgData[:, :, 0] / 255
g = imgData[:, :, 1] / 255
b = imgData[:, :, 2] / 255

From there you have two options: You can either do the gaussian blurring each frame according to the slider value, making it fully continuous but computationally intensive, or you can create several different blurred images at the beginning and then access them according to the slider value, making it discrete but fast. So the first option might look like this:
Each Frame

# Blur each color channel
rBlurred = scipy.ndimage.gaussian_filter(r, slider.markerPos)
gBlurred = scipy.ndimage.gaussian_filter(g, slider.markerPos)
bBlurred = scipy.ndimage.gaussian_filter(b, slider.markerPos)
# Apply to image component
img_1.image = np.dstack((rBlurred, gBlurred, bBlurred))

(you’ll need to add import scipy to your Begin Experiment tab in the code component)

However, as this is calculating gaussians each frame, it’s going to be pretty slow unless you have a very good computer or a very small image. Instead, you could do this:
Before Experiment

# Make a dict of pre-blurred images
imgBlurred = {}
for sigma in np.array(range(0, 11)):  # to do it every .1, do np.array(range(0, 101)) / 10
    # Blur each color channel
    rBlurred = scipy.ndimage.gaussian_filter(r, sigma)
    gBlurred = scipy.ndimage.gaussian_filter(g, sigma)
    bBlurred = scipy.ndimage.gaussian_filter(b, sigma)
    # Store blurred image
    imgBlurred[sigma] = np.dstack((rBlurred, gBlurred, bBlurred))

Each Frame

# Set image from dict
obj.image = imgBlurred[slider.markerPos]

So you’re essentially doing the blurring at the beginning then just using the slider value to access pre-blurred images. Be sure to set the granularity of your slider to match the granularity of your blurs dict though, otherwise you’ll get indexing errors!

You’ll end up with something like this:

1 Like

Thank you so much for your reply! But I have some problems:

when I run the first option: TypeError: ‘>’ not supported between instances of ‘NoneType’ and ‘float’


the second option: File “/Users/dinny/Desktop/code_lastrun.py”, line 170, in
obj.image = imgBlurred[slider.markerPos]
KeyError: None

Could you tell me why these errors are happening? By the way, if these code components can be run on Pavlovia?

Thanks a lot in advance,

Dinny


here are my slider properties

You need to have a start value specified, as you need to know what blur to start at, without a start value it will return None

1 Like

Thank you again for your reply.

I have set the value like this:

it always runs error:

here is my code component:


Hi There,

There are a couple of things you will want to bare in mind for taking this online @TParsons suggestion will work great locally, but PIL is a specific python library, so that won’t work online also sliders don’t yet have the parameter startVal just yet online. That said, there are some work arounds to build on todds suggestion (but I don’t think this is quite perfect yet).

Here is a demo working online, though as you can see at the moment it is a bit laggy, so needs some further debugging: blurSlider [PsychoPy]

  1. You want to use the code Todd shared to generate images locally using a script like the one in the “scripts” folder here Rebecca Hirst / blur_slider_demo · GitLab.
  2. In your experiment, locally the most efficient method could be to use the slider rating to pull the corresponding image, but online that won’t quite work yet, so we draw all the images and set the image opacity of each according to the rating (see the code components “fetchRating” and “drawImages” in the .psyexp file of the shared gitlab repository).

Limitations:

  • Because this could involve drawing a large number of images at once, it means this method would really only work with discrete blur values, it could be very laggy with 100+ images.
  • The more images you have the more time the experiment will take to load at the start of your experiment, so, if you have 100 images, each of which needs 10 blur values, you suddely have 1000 images that need to load at the start of the experiment (how many images do you have that need blurring?)

Alternative work arounds I was thinking involved using something like the gaussian blur filter applied by mouseview Running MouseView.js experiment using PsychoJS-PsychoPy | MouseView.js though that would need a fair bit of extra work to think about, it would likely be a more dynamic approach to applying blur online.

Sorry this isn’t a full solution just yet - I just wanted to flag the extra considerations for taking this online since you mentioned that would be the goal.

Thanks,
Becca

1 Like

Thank you for you help very much and I will try next as your suggestions.

Thanks again!

Oops! obj is what I’d called my image when I was testing this - it should be the name of your image stimulus