user1992705
user1992705

Reputation: 188

How to generate a video file using a series of plots on MATLAB?

I'm trying to stitch together a bunch of plots I created within a loop into a single video file. I've been at this for several hours, but had no luck. Here is my minimum working example where I attempt to use the VideoWriter function to create a video. I always get an error saying my frame(s) can't be copied into the video objects. Grr.

Here is my minimum working example:

n=(1:50)*2*pi;
for t = 1:1000
    Y = sin(n*50/t);
   plot(Y);     %plot shows a sine wave with decreasing frequency

   F(t) = getframe; %I capture the plot here


end

writerObj = VideoWriter('test2.avi'); %Attempt to create an avi
open(writerObj);
for t= 1:time

    writeVideo(writerObj,F(t))

end

close(writerObj);

Upvotes: 1

Views: 13482

Answers (2)

Hoki
Hoki

Reputation: 11792

Matheburg answer is correct and identified the part which was causing the error (at some point the scale of your axis was resized, which cause the frame size to change).

His solution works fine and if the usage of fplot works for you then follow his way.

In case you still want to use the traditional plot (2d lineserie object) method, then here's how I usually organize "animated" plots:

The plot function is high level. It means when it runs it plots the data (obviously) but also does a lot of other things. In any case it generate a completely new plot (erasing previous plot if hold on wasn't specified), but also readjust the axes limits and many other settings (color, style etc ...).

If in your animation you only want to update the plot data (the points/line position) but not change any other settings (axes limits, colors etc ...), it is better to define the plots and it's settings one time only, outside of the loop, then in the loop you only update the YData of the plot object (and/or the XData if relevant).

This is done by retrieving the plot object handle when you create it, then use the set method (which unlike plot will only modify the parameters you specify explicitly, and won't modify anything else).

In your case it looks like this:

n=(1:50)*2*pi ;

Y = sin(n*50) ;
hp = plot(Y) ;              %// Generate the initial plot (and retrieve the handle of the graphic object)
ylim([-1,1]) ;              %// Set the Y axes limits (once and for all)

writerObj = VideoWriter('test2.avi'); %// initialize the VideoWriter object
open(writerObj) ;
for t = 1:1000
   Y = sin(n*50/t) ;        %// calculate new Y values
   set(hp,'YData',Y) ;      %// update the plot data (this does not generate a "new" plot), nor resize the axes

   F = getframe ;           %// Capture the frame
   writeVideo(writerObj,F)  %// add the frame to the movie
end
close(writerObj);

Also, this method will usually runs faster, and save a significant amount of time if your loop has a great number of iterations.


Side note: As said above, Matheburg solution runs also fine. For such an application, the difference of speed will not be a major issue, but note that the plots (and movie) generated are slightly different (due to it's use of fplot instead of plot). So I encourage you to try both versions and choose which one suits you best.

Upvotes: 3

matheburg
matheburg

Reputation: 2180

You are missing a constant height of images. You can guarantee it by, e.g., ylim:

time = 100;
for t = 1:time
   fplot(@(x) sin(x*50/t),[0,2*pi]);  % plot
   ylim([-1,1]);                      % guarantee consistent height
   F(t) = getframe;                   % capture it
end

writerObj = VideoWriter('test2.avi');
open(writerObj);
writeVideo(writerObj, F)
close(writerObj);

I have further replaced your discrete plot by a "continuous" one (using fplot).

Upvotes: 2

Related Questions