matlab image popping during animation creation [duplicate] - matlab

This question already has answers here:
Approaches to create a video in matlab
(4 answers)
Closed 6 years ago.
I'll do my best to explain my problem. I am simulating the dynamics of a network and I'd like to get an animation where each frame represents my network with a specific color for each node with respect to an input file.
Here my script
for ii=1:Movie_size
hfig=figure('visible','off');
hold on;
%plot edges
for kk=1:Nedge,
plot(xedge(kk,:),yedge(kk,:),'black')
end
%color of the nodes
for kk=1:nodes,
val=(1-(Color_node(12798 ,kk)-umin)/(umax-umin));
ggCol(kk,:)=[1,val,1-val];
end
%enhanced the contrast of the figure
ggCol = imadjust(ggCol,[.2 .3 0; .6 .7 1],[]);
%plot nodes
for kk=1:nodes,
plot(xpos(kk),ypos(kk),'o','MarkerFaceColor',ggCol(kk,:), ...
'MarkerEdgeColor','k','MarkerSize',10)
end
frames(ii)=getframe(hfig);
hold off;
end
movie(frames);
I succeeded in plotting each frame but when I want to get the animation, I have all the figures being displayed and no movie. I tried a lot of different things but it never works...
PS : I have been editing the title since the topic seems to have been already asked...

While you have already called getframe which takes a screen capture of the current figure, you need to do something with this frame to make a movie. The typical thing would be to add this frame to an existing VideoWriter object within your loop.
writer = VideoWriter('output.avi');
hfig = figure();
hplot = plot(rand(10,1));
for k = 1:100
% Update the plot
set(hplot, 'YData', rand(10, 1));
% Take a screengrab and add it to the video file
frame = getframe(hfig);
writer.writeVideo(frame);
end
writer.close()
Alternately, you can create an array of frames and then display these interactively within MATLAB with movie.
for k = 1:100
frames(k) = getframe(hfig);
end
% View as a movie
movie(frames)
Update
Based on your updated question, the windows have to popup because getframe must have the figure render before it is able to capture the screen. Also, you've created your array of frames but haven't attempted to display a movie. You need:
movie(frames)

Related

Animation of figure with subplots using VideoWriter in MATLAB

I'm trying to create an animation file in MATLAB from a figure with 2 subplots using the VideoWriter. However, the avi file that I get includes only one of the subplots.
Here is the code:
clc
clear
vidObj = VideoWriter('randdata');
open(vidObj)
figure (1)
for i = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow
CF = getframe;
writeVideo(vidObj,CF);
end
There must be something simple going wrong here but I don't know what. I would like to capture the entire figure.
The documentation for getframe states in the first line:
F = getframe captures the current axes
So it's capturing the axes, not figure.
You want to use it as also specified in the documentation
F = getframe(fig) captures the figure identified by fig. Specify a figure if you want to capture the entire interior of the figure window, including the axes title, labels, and tick marks. The captured movie frame does not include the figure menu and tool bars.
So your code should be
clc; clear
vidObj = VideoWriter('randdata');
open(vidObj);
figure(1);
for ii = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow;
% The gcf is key. You could have also used 'f = figure' earlier, and getframe(f)
CF = getframe(gcf);
writeVideo(vidObj,CF);
end
For ease, you might want to just get a File Exchange function like the popular (and simple) gif to create an animated gif.

Animated plots MATLAB [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have problem to produce animated plots, using MATLAB.
I want to plot my signal y as a function of my time x (that i keep in two separate variables) and then produce an animation of it, seeing variations of my signal according to time.
At the end, I would like to produce both a succession of ".tif" images (for reading it in imageJ) and a ".avi" movie file.
It will really help me if someone can show me the way, because i try to do it by myself using MATLAB Help and forums, but i failed every time.
Thanks in advance!
The standard way of doing this would be to update your plot data within a loop, and use getframe or a similar function to grab the current screen and save it to a file with imwrite or VideoWriter.
imwrite
With imwrite it is important that if you want to write multi-frame data (for either a TIFF or GIF) you want to use the 'WriteMode' parameter and set it to 'append' so that you simply add the new frame to the image. On the first time through the loop you don't want to append since that would append to an existing image that may already exist.
getframe
As far as getframe, it grabs a screenshot of the specified figure and returns a struct containing a colormap and the RGB image as cdata. This is the thing that you want to write to either your video or your multi-frame image.
VideoWriter
For writing to video, you'll use the VideoWriter class which behaves a little differently. The main steps are:
Create the object
vid = VideoWriter('filename.avi');
Open the object
vid.open() % or open(vid)
Write some data using writeVideo
vid.writeVideo(data)
Close the Video
vid.close()
Then you can call writeVideo as many times as you want and each time it will add an additional frame.
Summary
Here is a demo which brings all of that together and writes a multi-frame TIFF as well as an AVI.
% Example data to plot
x = linspace(0, 2*pi, 100);
y = sin(x);
% Set up the graphics objects
fig = figure('Color', 'w');
hax = axes();
p = plot(NaN, NaN, 'r', 'Parent', hax, 'LineWidth', 2);
set(hax, 'xlim', [0, 2*pi], 'ylim', [-1 1], 'FontSize', 15, 'LineWidth', 2);
% Create a video object
vid = VideoWriter('video.avi')
vid.open()
% Place to store the tiff
tifname = 'image.tif';
for k = 1:numel(x)
set(p, 'XData', x(1:k), 'YData', y(1:k));
% Grab the current screen
imdata = getframe(fig);
% Save the screen grab to a multi-frame tiff (using append!)
if k > 1
imwrite(imdata.cdata, tifname, 'WriteMode', 'append')
else
imwrite(imdata.cdata, tifname);
end
% Also write to an AVI
vid.writeVideo(imdata.cdata);
end
% Close the video
vid.close()
Results (as an animated GIF)

Animate through multiple 2D Matlab plots

I have multiple 2D line plots in Matlab (they represent some wave moving through space). Each plot represents the wave at some time t. I want to animate through these plots (i.e. show the first plot for a fraction of a second, then show the next one, and the next, etc. I want to loop back to the beginning once it reaches the end time) to show the time evolution of the system. surf and mesh don't really do what I want since it is too difficult to see the changes with the number of time steps I have. Is there a way to do this in Matlab?
I assume with "2d-line" you mean a 2d-plot. This is done by the plot-function, so there is no need of surf or mesh. Sorry, when I got you wrong.
The following code does what I think you asked for:
% Generate some propagating wave
n = 20;
t = linspace(0,10,100);
x = cell(1,n);
for i = 1:n
x{i} = (1-abs(i/n-0.4))*sin(t+i*0.2);
end
% Create frames
figure;
for i = 1:length(x)
clf;
plot(t,x{i});
ylim([-1,1]);
myFrames(i) = getframe; %#ok<SAGROW>
end
% Show movie
figure;
movie(myFrames,2,2); % frames, repetitions, frames per second

Change the color of a pixel in an imagesc plot without repainting everything in Matlab/Octave

I have a for-loop where I would like to paint at every step a new pixel in an imagesc plot. I am currently repainting the whole figure but the figure is blinkering and I know it is not the proper way to do so. Can anyone help to find the appropriate function to do this task?
You can address the data in each pixel with the CData property of the image without having to close and redraw the figure, axes, or axes object over and over. Ends up being about 1.5x - 2x faster than trying to generate a new image object or just calling imagesc() over and over.
In these loops don't forget the drawnow call or MATLAB will try to skip the figure drawing until the looping completes.
Example code:
data = rand(200, 200); % Data to display
figure(1) % Make a figure
imgHand = imagesc(data); % Display data in it
% Naive way - call imagesc() each time.
% Slow. Don't do it this way.
for k = 1:numel(data);
data(k) = data(k) + 10*rand(1,1); % Update data
imagesc(data) % Redraw it by calling imagesc()
drawnow; % Display updated figure
end
% Faster way - address CData of image object directly
% 1.5-2x faster than above method
for k = 1:numel(data);
data(k) = data(k) + 10*rand(1,1); % Update data
set(imgHand, 'CData', data); % Change CData property of object
drawnow; % Display updated figure
end
You don't have a choice but to paint everything at each iteration if you want to draw every frame that has an update. However, you can minimize the flickering (or perhaps even remove it) by perhaps placing a pause at the end of your loop before the next iteration. This way, it'll give the frame buffer a chance to draw to the screen completely before you draw the next frame.
Something like:
for idx = 1 : total_frames
%// Do stuff
drawnow; %// Draw frame
pause(0.1); %// Pause
end
total_frames would be the total number of times you are refreshing the plot, and inside the loop you would do the work necessary, you then draw the figure, then pause for 0.1 ms. Adjust the time to whatever works for you.

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);
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.
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).