Display a colored image with pixels stored as numpy array

Hello,

I would like to display a colored disc, with every pixel’s RGB values specified in a numpy array. I can generate the image as a 3D numpy array (n rows of pixel x n columns of pixels x 3 colors RGB), but I can’t find a way to display it.

The closest thread I could find is the following, but it’s not exactly what I’d like to have in my stimulus.

May I ask if ImageStim or GratingStim can do this? If so , how do I pass the pixel array to the object?

Thanks,
Alan

You can pass the array as the image argument to ImageStim or the tex argument to GratingStim.

Thanks! It works now with ImageStim. I was stuck before as I didn’t know the size argument is necessary for ImageStim.

Hi,

I’m still stuck on trying to display a 3D numpy array as an image.

Here’s a sample of what I’m trying:

win = visual.Window(
    size=[2560, 1440], fullscr=True, screen=0, 
    winType='pyglet', allowGUI=False, allowStencil=False,
    monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
    blendMode='avg', useFBO=True, 
    units='height')

stim_img=np.load('image_to_view.npy')
type(stim_img)
#This outputs: <class 'numpy.ndarray'> 
np.shape(stim_img)
#This outputs: (504, 334, 3)

stim = visual.ImageStim(win,image=stim_img)

This stim variable later gets input into the routine and flipped to the window etc. However, all that appears is a mostly red static image.

The values in the array are the rbg 255 pixel values. So I tried replacing stim = visual.ImageStim(win,image=stim_img) with stim = visual.ImageStim(win,image=stim_img,colorSpace='rgb255'). This latter version produced a mostly blue static image.

Any help would be greatly appreciated!

EDIT: Updating to include PsychoPy version: 2020.2.4

Could you upload the npy file (and a screenshot of what you’re expecting the image to look like)? I expect it’s a scaling issue but hard to know without seeing the array

Thanks so much! Discourse doesn’t support uploading .npy files unfortunately. Instead, here is a very small portion of the image so that you can create the array on your end:


image_to_view=np.array([[[ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 31, 125, 149],
        [ 30, 123, 149],
        [ 29, 123, 148],
        [ 16, 118, 150],
        [ 35, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 25, 121, 147],
        [  7, 110, 138],
        [  8, 111, 139],
        [ 28, 124, 148],
        [ 16, 118, 150],
        [ 35, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 22, 118, 145],
        [  8, 111, 140],
        [ 84, 155, 175],
        [ 74, 149, 170],
        [  8, 110, 138],
        [ 15, 116, 148],
        [ 36, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 30, 123, 149],
        [  1, 106, 136],
        [148, 191, 205],
        [255, 255, 255],
        [255, 255, 255],
        [115, 173, 187],
        [  0, 104, 138],
        [ 39, 128, 148],
        [255, 219,  99]],

       [[ 27, 122, 148],
        [ 29, 124, 148],
        [  5, 108, 137],
        [239, 245, 247],
        [255, 255, 255],
        [255, 255, 255],
        [207, 226, 230],
        [  0,  98, 135],
        [ 41, 129, 148],
        [255, 219,  99]],

       [[ 27, 122, 148],
        [ 30, 125, 149],
        [  2, 108, 136],
        [116, 174, 190],
        [255, 255, 255],
        [255, 255, 255],
        [ 88, 157, 175],
        [  0, 106, 141],
        [ 39, 127, 148],
        [255, 219,  99]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 24, 120, 146],
        [  4, 108, 137],
        [ 47, 133, 158],
        [ 40, 129, 153],
        [  6, 110, 137],
        [ 16, 117, 150],
        [ 36, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 29, 123, 149],
        [ 16, 115, 143],
        [ 18, 117, 143],
        [ 31, 124, 149],
        [ 16, 118, 150],
        [ 35, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 30, 123, 149],
        [ 28, 123, 149],
        [ 29, 123, 148],
        [ 16, 118, 150],
        [ 35, 125, 145],
        [255, 219, 100]],

       [[ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 27, 122, 148],
        [ 29, 123, 148],
        [ 16, 118, 150],
        [ 35, 125, 145],
        [255, 219, 100]]])

Here is the screenshot of what that small part should look like:

Thanks again!

Hi again! I updated psychopy to the most recent release and am still running into issues. You stated that you suspect it is a scaling issue. Can you clarify what you mean by that? Thanks so much!

I’ve been experiencing the same issue as the OP, and wanted to highlight that the solution indeed seems to be that you must pass a size to ImageStim when using a numpy array as input. You don’t need to pass one if using an image path (e.g. to a .png). This is confusing.

I wonder if there could be a recipie / how-to added for the recommended method to display images (from either image files or from numpy array)?

I started a recipe here