psychopy.org | Reference | Downloads | Github

Save large number of frames to tiff image stack

Hello,

I wanted to ask whether it is possible to compress/downsize frames saved by mywin.getMovieFrame(), so that I can save large number of frames (2000) into image stack eg tiff. I am getting memory error while trying to do so.

Thanks,

If you want to compress an image file, .TIFF probably isn’t the way to go :wink:

But regardless, you might be confusing disk space with memory here. The images when held in memory will be uncompressed, at 3-4 bytes per pixel. If you are running out of memory, that will be the issue, not what size those images end up on disk after the process is complete.

Perhaps what you should do here is call .saveMovieFrames() periodically during a non time-critical period in your experiment. Each time you that, it will clear all of the image data being stored in memory so you can start from 0 again.

Hello,

Thanks for a quick reply. I do not want to compress the image (sorry for confusion). I just want to save many frames but getting memory error. I think I just can create smaller window to save more frames.

Then like I said, you should try to call win..saveMovieFrames() periodically so that not so many frames build up in memory.

Don’t make the window smaller: performance is much better when the window is fullscreen.

Hello,

Yes, it works if I save images periodically.

Thanks,

Hello,

I’m absolutely new to psychopy, and wanted to save multiple frames of a dynamic grating I’m generating with the code below. However, all I’ve managed to get is to save one frame either in .png or in .mp4. The thing is that I understand that I have to save images periodically, but don’t know what line of code I have to add to do it. Thank you so much in advance for your help.

Vanessa

Here is my code :

import numpy as np

import psychopy.visual
import psychopy.event
import psychopy.core
from moviepy.editor import ImageSequenceClip
from psychopy import core, visual, event

win = visual.Window(
    size=(1280, 800), fullscr=True, screen=0,
    allowGUI=False, allowStencil=False,
    monitor='testMonitor', color=[-1,-1,-1], colorSpace='rgb',
    blendMode='avg', useFBO=True)


grating = psychopy.visual.GratingStim(
    win=win,
    size=[110, 110],
    mask="circle",
    units="pix",
    sf=3.0 / 110.0
)

grating.mask = "gauss"

clock = psychopy.core.Clock()

while clock.getTime() < 5.0:

    grating.phase = np.mod(clock.getTime() / 1, 1)

    grating.draw()

    win.flip()
    
for n, frame in enumerate(win.movieFrames):
    win.movieFrames[n] = np.array(frame)
clip = ImageSequenceClip(win.movieFrames, fps=60)
clip.write_videofile('movieName.mp4')
    
win.getMovieFrame(buffer='front') 
win.saveMovieFrames(fileName='myMovie.mp4')
    
thisExp.abort()  
win.close()
core.quit ()

Thank you. I’ve edited my post to include the backticks.

Put:

win.getMovieFrame()

immediately after your win.flip() line. i.e. you are wanting to store each newly-drawn lot of window content.

That stored set of frames can then later be saved with a single command:

win.saveMovieFrames('your_file_name.png')

That will automatically generate a set of numbered .png files, one file per frame. Alternatively it can output a movie file but the success of this can be variable depending on platform. Details in the API here: http://www.psychopy.org/api/visual/window.html

Thank you for your response.

I did what you suggested. However, there is only the first frame (one .png) that is saved. I’m not able to generate multiple images.

Thank you so much for the help!

For anyone who finds this thread in the future …

I was using a GratingStim object to capture a screenshot of the grating, transform it, and write it to a movie file using OpenCV that I can later playback with the MovieStim3 class. I was getting a memory leak when trying to generate movies more than a few seconds long and it turns out that the call to the “getMovieFrame” method both returns the screenshot as a PIL object AND appends the image to a list stored as an attribute of the Window object called “movieFrames” (thank you @Michael for pointing this out). You can call the “saveMovieFrames” method which will save all images in this list as images to a specified directory and empty the list, or if you don’t want to do this, manually emptying/deleting this list in between calls to the “getMovieFrame” method will prevent unnecessary memory allocation.