Making a gif from images

2019-07-19 14:27发布

问题:

I have a load of data in 100 .sdf files (labelled 0000.sdf to 0099.sdf), each of which contain a still image, and I'm trying to produce a .gif from these images.

The code I use to plot the figure are (in the same directory as the sdf files):

q = GetDataSDF('0000.sdf');
imagesc(q.data');

I've attempted to write a for loop that would plot the figure and then save it with the same filename as the sdf file but to no avail, using:

for a = 1:100
    q=GetDataSDF('0000.sdf');
    fh = imagesc(q.dist_fn.x_px.Left.data');
    frm = getframe( fh );
    % save as png image
    saveas(fh, 'current_frame_%02d.jpg');
end

EDIT: I received the following errors when trying to run this code:

Error using hg.image/get
The name 'Units' is not an accessible property for an instance of class 'image'.

Error in getframe>Local_getRectanglesOfInterest (line 138)
  if ~strcmpi(get(h, 'Units'), 'Pixels')

Error in getframe (line 56)
  [offsetRect, absoluteRect, figPos, figOuterPos] = ...

Error in loop_code (line 4)
    frm = getframe( fh );

How do I save these files using a for loop, and how do I then use those files to produce a movie?

回答1:

The reason for the error is that you pass an image handle to getframe, but this function excpects a figure handle. Another problem is that you always load the same file, and that you saveas will not work for gifs. (For saving figures as static images, maybe print is the better option?)

I tried to modify my own gif-writing loop so that it works with your data. I'll try to be extra explicit in the comments, since you seem to be starting out. Remember, you can always use help name_of_command to display a short Matlab help.

% Define a variable that holds the frames per second your "movie" should have
gif_fps = 24; 
% Define string variable that holds the filename of your movie
video_filename = 'video.gif';

% Create figure 1, store the handle in a variable, you'll need it later
fh = figure(1);
for a = 0:99
    % Prepare file name so that you loop over the data
    q = GetDataSDF(['00' num2str(a,'%02d') 'sdf']);
    % Plot image
    imagesc(q.dist_fn.x_px.Left.data');
    % Force Matlab to actually do the plot (it sometimes gets lazy in loops)  
    drawnow;
    % Take a "screenshot" of the figure fh
    frame = getframe(fh);
    % Turn screenshot into image
    im = frame2im(frame);
    % Turn image into indexed image (the gif format needs this)
    [imind,cm] = rgb2ind(im,256);
    % If first loop iteration: Create the file, else append to it
    if a == 0;
        imwrite(imind,cm,video_filename,'gif', 'Loopcount',inf);
    else
        imwrite(imind,cm,video_filename,'gif','WriteMode','append','DelayTime',1/gif_fps);
    end
end

One more note: When the size of the data is the same for each plot, it makes sense to only use the plot(or in this case, imagesc) command once, and in later loop iterations replace it with a set(ah,'Ydata',new_y_data) (or in this case set(ah,'CData',q.dist_fn.x_px.Left.data'), where ah is a handle of the plot axes (not the plot figure!). This is orders of magnitude faster than creating a whole new plot in each loop iteration. The downside is that the scaling (here, the color-scaling) will be the same for each plot. But in every case that I have worked on so far, that was actually desirable.