29

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!

EBH
  • 10,350
  • 3
  • 34
  • 59
beginh
  • 1,133
  • 3
  • 26
  • 36

4 Answers4

50

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')
Lucademicus
  • 383
  • 3
  • 9
Amro
  • 123,847
  • 25
  • 243
  • 454
  • thanks for a nice overview! what about preventing the created figures to pop up? The mainstream approach so presetting as here: set(gcf,'Visible', 'off'); seems to be not a case here. While put around 'figure' or 'AVI' creation, does nothing. While in a 'k' loop, results in blinking. Is there any other approach? – beginh Jun 25 '12 at 02:21
  • 2
    @beginh: Read this: [Render MATLAB figure in memory](http://stackoverflow.com/q/4137628/97160) – Amro Jun 25 '12 at 05:29
  • How can you replace the `surf` command in `surf(sin(...,Z)` by a `imshow`? I do not understand why you cannot use `imshow` inside your for -loop, like `imshow(signal(:,k,:))`. – Léo Léopold Hertz 준영 Apr 28 '15 at 22:17
  • @Masi: You should be able to do that, no problem... Maybe throw in a `drawnow` call inside the loop to make sure the graphics pipeline is flushed. – Amro Apr 28 '15 at 22:30
  • @Amro Thank you for your answer! Something else in Matlab which I do not understand. I made a new question here http://stackoverflow.com/q/29936706/54964 – Léo Léopold Hertz 준영 Apr 29 '15 at 07:14
12

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.).

Herr von Wurst
  • 2,571
  • 5
  • 32
  • 53
7

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

zachd1_618
  • 4,210
  • 6
  • 34
  • 47
5

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.

Community
  • 1
  • 1
horchler
  • 18,384
  • 4
  • 37
  • 73
  • 1
    +1 nice project! thank you for sharing. You should mention the fact that you are not using any external codec or library, instead writing the QuickTime format directly. – Amro Aug 23 '13 at 01:49
  • btw, the pendulum demo is not saving the video correctly (tested on Windows 8). Perhaps I'll file a bug once I had a closer look.. – Amro Aug 23 '13 at 01:58
  • @Amro: I can't test or fix anything on Windows so unless it's something cross-platform, I'd need a specific bug report. Does the simpler demo work? It may also be a version thing -when I get a chance I'll check to see that all still works on R2013a. – horchler Aug 23 '13 at 15:13
  • 1
    So I ran into this problem again making my own GIF animation, and I tracked down the problem this time. It turns out that "opengl renderer" in combination with `getframe` inside a loop is the issue. I fixed it by temporarily switching to `opengl software` mode. Of course if you don't need specifically need it (if you are not using transparency for example), just change it to one of the other renderers like `zbuffer` which works perfectly. fwiw I didnt have this problem on my old WinXP machine also running R2013a, it must be a Win7/8 problem... Sorry I took so long to get back to you :) – Amro Sep 05 '13 at 23:38
  • Thanks for the heads-up @Amro. I appreciate it. So I assume that you would have seen the same issues if you had used `VideoWriter`? I've definitely seen mention of various OpenGL bugs on Windows Matlab (there are plenty of others on OS X). I'll see about adjusting my demo and at least make mention of the issue. Proper video creation software should explain how to go about actually creating the video after all. – horchler Sep 05 '13 at 23:51
  • 1
    Regarding `getframe`, I have worked on a alternative/replacement for it using `hardcopy`, but I had trouble matching the pixels up one-to-one in tricky cases when only an axis is grabbed (I want identical output). And even `hardcopy` [has issues](http://www.mathworks.com/matlabcentral/answers/41367) and I imagine there might be issues with the different renderers and with `opengl software` mode. – horchler Sep 05 '13 at 23:58
  • the issue has nothing to do with `VideoWriter` or your class `QTWriter`, it is a bug in `getframe` when used with OpenGL renderer, at least on some systems. I was getting only the first frame for the entire video with the whole figure wrongly transparent. I have seen others mention the same problem: http://www.mathworks.com/matlabcentral/newsreader/view_thread/321081, http://www.mathworks.com/matlabcentral/newsreader/view_thread/313716, http://www.mathworks.com/matlabcentral/newsreader/view_thread/291912 – Amro Sep 06 '13 at 00:03
  • This bug with `getframe` is officially recognized: http://www.mathworks.com/support/bugreports/384622 (although it should probably say that Windows Vista and up are affected). As for `hardcopy` is it undocumented, so we can't complain about it :) It would be interesting to see how the newer HG2 system behaves with all the above methods.. – Amro Sep 06 '13 at 00:19