Matlab for loop animations - matlab

I'm trying to animate the graph of a function but I cant get the program to graph the correct points. I want to plot points between time 0 and 10 and animate this graph. How do I get the plot as a function of time?
clear;
w = 2*pi;
t = 0:.01:10;
y = sin(w*t);
x = cos(w*t);
for j=1:10
plot(x(6*j),y(6*j),'*');
axis square;
grid on;
F(j) = getframe;
end
movie(F,1,1);
I refined the code to:
clear;
w = 2*pi;
for j=2:11
t=j-1;
y = sin(w*t);
x = cos(w*t);
plot(x(t),y(t),'*');
axis square;
grid on;
F(j) = getframe;
end
movie(F);
This should do what I'm trying however now I'm getting an "Index exceeds matrix dimension." How can I solve this?

Here is an example that show an animated point along a circular path, while recording an AVI movie.
To learn more about doing animations and recording movies in MATLAB, check out this guide.
%# some parameters
ERASEMODE = 'normal'; %# normal,xor
RENDERER = 'painters'; %# painters,zbuffer,opengl
%# data
t = linspace(0,2*pi,100)'; %'# adjust number of points here
D = [cos(t) -sin(t)];
%# plot circluar path
figure('DoubleBuffer','on', 'Renderer',RENDERER)
plot(D(:,1), D(:,2), 'Color','b', 'LineWidth',2)
grid on, axis([-1.5 1.5 -1.5 1.5]), axis square
xlabel('x'), ylabel('y'), title('Circle Animation')
%#set(gca, 'DrawMode','fast')
%# moving point
hPoint = line('XData',D(1,1), 'YData',D(1,2), 'EraseMode',ERASEMODE, ...
'Color','r', 'Marker','.', 'MarkerSize',30);
%# moving coordinates text
hTxtCoords = text(D(1,1), D(1,2), sprintf('(%.2f,%.2f)',D(1,:)), ...
'Color',[0.2 0.2 0.2], 'FontSize',8, 'EraseMode',ERASEMODE, ...
'HorizontalAlignment','left', 'VerticalAlignment','top');
%# angle text
hTxtAngle = text(0, 0, num2str(t(1),'%.02f'), ...
'FontSize',15, 'EraseMode',ERASEMODE, ...
'HorizontalAlignment','center', 'VerticalAlignment','middle');
%# prepare video output
useVideoWriter = ~verLessThan('matlab','7.11');
if useVideoWriter
vid = VideoWriter('vid.avi');
vidObj.Quality = 100;
vid.FrameRate = 30;
open(vid);
else
vid = avifile('vid.avi', 'fps',30, 'quality',100);
end
%# loop
for i=1:numel(t)
set(hPoint, 'XData',D(i,1), 'YData',D(i,2)) %# update point location
set(hTxtAngle, 'String',num2str(t(i),'%.02f')) %# update angle text
set(hTxtCoords, 'Position',D(i,:), ... %# update angle text
'String',sprintf('(%.3f,%.3f)',D(i,:)))
drawnow %# force refresh
if ~ishandle(hPoint), break; end %# if you close the figure
%# capture frame
if useVideoWriter
writeVideo(vid,getframe);
else
vid = addframe(vid, getframe(gcf));
end
end
%# close and save video output
if useVideoWriter
close(vid);
else
vid = close(vid);
end
%# open AVI file using system default player
winopen('vid.avi')

It's doing exactly what you ask it to do. You're subsampling the x and y, so it looks kind of funny.
Try
plot(x,y);
axis square;
ax = axis;
for jx = 1 : length(t),
plot(x(ix), y(ix), '*');
axis(ax); grid on;
F(ix) = getframe;
end
movie(F, 1, 1/(t(2)-t(1)))
I would also use t = 1 : 0.1 : 10; so that it plots at 10 FPS instead of 100. Slowing the frequency down to, say, w = pi; will be smoother as well.
At the end of the day, Matlab is just not a great animation solution.
Answer to refined code question
You'd need to use plot(x,y);, but this will reveal another error - your frame index does not start at 1. It will choke on F(j) in the first iteration, where j = 2. Why not just loop over t = 1 : 10?

Related

How to make animation in MATLAB which the curve is moving, not axes is moving?

I want to plot y=omega*x^2, which omega is -3 into 3 with step size 0.25, x from -4 into 4 with step size 0.001. But this code give me the curve is cannot moving and axes is moving. I want the curve is moving, like this.
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
pause(0.1);
end
How to do that?
As another answer has indicated, you need to set the axis limits.
(Also note that there is no reason to calculate y using a loop.)
But instead of using plot every time through the loop it's more efficient to create the line only once, and then replace the x and y data of the line each time through the loop.
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create line
hl = plot(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace line data
set(hl,'XData',x,'YData',y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
Or you might want to use animatedline,
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create animated line
am = animatedline(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace the line
clearpoints(am)
addpoints(am,x,y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
A quick method is setting the x- and y-axes limits in the loop after each plot, using the axis([xmin, xmax, ymin, ymax]) command. This method isn't foolproof, in the case that the script gets help up after plotting but before setting the axes limits, but in most cases it should work.
figure(1)
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
axis([-4 4 -50 50])
pause(0.1);
end
This is the same as #phil-goddard's answer, but makes more efficient use of handles to the animated YData and title string.
x = -4 : 0.001 : 4;
y = zeros(1, numel(x));
omega_range = -3 : 0.25 : 3;
% Create line and title, and obtain handles to them.
h_plot = plot(x, y);
axis([-4, 4, -40, 40]);
box on;
grid on;
h_title = title(sprintf('\\omega = %.2f', 0));
for idx = 1:numel(omega_range)
omega = omega_range(idx);
y = omega * (x.^2);
% Replace y data.
h_plot.YData = y;
% Replace title string.
h_title.String = sprintf('\\omega = %.2f', omega);
pause(0.1);
end

Detecting lanes in a video using matlab and image processing.

I am a little bit new to matlab and imageprocessing and I was given a task at my faculty to carry out a project which detects the lanes for a moving car in a video. I tried to use some tutorials on Mathworks and other sites and there were really helpful and I came out with a code that detects lanes in an image and I just want to know how to apply my code on a video as I see it working properly on an image.
and here is my code :
img = imread ('test_image.jpg');
I = rgb2gray (img);
%making a gaussian kernel
sigma = 1 ; %standard deviation of distribution
kernel = zeros (5,5); %for a 5x5 kernel
W = 0 ;
for i = 1:5
for j = 1:5
sq_dist = (i-3)^2 + (j-3)^2 ;
kernel (i,j) = exp (-1*exp(sq_dist)/(2*sigma));
W = W + kernel (i,j) ;
end
end
kernenl = kernel/W ;
%Now we apply the filter to the image
[m,n] = size (I) ;
output = zeros (m,n);
Im = padarray (I , [2 2]);
for i=1:m
for j=1:n
temp = Im (i:i+4 , j:j+4);
temp = double(temp);
conv = temp.*kernel;
output(i,j) = sum(conv(:));
end
end
output = uint8(output);
%--------------Binary image-------------
level = graythresh(output);
c= im2bw (output,level);
%---------------------------------------
output2 = edge (c , 'canny',level);
figure (1);
%Segment out the region of interest
ROI = maskedImage;
CannyROI = edge (ROI , 'canny',.45);
%----------------------------------
set (gcf, 'Position', get (0,'Screensize'));
%subplot (141), imshow (I), title ('original image');
%subplot (142), imshow (c), title ('Binary image');
%subplot (143), imshow (output2), title ('Canny image');
%subplot (144), imshow (CannyROI), title ('ROI image');
[H ,T ,R] = hough(CannyROI);
imshow (H,[],'XData',T,'YData',R,'initialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on , axis normal, hold on ;
P = houghpeaks(H,5,'threshold',ceil (0.3*max(H(:))));
x = T(P(:,2));
y = R(P(:,1));
plot (x,y,'s','color','white');
%Find lines and plot them
lines = houghlines (CannyROI,T,R,P,'FillGap',5,'MinLength',7);
figure, imshow (img), hold on
max_len = 0 ;
for k = 1:length(lines);
xy = [lines(k).point1; lines(k).point2];
plot (xy(:,1), xy(:,2), 'LineWidth', 5 , 'Color', 'blue');
%plot beginnings and ends of the lines
plot (xy(1,1), xy(1,2),'x', 'LineWidth', 2, 'Color', 'yellow');
plot (xy(2,1), xy(2,2),'x', 'LineWidth', 2, 'Color', 'red');
%determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if (len>max_len)
max_len = len;
xy_long = xy;
end
end
and here is the link of the image and the video :
https://github.com/rslim087a/road-video
https://github.com/rslim087a/road-image
Thanks in advance.
Basically video processing happens in such a way that video will be converted to video frames (images). So if you need, you can convert your video to video frames and run the code, looping over the folder having the video frames. Change the imread function to get images from video frames folder...
img = imread(path_to_video_frames_folder/*)

Changing speed of a point moving along a graph in MATLAB

I have used the code provided by #Amro in other question:
%# control animation speed
DELAY = 0.01;
numPoints = 600;
%# create data
x = linspace(0,10,numPoints);
y = log(x);
%# plot graph
figure('DoubleBuffer','on') %# no flickering
plot(x,y, 'LineWidth',2), grid on
xlabel('x'), ylabel('y'), title('y = log(x)')
%# create moving point + coords text
hLine = line('XData',x(1), 'YData',y(1), 'Color','r', ...
'Marker','o', 'MarkerSize',6, 'LineWidth',2);
hTxt = text(x(1), y(1), sprintf('(%.3f,%.3f)',x(1),y(1)), ...
'Color',[0.2 0.2 0.2], 'FontSize',8, ...
'HorizontalAlignment','left', 'VerticalAlignment','top');
%# infinite loop
i = 1; %# index
while true
%# update point & text
set(hLine, 'XData',x(i), 'YData',y(i))
set(hTxt, 'Position',[x(i) y(i)], ...
'String',sprintf('(%.3f,%.3f)',[x(i) y(i)]))
drawnow %# force refresh
%#pause(DELAY) %# slow down animation
i = rem(i+1,numPoints)+1; %# circular increment
if ~ishandle(hLine), break; end %# in case you close the figure
end
but I need to change the velocity of the marker. I've tried changing the value of DELAY, but it didn't work. The point is that I can't change the numPoints (size of the function), so I don't know hot to do it.
Any ideas?
Thanks!
Just uncomment the pause(DELAY) in the infinite loop. Change DELAY to a suitable value

how to draw three graphics on the same figure?

That's how I draw two graphics (thanks for guys who helped me to do that):
clear
logsFolder = 'C:\logs\';
stocks = {'log'};
for stock = stocks
filename = [logsFolder stock{1} '.log'];
fLog = fopen(filename);
data = textscan(fLog, '%f:%f:%f:%f %f %f %f');
fclose(fLog);
% hh:min:sec:millisec
secvec = [60*60 60 1 1e-3];
x = [data{1:4}] * secvec';
y = data{5};
yPrice = data{6};
xindays = x / (24*60*60);
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
set(AX(1),'xtick',[]);
lo1 = min(y);
hi1 = max(y);
lo2 = min(yPrice);
hi2 = max(yPrice);
if (hi2/lo2 > hi1/lo1)
ylim(AX(1),[lo1 hi2/lo2 * lo1]);
ylim(AX(2),[lo2 hi2]);
else
ylim(AX(1),[lo1 hi1]);
ylim(AX(2),[lo2 hi1/lo1 * lo2]);
end
ticklabelformat(AX(2),'y','%g')
ticklabelformat(AX(2),'x',{#tick2datestr,'x','HH:MM:SS'})
title(stock);
% iNeedToDrawThat = data{7}
end
Input file example is available here As you can see my file contains the last column which I also want to display. The range should be from 0 (at the bottom of figure) to the maximum value (at the up of the graph). So I need to draw three graphics somehow. It's ok to omit axis with labels for the third graph as I already have two axis and I have no place to add third one. However it's ok to "overlap" two axis if possible.
I have no idea how to do that so I'm looking for your help.
I've tried that but it doesn't work:
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
I have already mentioned a similar question in the comments, it should give you plenty of ideas...
Anyway, I've put together a solution to plot multiple y axes. Right now the code is a bit involved, but it should be possible to refactor a re-usable function out of it (like the addaxis function on the File Exchange).
The idea is to first plot each curve in a separate axis (all superimposed), and make them transparent (except the bottom one). Next we create copies of this set of axes and shift them along the x-direction. We also make those copies transparent, but now we can show the tick-marks along the y-axis of each. Finally we give them correct z-order, and link the x and y limits so that we can use the pan and zoom functionality.
%# read and parse data from file
fid = fopen('log.log','rt');
C = textscan(fid, '%s %f %f %f', 'CollectOutput',true);
fclose(fid);
dt = datenum(C{1}, 'HH:MM:SS:FFF');
data = C{2};
NUM = size(data,2);
%# create a wider figure
hFig = figure('Position',get(0,'DefaultFigurePosition').*[1 1 1.7 1]);
%# some properties
clr = lines(NUM);
bgClr = get(0,'DefaultFigureColor');
pos = get(0,'DefaultAxesPosition');
pp = 0.1; % shift in normalized units: pos(1)
%# create plot axes (make axis invisible)
hAx = zeros(NUM,1);
for i=1:NUM
hAx(i) = axes('Parent',hFig, 'Color','none', ...
'XColor',bgClr, 'YColor',bgClr, ...
'Units','normalized', 'Position',pos+[(NUM-1)*pp 0 -(NUM-1)*pp 0]);
line(dt, data(:,i), 'Color',clr(i,:), 'Parent',hAx(i))
end
axis(hAx, 'tight') %# tight x/y limits
%# create shifted copies of axes to show y-ticks
hAxx = zeros(size(hAx));
for i=1:NUM
hAxx(i) = copyobj(hAx(i), hFig);
delete(get(hAxx(i),'Children')); %# keep only axis
set(hAxx(i), 'YColor',clr(i,:), ...
'Units','normalized', 'Position',pos+[(NUM-i)*pp 0 -(NUM-i)*pp 0]);
ylabel(hAxx(i), sprintf('Axis %d',i))
end
xlabel(hAxx(1), 'datetime')
title(hAxx(1), 'Log')
datetick(hAxx(1), 'x', 'HH:MM', 'keeplimits')
%# set 1st axis copy as current axis
set(hFig, 'CurrentAxes',hAxx(1))
%# adjust ticks of axes
set(hAx(1), 'Color','w') %# give white bg to 1st axis
set(hAxx(1), 'XColor','k') %# show xticks of 1st axis copy
set(hAxx(2:end), 'XTick',[], 'XTickLabel',[])
set(hAx, 'XTick',[], 'XTickLabel',[], 'YTick',[], 'YTickLabel',[])
%# fix z-order
for i=3:-1:1, uistack(hAxx(i),'top'), end
uistack(hAx(1), 'bottom')
%# link x/y limits so that panning/zooming works
lh = cell(NUM+1,1);
for i=1:NUM
lh{i} = linkprop([hAxx(i);hAx(i)], 'YLim');
end
lh{end} = linkprop([hAxx;hAx], 'XLim');
The result:
The panning/zooming is a bit funny, you have to initiate them by starting to drag from the side (the shifted colored axes). This is because the first one (corresponding to the blue line) is the one on top, thus catches all mouse clicks.
Note: I see you are using a custom function ticklabelformat, which I haven't tested in combination with the above code. I will leave that part to you..
HTH
sample use of hold on
figure;
plot(x1,y1);
hold on
plot(x2,y2);
plot(x3,y3);
hold off
do "figure" and "hold on" only once outside the loop. then plot all the graphs you need
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
if you do it the way you suggested using hold on, i.e. use plotyy() first then the axes won't adjust so if you 3rd series is out of the range of your first set of axes then it won't appear. Try just flipping them and see if that produces a result?
volume = data{7};
plot(xindays, volume);
hold on;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
This way the axes should adjust
For example:
t = 1:10;
x = t*2;
y = t*-2;
z = x + 1000;
Now compare
plot(t,z, 'r')
hold on
plotyy(t,x, t,y)
to
plotyy(t,x, t,y)
hold on
plot(t,z, 'r')

Creating a point moving along a graph in MATLAB

I am looking to create a simple log(x) graph within MATLAB in which the model shows the point moving along the curve with time.
The overall aim is to have two of these graphs alongside one another and to apply an algorithm to them. I am really unsure where to start here.
I am relatively new at MATLAB coding so any help would be very useful!
Thanks
Luke
Here is a variation on #Jacob's solution. Instead of redrawing everything at each frame (clf) we simply update the point's location:
%# control animation speed
DELAY = 0.01;
numPoints = 600;
%# create data
x = linspace(0,10,numPoints);
y = log(x);
%# plot graph
figure('DoubleBuffer','on') %# no flickering
plot(x,y, 'LineWidth',2), grid on
xlabel('x'), ylabel('y'), title('y = log(x)')
%# create moving point + coords text
hLine = line('XData',x(1), 'YData',y(1), 'Color','r', ...
'Marker','o', 'MarkerSize',6, 'LineWidth',2);
hTxt = text(x(1), y(1), sprintf('(%.3f,%.3f)',x(1),y(1)), ...
'Color',[0.2 0.2 0.2], 'FontSize',8, ...
'HorizontalAlignment','left', 'VerticalAlignment','top');
%# infinite loop
i = 1; %# index
while true
%# update point & text
set(hLine, 'XData',x(i), 'YData',y(i))
set(hTxt, 'Position',[x(i) y(i)], ...
'String',sprintf('(%.3f,%.3f)',[x(i) y(i)]))
drawnow %# force refresh
%#pause(DELAY) %# slow down animation
i = rem(i+1,numPoints)+1; %# circular increment
if ~ishandle(hLine), break; end %# in case you close the figure
end
A simple solution is:
x = 1:100;
y = log(x);
DELAY = 0.05;
for i = 1:numel(x)
clf;
plot(x,y);
hold on;
plot(x(i),y(i),'r*');
pause(DELAY);
end
You may want to have a look at the COMET function, which will make an animation of the curve.
For example (using the same numbers as #Jacob)
x = 1:100;
y = log(x);
comet(x,y)
If you want to show the point moving on the line (not 'drawing' it), you simply plot the line before
x = 1:100;
y = log(x);
plot(x,y,'r')
hold on %# to keep the previous plot
comet(x,y,0) %# 0 hides the green tail
a little more complex solution along the same lines as #Jacob. Here I add some optimization using handle graphics and a MATLAB movie object for playback.
x=1:100;
y=log(x);
figure
plot(x,y);
hold on; % hold on so that the figure is not cleared
h=plot(x(1),y(1),'r*'); % plot the first point
DELAY=.05;
for i=1:length(x)
set(h,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
M(i)=getframe(gcf);
pause(DELAY)
end
%% Play the movie back
% create figure and axes for playback
figure
hh=axes;
set(hh,'units','normalized','pos',[0 0 1 1]);
axis off
movie(M) % play the movie created in the first part
solution can be this way
x = .01:.01:3;
comet(x,log(x))