How to animate points on an image in MATLAB? - matlab

I have the pixel locations of P points on a -constant- image, for T iterations of an algorithm, so locations = [T x 2*P] double.
Now I want to create an animation where it plots the image, then plots the points, pauses for N seconds and updates their location to the next step. I don't know if there is a standard way to follow. I think I need something like:
figure;
imshow(img);
hold on;
for t=1:T
anim = updatePlot(locations(t,:), anim); % ?
end
How can I implement this updatePlot function?
Thanks for any help!

You can do this a couple of different ways. The first way would be to give the plotted points a handle so that you can delete them before the next iteration:
figure
imshow(img);
hold on;
for t = 1:T
% delete the previous points plotted (skip t = 1 since they won't exist)
if t > 1
delete(hPoints);
end
hPoints = plot(xLocations(t,:),yLocations(t,:),'.');
getframe;
pause(N);
end
(I am not exactly sure how you parse your locations along each row to separate the x and y components, so I've just used xLocations and yLocations to represent those values.)
The second way would be to re-draw the entire image at each iteration:
figure
for t = 1:T
clf;
imshow(img);
hold on;
plot(xLocations(t,:),yLocations(t,:),'.');
getframe;
pause(N);
end
Note that imshow might have its own getframe effect so that you'll see the image flicker before plotting the points -- if that happens just switch from imshow to image.

Related

Plot digitization in MATLAB using ginput

I'm trying to digitize this image using MATLAB:
I have the following script:
%// Get data from plot
clear all; close all;
%// Input
fname = 'Fig15a.PNG';
xvec = [1e3:1:1e8];
yvec = [1e-4:1:1e-1];
xt = [1e3 1e4 1e5 1e6 1e7 1e8];
yt = [1e-4 1e-3 1e-2 1e-1];
%// Read and plot the image
im = imread(fname);
figure(1), clf
im = im(end:-1:1,:,:);
image(xvec,yvec,im)
axis xy;
grid on;
%// Set ticks
set(gca,'xtick',xt,'ytick',yt); %// Match tick marks
%// Collect data
[x,y] = ginput; %// Click on points, and then hit ENTER to finish
%// Plot collected data
hold on; plot(x,y,'r-o'); hold off;
%// Then save data as:
save Fig15a.mat x y
The script works fine
Is there a way I can change the x and y axes to a log scale ?
I have tried adding the following code in different places without luck:
%// Set Log scale on x and y axes
set(gca,'XScale','log','YScale','log');
Below's a proof of concept that should get you on the right track. I have replaced things in your original code with what I consider "good practices".
function q36470836
%% // Definitions:
FIG_NUM = 36470836;
%% // Inputs:
fname = 'http://i.stack.imgur.com/2as4t.png';
xt = logspace(3,8,6);
yt = logspace(-4,-1,4);
%% // Init
figure(FIG_NUM); clf
% Read and plot the image
im = imread(fname);
hIMG = imshow(im); axis image;
%// Set ticks
hDigitizer = axes('Color','none',...
'XLim',[xt(1) xt(end)],'YLim',[yt(1) yt(end)],...
'XScale','log','YScale','log',...
'Position',hIMG.Parent.Position .* [1 1 696/785 (609-64+1)/609]);
uistack(hDigitizer,'top'); %// May be required in some cases
grid on; hold on; grid minor;
%// Collect data:
[x,y] = ginput; %// Click on points, and then hit ENTER to finish
%// Plot collected data:
scatter(x,y,'o','MarkerEdgeColor','r');
%// Save data:
save Fig15a.mat x y
Here's an example of what it looks like:
Few notes:
xt, yt may be created in a cleaner fashion using logspace.
It is difficult (possibly impossible) to align the digitization grid with the image correctly, which would inevitably result in errors in your data. Though this can be helped in the following scenarios (for which you will require a vector graphics editor, such as the freeware InkScape):
If, by any chance, you got this image from a PDF file, where it appears as a vector image (you can test this by zooming in as much as you like without the chart becoming pixelated; this seems to be your case from the way the .png looks), you would be better off saving it as a vector image and then you have two options:
Exporting the image to a bitmap with a greatly increased resolution and then attempting the digitization procedure again.
Saving the vector image as .svg then opening the file using your favorite text editor and getting the exact coordinates of the points.
If the source image is a bitmap (as opposed to vector graphic), you can "trace the bitmap", thus converting it to vectoric, then #GOTO step 1.
This solution doesn't (currently) support resizing of the figure.
The magic numbers appearing in the Position setting are scaling factors explained in the image below (and also size(im) is [609 785 3]). These can technically be found using "primitive image processing" but in this case I just hard-coded them explicitly.
You can plot in double logarithmic scale with
loglog(x,y);
help loglog or the documentation give additional information.
For a single logarithmic scale use
semilogx(x,y);
semilogy(x,y);

How do I reach first and second plots from bode()

I know how to create the Bode plots with bode() function. If I want to overlap two or more systems frequency responses, I use
bode(sys1,sys2,...)
or
hold on
When I want to reach the plot in order to put a legend with text(), for instance, is easy to reach the second plot. Something like the figure pointer always returns to the second plot (phase graph).
i.e., if try these lines:
G = tf([1],[1 6]); figure(1); bode(G); text(10,-20,'text');
G = tf([1],[1 6]); figure(2); bode(G); text(10,-20,'text');
when I return to the first figure, with figure(1), and try
figure(1); text(10,-20,'text')
legend is displayed in the second plot (Phase plot)
I try these other lines:
P = bodeoptions; % Set phase visiblity to off
P.PhaseVisible = 'off';
G = tf([1],[1 6]);
figure(1); bode(G,P); text(10,-20,'text');
figure(1); text(10,-20,'text');
As you can see, even I turn off the phase plot visiblity, the legend is not displayed.
Essentialy, my question is, how do I reach first and second plots, one by one? I tried with subplot(), but it is pretty clear this is not the way Matlab traces these plots.
Thanks in advance.
It all comes to getting into upper plot, since after bodeplot command the lower one is active. Intuitively one would want to call subplot(2,1,1), but this just creates new blank plot on top of if. Therefore we should do something like this:
% First, define arbitrary transfer function G(s), domain ww
% and function we want to plot on magnitude plot.
s = tf('s');
G = 50 / ( s*(1.6*s+1)*(0.23*s+1) );
ww = logspace(0,3,5000);
y = 10.^(-2*log10(ww)+log10(150));
hand = figure; % create a handle to new figure
h = bodeplot(G,ww);
hold on;
children = get(hand, 'Children') % use this handle to obtain list of figure's children
% We see that children has 3 objects:
% 1) Context Menu 2) Axis object to Phase Plot 3) Axis object to Magnitude Plot
magChild = children(3); % Pick a handle to axes of magnitude in bode diagram.
% magChild = childern(2) % This way you can add data to Phase Plot.
axes(magChild) % Make those axes current
loglog(ww,y,'r');
legend('transfer function','added curve')
you can get magnitude and phase data separately for each system using:
[mag,phase] = bode(sys,w)
now you can use subplot or plot to plot the diagram you want.
The only solution I was able to perform is taking into account axis position. It is not very clean but it works.
Here is the code to select mag plot:
ejes=findobj(get(gcf,'children'),'Type','axes','visible','on');
posicion=get(ejes,'pos');
tam=length(posicion);
for ii=1:tam
a=posicion{ii}(2);
vectorPos(ii)=a;
end
[valorMax,ind]=max(vectorPos); % min for choosing the phase plot
axes(ejes(ind))

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

editing the random waypoint mobility matlab for a constant node

Please help me out with this. This plot gives the mobile users that are moving. Now, I am trying to add a few constant points in the plot. Like the base stations for the mobile users '*'. I want to put say a '#' for every base station and put like around 10 of them.
function test_Animate(s_mobility,s_input,time_step)
v_t = 0:time_step:s_input.SIMULATION_TIME;
for nodeIndex = 1:s_mobility.NB_NODES
%Simple interpolation (linear) to get the position, anytime.
%Remember that "interp1" is the matlab function to use in order to
%get nodes' position at any continuous time.
vs_node(nodeIndex).v_x = interp1(s_mobility.VS_NODE(nodeIndex).V_TIME,s_mobility.VS_NODE(nodeIndex).V_POSITION_X,v_t);
vs_node(nodeIndex).v_y = interp1(s_mobility.VS_NODE(nodeIndex).V_TIME,s_mobility.VS_NODE(nodeIndex).V_POSITION_Y,v_t);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure;
hold on;
for nodeIndex = 1:s_mobility.NB_NODES
vh_node_pos(nodeIndex) = plot(vs_node(nodeIndex).v_x(1),vs_node(nodeIndex).v_y(1),'*','color',[0.3 0.3 1]);
end
title(cat(2,'Simulation time (sec): ',num2str(s_mobility.SIMULATION_TIME)));
xlabel('X (meters)');
ylabel('Y (meters)');
title('Random Waypoint mobility');
ht = text(min(vs_node(1).v_x),max(vs_node(1).v_y),cat(2,'Time (sec) = 0'));
axis([min(vs_node(1).v_x) max(vs_node(1).v_x) min(vs_node(1).v_y) max(vs_node(1).v_y)]);
hold off;
for timeIndex = 1:length(v_t);
t = v_t(timeIndex);
set(ht,'String',cat(2,'Time (sec) = ',num2str(t,4)));
for nodeIndex = 1:s_mobility.NB_NODES
set(vh_node_pos(nodeIndex),'XData',vs_node(nodeIndex).v_x(timeIndex),'YData',vs_node(nodeIndex).v_y(timeIndex));
end
drawnow;
end
end
The complete submission of this can be got in the MATHworks site.
http://www.mathworks.in/matlabcentral/fileexchange/30939-random-waypoint-mobility-model
Please help me out.
Here's the basic idea. In the following, fixed_x and fixed_y are vectors of equal length giving the location of your fixed points.
moving_x and moving_y are matrices of size t x n where t is the number of time steps, and n the number of points.
%plot the fixed points
plot(fixed_x,fixed_y, 'p');
hold on
%plot the first set of moving points
h = plot(moving_x(1,:),moving_y(1,:),'r*');
Then, to move the points, we use the handle to the moving points, h to set XData and YData values. This would be within a loop where n is the time step:
set(h, 'XData',moving_x(n,:),'YData',moving_y(n,:));
%may need drawnow;
If you want to be able to see the points moving, you may need to add some pause command - otherwise it might cycle through the update loop so quickly you won't see anything except the final set of positions. On the other hand, you could just save out the figure as an image file after you've moved the points with set, or add it as a frame to a movie, etc.

MATLAB plot moving data points in separate subplots simultaneously

I wish to visualize the movement of a data point throughout space across a period of time within MATLAB. However, the way I want my figure to display is such that only a single instant is plotted at any given time. That was easy, I simply created a for loop to update my 3D plot display for every set of coordinates (x,y,z) in my data. However, I wish to display 4 different viewing angles of this plot at all times. I am well aware of how to setup subplots within MATLAB, that is not the issue. My issue is getting all 4 of these subplots to execute simultaneously so that all 4 subplots are always displaying the same point in time.
How to handle this issue?
As requested, my code for a figure with a single plot is shown below:
datan = DATA; %data in form of x,y,z,a,b,c by column for row# of time points
tib=zeros(size(datan,1),12);
tib(:,1:3) = datan(:,1:3);
tib_ref=tib(1,1:3);
for i=1:size(datan,1)
tib(i,1:3)=tib(i,1:3)-tib_ref;
end
angle_to_dircos
close all
figure('Name','Directions (Individual Cycles)','NumberTitle','off')
for cc=1:2
hold off
for bb=1:10:size(tib,1);
scatter3(tib(bb,1),tib(bb,2),tib(bb,3),'green','filled'); %z and y axes are flipped in polhemus system
hold on
p0 = [tib(bb,1),tib(bb,2),tib(bb,3)];
p1 = [tib(bb,1)+10*tib(bb,4),tib(bb,2)+10*tib(bb,5),tib(bb,3)+10*tib(bb,6)];
p2 = [tib(bb,1)+10*tib(bb,7),tib(bb,2)+10*tib(bb,8),tib(bb,3)+10*tib(bb,9)];
p3 = [-(tib(bb,1)+100*tib(bb,10)),-(tib(bb,2)+100*tib(bb,11)),-(tib(bb,3)+100*tib(bb,12))];
vectarrow(p0,p1,1,0,0)
hold on
vectarrow(p0,p2,0,1,0)
hold on
vectarrow(p0,p3,0,0,1)
hold on
az = 90;
el = 0;
view(az, el);
xlim([-50,50]);
ylim([-50,50]);
zlim([-50,50]);
xlabel('distance from center in X');
ylabel('distance from center in Y');
zlabel('distance from center in Z');
title('XYZ Scatter Plots of Tracker Position');
hold on
plot3(0,0,0,'sk','markerfacecolor',[0,0,0]);
p0 = [0,0,0];
p1 = [10,0,0];
p2 = [0,10,0];
p3 = [0,0,100];
vectarrow(p0,p1,1,0,0)
hold on
vectarrow(p0,p2,0,1,0)
hold on
vectarrow(p0,p3,1,0,1)
drawnow;
end
end
If you use set to update the x and y-data of your points, rather than recreating the plot entirely every time, the update will be simultaneous thanks to Matlab waiting for drawnow.
Here's an example
figure,
subplot(1,2,1),plot(rand(10,1),rand(10,1),'.'),hold on,p1=plot(rand(1),rand(1),'.r')
subplot(1,2,2),plot(rand(10,1),rand(10,1),'.'),hold on,p2=plot(rand(1),rand(1),'.r')
%# read the red coordinates - I should have stored them before plotting :)
x(1) = get(p1,'xdata');y(1)=get(p1,'ydata');x(2)=get(p2,'xdata');y(2)=get(p2,'ydata');
%# animate
for i=1:100,
delta = randn(1,2)*0.01;
x=x+delta(1);
y=y+delta(2);
set(p1,'xdata',x(1),'ydata',y(1));
set(p2,'xdata',x(2),'ydata',y(2));
pause(0.1),
drawnow, %# I put this in case you take out the pause
end