What are the possibilities to create videos in Matlab? I was searching and found mainly 3 toolboxes that work in this field, image processing, image acquisition and control vision... but how can I do it without them, just to create the video from scratch? I'm interested in various approaches to have an overview, but I was unable to find any decent tutorial or consistent source of info on the internet.
Thanks for the help!
Here are some of the different ways to create movies in (core) MATLAB.
MOVIE2AVI
(deprecated, use VIDEOWRITER instead)
%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z); axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
%# preallocate
nFrames = 20;
mov(1:nFrames) = struct('cdata',[], 'colormap',[]);
%# create movie
for k=1:nFrames
surf(sin(2*pi*k/20)*Z, Z)
mov(k) = getframe(gca);
end
close(gcf)
%# save as AVI file, and open it using system video player
movie2avi(mov, 'myPeaks1.avi', 'compression','None', 'fps',10);
winopen('myPeaks1.avi')
AVIFILE
(deprecated, use VIDEOWRITER instead)
%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z); axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
%# create AVI object
nFrames = 20;
aviobj = avifile('myPeaks2.avi', 'fps',10);
%# create movie
for k=1:nFrames
surf(sin(2*pi*k/20)*Z, Z)
aviobj = addframe(aviobj, getframe(gca));
end
close(gcf)
%# save as AVI file, and open it using system video player
aviobj = close(aviobj);
winopen('myPeaks2.avi')
VIDEOWRITER
%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z); axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
%# create AVI object
nFrames = 20;
vidObj = VideoWriter('myPeaks3.avi');
vidObj.Quality = 100;
vidObj.FrameRate = 10;
open(vidObj);
%# create movie
for k=1:nFrames
surf(sin(2*pi*k/20)*Z, Z)
writeVideo(vidObj, getframe(gca));
end
close(gcf)
%# save as AVI file, and open it using system video player
close(vidObj);
winopen('myPeaks3.avi')
IMWRITE
(technically not a movie, but an animated GIF image)
%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z); axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
%# preallocate
nFrames = 20;
f = getframe(gca);
[f,map] = rgb2ind(f.cdata, 256, 'nodither');
mov = repmat(f, [1 1 1 nFrames]);
%# create movie
for k=1:nFrames
surf(sin(2*pi*k/20)*Z, Z)
f = getframe(gca);
mov(:,:,1,k) = rgb2ind(f.cdata, map, 'nodither');
end
close(gcf)
%# create GIF and open
imwrite(mov, map, 'myPeaks4.gif', 'DelayTime',0, 'LoopCount',inf)
winopen('myPeaks4.gif')
There is http://www.mathworks.de/help/techdoc/ref/videowriterclass.html
My approach is to print the single frames/figures to png files using the print function giving them filenames like 1.png, 2.png, ... and then I use the free FFMPEG converter to make a video.
ffmpeg -r 20 -i %d.png foo.avi
This allows for a lot of finetuning, when it comes to the parameters of the conversion (bitrate, codec, geometry etc.).
Matlab has a built in 'movie' command to play movies. I find it pretty easy to work with. I've used it on plots to show changes in time, as well as individual images to make a real movie.
http://www.mathworks.com/help/techdoc/ref/movie.html
I believe the general procedure is:
for ii=1:100
plot(something(ii))
F = getframe;
end
movie(F)
To save a movie, you can use a similar procedure as above, but use the
writeVideo
command.
http://www.mathworks.com/help/techdoc/ref/videowriterclass.html
QTWriter
To export QuickTime movies, my own QTWriter is available: http://horchler.github.io/QTWriter/. It works very similarly to Matlab's VideoWriter class, but has both lossy and lossless still image codecs (compression formats) that work well with typical data in Matlab plots (i.e., no inter-frame compression). Notably it also supports alpha channel transparency ('Photo PNG' codec), looping (two kinds), and continuously variable frame rates. QTWriter is written as a single Matlab class file and should work on all platforms, but I have not tested it on Windows.
Here's some example code illustrating how a simple looping, variable frame-rate QuickTime movie can be generated:
% Prepare new movie file using the default PNG compression
movObj = QTWriter('peaks.mov');
% Create an animation
hf = figure; Z = peaks; surfc(Z); frames = 100;
axis tight; set(hf,'DoubleBuffer','on');
set(gca,'nextplot','replacechildren');
% Animate plot and write movie
for k = 0:frames
hs = surfc(sin(2*pi*k/frames)*Z,Z);
set(hs,'FaceColor','interp','FaceLighting','phong');
light('Position',[0 0 4]);
movObj.FrameRate = k; % Vary the frame-rate
writeMovie(movObj,getframe(hf)); % Write each frame to the file
end
movObj.Loop = 'backandforth'; % Set palindromic looping flag
close(movObj); % Finish writing movie and close file
The output movie, another more complex demo, and further details are available on the project website. QTWriter is open source (BSD license) and the code repository is hosted on GitHub.
Related
I create a video of my plot series as below:
clc;
clear;
close all;
r0=1;
theta=0:0.01:2*pi;
a=0.2;
psi=0;
writerObj = VideoWriter('shapes.mp4'); % Name it.
writerObj.FrameRate = 1; % How many frames per second.
open(writerObj);
for k=1:3
pause(1);
r=r0+a*sin(k*theta+psi)+a*sin((k+1)*theta+psi)+a*sin((k+2)*theta+psi)+a*sin((k+3)*theta+0.8*pi);
figure();
x=r.*cos(theta);
y=r.*sin(theta);
plot(x,y);
axis([-2 2 -2 2]);
% axis equal
grid on
%%%%%%%%% Finding Area %%%%%%%%%%%%%
A = polyarea(x,y);
title({'line1',['Area = ' num2str(A)]})
% title(['Area = ' num2str(A)]);
set(gcf,'renderer','zbuffer');
view(2)
frame = getframe(gcf);
writeVideo(writerObj, frame);
close all
end
close(writerObj); % Saves the movie.
But when you watch the video it has poor quality (by poor quality I mean, the quality when you export matlab plots in a jpeg format for instance).
For matlab plots people usually export in .eps format so that they save high quality plots and use them in their report or presentations.
What is an equivalent way (.eps in plot saving) for video making in matlab to preserve a good quality.
I am trying to test the function movie2avi using simple codes in R2014a as follows:
clear; close all;
figure;
Z = peaks;
surf(Z);
axis tight manual;
ax = gca;
ax.NextPlot = 'replaceChildren';
loops = 40;
F(loops) = struct('cdata',[],'colormap',[]);
for j = 1:loops
X = sin(j*pi/10)*Z;
surf(X,Z);
drawnow;
F(j) = getframe(gcf);
end
movie(F);
movie2avi(F, 'myPeaks.avi', 'compression', 'None');
It seems the movie(F) works well but the avi file created contains the toolbar and background instead of just showing the graph. Also the avi file just show stationary picture as follow:
Using quicktime to open it would produce same result:
https://www.dropbox.com/s/fd8vw7jvll5xkpw/b.png?dl=0
There is also a warning:
Warning: Struct field assignment overwrites a value with class "double". See MATLAB R14SP2 Release Notes, Assigning Nonstructure
Variables As Structures Displays Warning, for details.
Please help. Thanks.
Have you tried
F(j) = getframe(gca); %// Gets the current axis
This will capture the axis rather than the entire figure window.
I have a sequence of MATLAB figures which I want to convert to a video. The figures are composed of 2 subplots, such that each subplot contains an imshow with 2 different plots (red and green) overlayed on it, like the following:
How do I get an image of all the data contained inside each figure, so that next I can convert the sequence of images to a video with VideoWriter?
The key is:
im = frame2im(getframe(h));
Where h is the handle to your plot or axis
You can also pass an optional argument 'rect' to getframe to specify the area to capture.
Here is an example from the MathWorks on how to use getframe in a loop to record the frames. For more information type doc getframe
Z = peaks;
surf(Z)
axis tight manual
ax = gca;
ax.NextPlot = 'replaceChildren';
loops = 40;
F(loops) = struct('cdata',[],'colormap',[]);
for j = 1:loops
X = sin(j*pi/10)*Z;
surf(X,Z)
drawnow
F(j) = getframe(gcf);
end
% Play back the movie two times.
fig = figure;
movie(fig,F,2)
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:
** 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.