Reputation: 188
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
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
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