Matlab animate background and line in same figure - matlab

I am trying to animate a line over a dynamic background at the same time, the problem is I cannot update both in the same plot. If I animate the background the lines don't appear.
So the question is why? I was trying in different positions without success.
If you remove the part of the imagesc, there is no problem and the animation of the lines flow
for k = 1:numel(t)
decay = rand;
res = decay * background;
imagesc(x,y,flip(res));
hold on
clearpoints(h);
clearpoints(p);
addpoints(p,[l,(cosO(k)],[0,cosO(k)]);
addpoints(h,[r,(senO(k)],[0,senO(k)]);
drawnow
hold off
end
Fixed! Create a handler and modify CData inside of the loop:
imh = imagesc(x,y,flip(res));
for ...
imh.CData = flip(res);
end

The calls to imagesc overrun your plot. you can overcome this by only change the image matrix represented by imagesc (as 'CData' property):
for k = 1:numel(t)
decay = rand;
res = decay * background;
if k == 1
imh = imagesc(x,y,flip(res));
else
imh.CData = flip(res);
% or: set(imh, 'CData', flip(res) ); % in older MATLAB versions
...
end

Related

Save animation as gif in Matlab GUI

I am trying to save an animation as animated GIF.
My plot is similar to the given code below.
I created it with animated line too.
The problem is that:
When I defined my figure as f=figure or figure(1) it creates the .gif file properly.
However, instead of plotting my figure in separate screen using "figure" command, I have to plot in an axes on MATLAB GUI axes as the given figure.
I tried it with: f=(handles.axes_threeDOF);, But when I use this function, the gif file creates different part of the screen.
Could you help me to solve my problem?
numpoints = 500;
x = linspace(0,4*pi,numpoints);
y = square(x);
y2 = 3 +square(x+1);
f = figure
h = animatedline('Color','b','LineWidth',2);
h2 = animatedline('Color','r','LineWidth',2);
grid on;
axis([0,12,-3,+6])
for k = 1:numpoints
addpoints(h,x(k),y(k))
addpoints(h2,x(k),y2(k))
drawnow
% Capture the plot as an image
frame = getframe(f);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
% Write to the GIF File
if k == 1
imwrite(imind,cm,'test.gif','gif', 'Loopcount',inf);
else
imwrite(imind,cm,'test.gif','gif','WriteMode','append');
end
end
I want to create a gif of this animation:
But it creates as given below with this function " f=(handles.axes_threeDOF)"
I think I found the problem:
f = handles.axes_threeDOF gets the handle of the axes instead of getting the handle of the figure.
Since I don't know the name of your figure, I can't give a perfect solution.
You may try the following options:
1.Find the name of the figure, and use something like: f = handles.figure_threeDOF;
2. Use f = gcf();, assuming there is only one figure.
3. Use f = handles.axes_threeDOF.Parent; assuming the figure is the "Parent" of the axes.
Update:
After im = frame2im(frame);, you need to crop the relevant part of the image:
Something like: im = im(36:884, 928:1800, :);
There are more robust solution than using fixed indices, but it requires some knowledge about the internal structure of the figure.
Here is a code that reproduce the problem (instead of figure handle, f gets axes handle):
numpoints = 500;
x = linspace(0,4*pi,numpoints);
y = square(x);
y2 = 3 +square(x+1);
f = figure;
h = animatedline('Color','b','LineWidth',2);
h2 = animatedline('Color','r','LineWidth',2);
grid on;
axis([0,12,-3,+6])
for k = 1:numpoints
addpoints(h,x(k),y(k))
addpoints(h2,x(k),y2(k))
drawnow
%%% Test %%%
%The following code demonstrates the problem.
%f = gca(), returns a handle to the axes, instead of the figure.
%You should remove the following line for the code to work properly...
f = gca();
%%% Test %%%
% Capture the plot as an image
frame = getframe(f);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
% Write to the GIF File
if k == 1
imwrite(imind,cm,'test.gif','gif', 'Loopcount',inf);
else
imwrite(imind,cm,'test.gif','gif','WriteMode','append');
end
end
Result of correct code (without f = gca();):
Result of wrong code (with f = gca();) - getting axes handle instead of figure handle:

Implementation of animatedline command to animate two lines simultaneously

This is a follow up to this question in which I was trying to animate two functions simultaneously. The solution provided did in fact fulfill the requirements and so I accepted it as a final answer.
However, I ran into additional problems when I tried to implement something similar for my more realistic case. The intent of the code below is to:
Generate a 3d matrix containing incrementally (linear) varying stress values named Stresses. The first index is for the incrementally varying values, the second index corresponds to each value in Depth matrix and the third index corresponds to each animatedline object
Generate a 2D matrix named Depth containing two rows. each row corresponds to an animatedline.
Plot the animated lines and animate simultaneously
%%PLOT AND ANIMATE
nlines = 2
h(1:nlines) = animatedline();
axis([-2.1,2,-10,0]);
for i = 1:100
for j = 1:3
Stresses(i,j,1) = (i/100)+j/3
Stresses(i,j,2) = -(i/100)-j/3
end
end
Depth = [0, -5, -10; 0,-6,-9]
for i = 1:size(Stresses,1)
for n = 1:nlines
n
currentStresses = Stresses(i,:,n)
h(n).clearpoints();
h(n).addpoints(currentStresses, Depth(n,:));
%pause(0.01)
end
drawnow
end
As far as I can tell this uses a similar format to the previous question. Including the pause statement results in simultaneous but "Choppy" plotting. Not including the pause statement results smooth but "non-simultaneous" plotting. I.e it plots only the second line.
I would like for the animation to be smooth and simultaneously plot both animatedline objects. How can I accomplish this?
For simultaneous plotting, you are missing the hold function.
close all
%%PLOT AND ANIMATE
nlines = 2;
% optional: so that you can distinguish between the two lines
colors = {'r','b'};
for n = 1:nlines
h(n) = animatedline('color',colors{n});
end
axis([-2.1,2,-10,0]);
for i = 1:50
for j = 1:3
Stresses(i,j,1) = (i/100)+j/3;
Stresses(i,j,2) = -(i/100)-j/3;
end
end
Depth = [0, -5, -10; 0,-6,-9];
for i = 1:size(Stresses,1)
for n = 1:nlines
n;
currentStresses = Stresses(i,:,n);
h(n).clearpoints();
h(n).addpoints(currentStresses, Depth(n,:));
% wait for another line
hold on
end
% clear hold
hold off
drawnow
end
Hope that helps!

Animate surface plot in Matlab

I have a matrix representing height of a 10x10 square grid over time. The height is updated in a for loop over the rows and columns. My attempt was to simply put the surf(height) within the this loop, with a 0.1 second pause between plots, because this is how I done it with a 2-d plot. How can I make this work?
I think the best way is to update the data directly from your surface plot.
To do so, assign it a handles (eg. named hSurf) during its creation and then update the ZData property using, for example,
set(hSurf,'ZData',SomeValues)
Sample code:
clear
clc
close all
figure(1)
%// Generate data
Z = peaks(25);
%// Create handles to access/modify data.
hSurf = surf(Z);
k = 0;
%// Set up name to create animated gif.
filename = 'AnimateSurf.gif';
%// Just a loop
while k < 10
%// IMPORTANT part. Update the Z data
set(hSurf,'ZData',k*Z);
%// Set limits so the graph looks nice.
zlim([-80 80])
drawnow
%// Capture frame to write to gif.
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if k == 0;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
pause(.15)
k = k+1;
end
And output:

How to do an animated plot in matlab

I was wondering if anyone knew how to do an animation plot of
x = (dataset of 1000 points)
y = (dataset of 1000 points)
plot(x,y)
big problem is these are datasets that i am trying to plot , or x,y coordinates as opposed to a function which I would know how to plot via an animation.
I tried to do frames in a for loop but it gave me dots and didn't join them in a line graph so I couldn't really watch the path being traced out.
code I used was
for i = 1:length(DATASET1)
pause(0.1)
plot(DATASET1(i),DATASET2(i))
draw on
end
If what you want is for the plot to "grow" point by point: the easiest way is to create an empty plot and then update its XData and YData properties at each iteration:
h = plot(NaN,NaN); %// initiallize plot. Get a handle to graphic object
axis([min(DATASET1) max(DATASET1) min(DATASET2) max(DATASET2)]); %// freeze axes
%// to their final size, to prevent Matlab from rescaling them dynamically
for ii = 1:length(DATASET1)
pause(0.01)
set(h, 'XData', DATASET1(1:ii), 'YData', DATASET2(1:ii));
drawnow %// you can probably remove this line, as pause already calls drawnow
end
Here's an example1 obtained with DATASET1 = 1:100; DATASET2 = sin((1:100)/6);
1 In case someone's interested, the figure is an animated gif which can be created by adding the following code (taken from here) within the loop, after the drawnow line:
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,filename,'gif','Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
Looks like you were close. Not sure draw on is any command though.
See if the code here inspires you to solve your case -
%// Sample x and y values assumed for demo.
x = 1:1000;
y = x.^2;
%// Plot starts here
figure,hold on
%// Set x and y limits of the plot
xlim([min(x(:)) max(x(:))])
ylim([min(y(:)) max(y(:))])
%// Plot point by point
for k = 1:numel(x)
plot(x(k),y(k),'-') %// Choose your own marker here
%// MATLAB pauses for 0.001 sec before moving on to execue the next
%%// instruction and thus creating animation effect
pause(0.001);
end
Since R2014b, you can work with annimatedline object (doc and how-to) that is meant to handle animated graphs pretty well. Basically, the annimatedline object has a addpoints function that adds new points to the line without having to redefine the existing points, along with a clearpoints function that clears lines for more complex animations.
Here is an example:
h = animatedline;
axis([0,4*pi,-1,1])
x = linspace(0,4*pi,1000);
y = sin(x);
for k = 1:length(x)
addpoints(h,x(k),y(k));
drawnow
end

Matlab: Real-time plotting of ROI selected with IMRECT

I have a GUI with two axes. The first axes has a low-resolution image.
What I would like to do is select an area on the first axes using IMRECT and then display that area as a high-resolution image on the second axes, while continuously updating as I move the IMRECT rectangle around.
The only way I have been able to do this is with a "for loop" with a 0.1 pause in it that just runs for a minute or two while I select and change the ROI with IMRECT, very cumbersome.
My thought was to use a function that ran whenever the mouse moved within the first axes, with the ploting and getPosition commands in that function. However, I'm not sure how to write such a function (triggering on mouse movement within an axes).
Any help would be greatly appreciated!
In general, you should assign a callback to your imrect. For example:
x = imrect();
x.addNewPositionCallback( #(x)(disp('The rect has changed')))
The callback should get additional parameters, such as the image and the second axes by utilizing anonymous functions.
I wrote a small code snippet that does what you want. You should add boundary checks, since I did not bother. It updates CData instead of running imshow when you move the rectangle, so it is quite smooth.
function Zoomer
figure();
highResImage = imread('peppers.png');
lowResImage = imresize(highResImage,0.5);
a1 = subplot(2,1,1);
a2 = subplot(2,1,2);
imshow(lowResImage,'Parent',a1);
initialPosition = [10 10 100 100];
lowResRect = imrect(a1,initialPosition);
lowResRect.addNewPositionCallback( #(pos)Callback(pos,a2,highResImage));
Callback( initialPosition , a2, highResImage);
end
function Callback(position,axesHandle, highResImage)
position = position * 2;
x1 = position(1);
y1 = position(2);
x2 = position(1) + position(3);
y2 = position(2) + position(4);
highResThumbnail = highResImage( round(y1:y2),round(x1:x2),:);
if isempty( get(axesHandle,'Children'))
imshow(highResThumbnail,'Parent',axesHandle);
else
imHandle = get(axesHandle,'Children');
oldSize = size(get(imHandle,'CData'));
if ~isequal(oldSize, size(highResThumbnail))
imshow(highResThumbnail,'Parent',axesHandle);
else
set( imHandle,'CData', highResThumbnail);
end
end
end
Simillar functionality as #Andrey's reply, with three differences:
Setting axis limits instead of 'CData' (which may be faster?)
The magnification factor is variable and depends on the rectangle size, due to the 'fit' 'IniitalMagnification'.
Added ConstraintFcn
would be:
function imZ = Zoom(im, s)
f = figure;
a1 = subplot(1,2,1);
imshow(im,'InitialMagnification', 'fit');
a2 = subplot(1,2,2);
imshow(im,'InitialMagnification', 'fit');
Ipos = [0 0 s];
rect = imrect(a1,Ipos);
rect.setPositionConstraintFcn(#(p) Const(p,size(im)));
rect.addNewPositionCallback(#(p) CB(p,a2));
CB(Ipos,a2);
if nargout > 0
uiwait(f);
imZ = im(pm(2):pm(2)+pm(4),pm(1):pm(1)+pm(3),:);
end
function p = Const(p,imS)
p(1:2) = max(1,p(1:2));
p(1:2) = min(imS([2 1])-p(3:4),p(1:2));
end
function CB(p,a)
pm = round(p);
axes(a);
axis([pm(1),pm(1)+pm(3),pm(2),pm(2)+pm(4)]);
end
end
which could be called as:
Zoom(imread('peppers.png'),[100 100]);