MATLAB Create Movie - matlab

** I figured out how to create the movie so the code has been changed to reflect the correct one in case it is useful for anyone in the future.
This script creates a movie of a eqdconic map and saves it in avi format. The movie will run through 1255 frames. It also plots a dot at a certain point on the image, places a changing title on the movie to show what month is being run through, and has a colorbar on the right side.
Some of the variables used were created elsewhere. The code for creating them has been left out to condense the code (and since they will not be useful for anyone else other than myself).
% Create movie
nFrames = 34; % Number of frames
for k = 1:nFrames
% Eqdconic script
% Define figure and axes
fg1 = figure(1);
axesm('MapProjection','eqdconic', 'MapParallels', [], 'MapLatLimit',[-80 -59],'MapLonLimit',[190 251]) % 60-70S and 120-160W
framem on; gridm on; mlabel on; plabel on; hold all;
% Plot data
frame = dataPoint_movie(:,:,k);
image = contourfm(lat,lon,frame, 'LineStyle', 'none');
hold on
% Plot dot
plotm(-66.75,224,'k.','MarkerSize',30);
% Colorbar
caxis([0 100]);
h = colorbar;
ylabel(h,'Percent');
% Title: Days 1:1258 inclusive. 20100101 to 20130611
date = datenum(2009, 12, 31) + k; % Convert t into serial numbers
str = datestr(date, 'mmm yyyy'); % Show in the format mmm yyyy so title changes only once a month
title(str);
mov(k) = getframe(gcf); % gca would give only the image. gcf places the title and other attributes on the movie.
end
close(gcf)
% % Save as AVI file
movie2avi(mov, 'SeaIceConcentration.avi', 'compression', 'none', 'fps', 2);

I prefer to export my movies from matlab to a .avi file.
before the for loop, initialize your movie:
vidObj = VideoWriter('Movie.avi');
vidObj.FrameRate=23;
open(vidObj);
then get your frame in the for loop:
A = getframe;
writeVideo(vidObj,A);
(note, i'm not saving each frame in a matrix, so A is an MxN matrix)
Then write out your movie after the for loop
close(vidObj);
The movie will be in your current working directory. you can open using quicktime or some other avi player. To change the frame rate (speed) of your movie, edit the second line of code. 23 fps is a good smooth movie framerate.

Check the consistency of the statements:
A = dataPoint(:,:,t);
and
A(i) = getframe;
A is overwritten all the time So that you will at best get the last frame.

Related

Although I used 'drawnow' and 'hold on', last plot still appears in animation - MATLAB

I read a lot of answers here, but for some reason my animation still doesn't work as expected.
The axis range should vary from frame to frame. The 'Hurricane Center' caption should remain in the center all the time, but the captions from the previous frames must be erased. Also, I'm afraid that some of the data from previous parts remain.
I used hold on and draw now but it still happens.
The animation can be seen here:
Code:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open()
hold on
for i=1:length(relevant(1,1,:))
if isempty(relevant) == 0
title('Lightning around Hurricane Jerry')
grid on
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius])
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius])
ylabel('latitude')
xlabel('longitude')
text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
scatter(relevant(:,3,i),relevant(:,2,i),'.');
drawnow
pause(0.1);
v.writeVideo(getframe(fig));
end
end
v.close()
The best of the two worlds:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open()
hold on;
for i=1:length(relevant(1,1,:))
if ~isempty(relevant) % Corrected
if i == 1
% Prepare first plot and save handles of graphical objects
ht = text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
hold on;
hs = scatter(relevant(:,3,i),relevant(:,2,i),'.');
ylabel('latitude')
xlabel('longitude')
title('Lightning around Hurricane Jerry')
grid on
else
% Update graphical objects
set(ht, 'position', [Interp_Jerry(i,3), Interp_Jerry(i,2)]);
set(hs, 'XData', relevant(:,3,i) , 'YData' , relevant(:,2,i));
end
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius])
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius])
drawnow
pause(0.1);
v.writeVideo(getframe(fig));
end
end
v.close()
Instead of writing the text every time, just modify its position in the loop. Create a text object out side of the loop
t = text(position1, position2, txt);
in the loop change the position and if necessary the text
set(t, 'position', [new_position1, new_position2]);
If you don't want the previous data to remain, then you shouldn't use hold on... I think you should revise your code as follows:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open();
fg = figure();
% Do not hold on, so that data is not retained frame-to-frame
for i=1:length(relevant(1,1,:))
% You don't need to test if 'relevant' is empty, since you're looping to its length!
% New plot
scatter(relevant(:,3,i),relevant(:,2,i),'.');
% Customise plot (labels / axes / text / ...)
title('Lightning around Hurricane Jerry')
ylabel('latitude')
xlabel('longitude')
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius]);
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius]);
text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
grid on;
drawnow;
% You don't need to pause whilst plotting, you already set the video framerate.
% pause(0.1);
v.writeVideo(getframe(fg));
end
v.close()

Animating a line plot and saving it as an avi movie in Matlab

I am trying to animate a line plot from a saved vector and save it as an avi file in Matlab. The code below can do it, but it does not capture the axis (numbers on the axis etc.) and does not show the legend. How can I fix this issue? Attached a screenshot from the movie.
vidObj = VideoWriter('OneWeekJune.avi');
vidObj.Quality = 100;
open(vidObj);
h = animatedline;
axis([min,max,ymin,ymax])
xlabel('Time (minute)')
ylabel('Demand')
legend('Demand in June')
grid on
x = 1:7*1440;
y = [Day1 Day2 Day3 Day4 Day5 Day6 Day7];
for k = 1:10:length(x)
addpoints(h,x(k),y(k));
drawnow
currFrame = getframe;
writeVideo(vidObj,currFrame);
end
close(vidObj);
Do currFrame = getframe(gcf);
https://www.mathworks.com/help/matlab/ref/getframe.html
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.

MATLAB enlarge 3D plot without enlarging colorbar

Is it possible to enlarge a 3D patch without altering the size of the colorbar? My original picture is like this one:
I just want to enlarge the block in the middle of the figure keeping the colorbar unchanged. I used zoom(1.9) before, it is good but since I need to use a for loop to read sequential files to plot different graphs and make video, the graph became larger and larger so it seems that I need another method to enlarge the plot.
Update: my codes
set(gcf,'Renderer','zbuffer'); %eliminate unnecessary background and prevent stationary video - Important!
vid = VideoWriter('afation.avi'); %Create a avi file
vid.Quality = 100;
vid.FrameRate = 15;
open(vid); %Open the avi file so that films can be put into it later on
for ii=FirstFile:FileInterval:LastFile
fid = fopen(filename,'r');
datacell = textscan(fid, '%f%f%f%f%f%f%f%f'); %There are 8 columns to be read so there are 8 %f
fclose(fid);
all_data = cell2mat(datacell); %converted into a matrix containing all the dis. density info. for every simulation cell
M=zeros(NumBoxX,NumBoxY,NumBoxZ); %create a matrix of 50x50x5,representing array of simulation cells
% % the following loops assign the dislocation density from all_data to M
for i=1:NumBoxX
for j=1:NumBoxY
for k=1:NumBoxZ
num=k+NumBoxZ*(j-1)+NumBoxZ*NumBoxY*(i-1);
M(i,j,k)=all_data(num,ValCol); %the ValCol column of all_data is dislocation density
end
end
end
indPatch=1:numel(M);
[F,V,C]=ind2patch(indPatch,M,'v'); %Call the function ind2patch in order to plot 3D cube with color
title('AA in different cells','fontsize',20);%set title \sigma_{xx}
xlabel('y','fontsize',20);ylabel('x','fontsize',20); zlabel('z','fontsize',20); hold on;
set(get(gca,'xlabel'),'Position',[5 -50 30]); %set position of axis label
set(get(gca,'ylabel'),'Position',[5 50 -15]);
set(get(gca,'zlabel'),'Position',[64 190 -60]);
patch('Faces',F,'Vertices',V,'FaceColor','flat','CData',C,'EdgeColor','k','FaceAlpha',0.5);
axis equal; view(3); axis tight; axis vis3d; grid off;
colormap(cMap);
caxis([MinDis MaxDis]); %set the range of the colorbar %caxis([min(M(:)) max(M(:))]); %range of the colorbar according to one file only
cb = colorbar; % create the colorbar
set(get(cb,'title'),'string','aaty(m^{-2})','fontsize',20);
lbpos = get(cb,'title'); % get the handle of the colorbar title
set(lbpos,'units','normalized','position',[0,1.04]);
MyAxes=gca;
set(MyAxes,'Units','Normalized','position',[0.05,0.1,0.8,0.8]);
zoom(1.9);
writeVideo(vid, getframe(gcf)); %get the picture and put in the avi file with the handle "vid"
end
close(vid); %close the avi file after putting all the films into it
% winopen('ggggon.avi'); %play the movie
I put the zoom in the for loop because I need to enlarge the picture one by one and put them into my avi file to make movie.

Creating a video from a set of 3D plots

I used a function called ind2patch to make a 3D block which contains a number of smaller blocks in 3 dimensions. Each small block has a value that is represented by a color. A typical plot is like this one:
Now I would like to show the evolution of values (i.e. the color) with time of these small blocks using a video. I have data at different moments but I only know how to plot the graphs at different time by reading different files. Is there a way to combine the plots to a video or directly plot the graphs in the form of video?
Here is my code:
clear; close all; clc;
fig = figure(1);
set (fig, 'Units', 'normalized', 'Position', [0,0,1,1]);
fig_color='w'; fig_colordef='white';
cMap=jet(256);
faceAlpha1=1;
faceAlpha2=0.65;
edgeColor1='none';
edgeColor2='none';
NumBoxX=100;%box number in x direction
NumBoxY=100;%box number in y direction
NumBoxZ=5;%box number in z direction
fid = fopen('rho 20950.dat','r');
datacell = textscan(fid, '%f%f%f%f%f%f%f%f');
fclose(fid);
all_data = cell2mat(datacell);
M=zeros(NumBoxX,NumBoxY,NumBoxZ);
for i=1:NumBoxX
for j=1:NumBoxY
for k=1:NumBoxZ
num=k+NumBoxZ*(j-1)+NumBoxZ*NumBoxY*(i-1);
M(i,j,k)=all_data(num,4);
end
end
end
indPatch=1:numel(M);
[F,V,C]=ind2patch(indPatch,M,'v');
title('\sigma_{xy} in different cells','fontsize',20);
xlabel('y','fontsize',20);ylabel('x','fontsize',20); zlabel('z','fontsize',20); hold on;
set(get(gca,'xlabel'),'Position',[5 -50 30]);
set(get(gca,'ylabel'),'Position',[5 50 -15]);
set(get(gca,'zlabel'),'Position',[64 190 -60]);
patch('Faces',F,'Vertices',V,'FaceColor','flat','CData',C,'EdgeColor','k','FaceAlpha',0.5);
axis equal; view(3); axis tight; axis vis3d; grid off;
colormap(cMap); caxis([min(M(:)) max(M(:))]);
cb = colorbar;
set(get(cb,'title'),'string','Stress (MPa)','fontsize',20);
lbpos = get(cb,'title'); % get the handle of the colorbar title
%set(lbpos,'Units','data');% change Units to data
%pos = get (lbpos,'position'); % get position of the colorbar title
set(lbpos,'units','normalized','position',[0,1.04]);
MyAxes=gca;
set(MyAxes,'Units','Normalized','position',[0.05,0.1,0.8,0.8]);
zoom(1.85);
You could do something like this:
Loop through each patch and grab an image of it.
Insert the images into a matrix
Convert the image matrix into a movie using immovie
% // Create a matrix to hold your images
A = zeros(row,col,numOfColours, numOfFrames);
where row is the number of rows and col is the number of columns in one image.
Loop through your patches and create a video of the individual images.
for n=1:numOfPatches
imshow(patches(:,:,n)) % // display the image
frame = getframe(gcf) % // get the current figure window
im = frame2im(frame); % // convert it to an image
A(:,:,1:3,n) = im; % // Insert the image into the matrix
end
The you can use immovie to convert it to a movie
mov = immovie(RGB);
movie(mov); % // play the movie

Why "lighting phong" is a must in order to create aminated GIF/movie successfully?

I have the following Matlab code, which is used for gif and avi animation creation;
Matlab imwrite is used to create frames of the gif; but I found lighting command is critical in order to successfully obtain the animated gif.
close all
clear all
clc; %
nFrames = 50;
% Preallocate movie structure.
mov(1:nFrames) = struct('cdata', [],'colormap', []);
% Create movie.
figure('color','white');
Z = peaks(150); surf(Z,Z,'edgecolor','none');
view(3);
axis vis3d tight equal off;
v = axis;
%
for k = 1:nFrames
clf;
surf(1.5*sin(2*pi*k/20)*Z,Z,'edgecolor','none');
axis(v);
axis off
camlight;
lighting phong
mov(k) = getframe;
[Inx,cmap]=rgb2ind(mov(k).cdata,256);
if k==1
imwrite(Inx,cmap,'testoutx.gif','gif','DelayTime',0.25,'LoopCount',Inf) %
else
imwrite(Inx,cmap,'testoutx.gif','gif','WriteMode','append','DelayTime',0.25) %
end
end
% Create AVI file.
movie2avi(mov, 'myPeaks.avi', 'compression', 'None');
When I comment "lighting phong", then the obtained gif is static, not animated. It seems only one of the frames is stored. I also tried to use drawnow before each getframe sentence, but that did not work. Why? How can I solve the problem without using lighting?
The desired gif (obtained from the code above):
The undesired gif with "lighting phong" commented: