3

I am trying to create a movie from my MATLAB plot. When I call getframe, it "usually" captures the plot image, but sometimes if there is something else active on the screen (which is normal if I continue to use the computer) it captures whatever window is active. Is there another way to grab the image of the active figure?

e.g.

fig = figure;
aviobj = avifile('sample.avi','compression','None');
for i=1:t
    clf(fig);
    plot(...); % some arbitrary plotting
    hold on;
    plot(...); % some other arbitrary plotting
    axis([0 50 0 50]);
    aviobj = addframe(aviobj, getframe(fig));
end
aviobj = close(aviobj);
Amro
  • 123,847
  • 25
  • 243
  • 454
paul simmons
  • 5,568
  • 13
  • 51
  • 78
  • Is this on Windows? Are you doing any sort of complicated plotting, like transparent patches or other detailed graphics that might be using OpenGL rendering? – gnovice Dec 19 '11 at 18:22
  • yes, it's windows and no, no complicated graphics. is it strange that i am the only one seeing this? i also ran into same problem in two different windows boxes but that time it was ok to leave the computers running and go away, so did not care much – paul simmons Dec 19 '11 at 18:49
  • related question: [Render MATLAB figure in memory](http://stackoverflow.com/questions/4137628/render-matlab-figure-in-memory) – Amro Jun 29 '12 at 05:59

6 Answers6

4

OK, found the solution; instead of

aviobj = addframe(aviobj, getframe(fig));

sending the figure handle directly to addframe is enough:

aviobj = addframe(aviobj, fig);
paul simmons
  • 5,568
  • 13
  • 51
  • 78
  • It's good that you found a workaround. I just wonder what was causing the problem in the first place. Perhaps a bug report is in order. – gnovice Dec 19 '11 at 19:14
3

The Matlab people are apparently phasing out the avifile and addframe functions in future releases, replacing them with VideoWriter and writeVideo respectively. Unfortunately, this means that the accepted answer will no longer work, since writeVideo doesn't accept the figure handle as the argument.

I've played around with it a bit, and for future reference, the same thing can be accomplished using the undocumented hardcopy function. The following code works perfectly for me, with the added benefit of not even having a plot window pop up, so it does everything completely in the background:

fig = figure('Visible','off');
set(fig,'PaperPositionMode','auto');
writerobj = VideoWriter('sample.avi','Uncompressed AVI');
open(writerobj);

for i=1:t
    clf(fig);
    plot(...); % some arbitrary plotting
    hold on;
    plot(...); % some other arbitrary plotting
    axis([0 50 0 50]);
    figinfo = hardcopy(fig,'-dzbuffer','-r0');
    writeVideo(writerobj, im2frame(figinfo));
end

close(writerobj);
A Blue Shoe
  • 157
  • 2
  • 11
1

You can pass the handle of the desired figure or axis to GETFRAME to ensure that it doesn't capture another window.

gnovice
  • 125,304
  • 15
  • 256
  • 359
1

I may depend on the renderer you're using. If it's 'painters', then you should be OK, but if it's anything else, such as 'OpenGL', then I think it has to get the frame data from the graphics card, which means that if you have something overlapping the window, then that may end up in the output of getframe.

Nzbuu
  • 5,241
  • 1
  • 29
  • 51
  • FYI, set(gcf, 'Renderer', 'painters'); aviobj = addframe(aviobj, getframe(gcf)); did not work either... – paul simmons Dec 19 '11 at 18:48
  • @paulsimmons: Are you using `gcf` or `fig` when passing the handle? It's `fig` in the question but `gcf` in your comment. – gnovice Dec 19 '11 at 19:01
  • well, gcf actually is a function to "Get the Current Figure" and it returns fig in my case – paul simmons Dec 19 '11 at 19:04
  • @paulsimmons: Yes, but if for whatever reason another figure besides `fig` becomes the current figure while making your movie, then `gcf` will refer to that one instead. – gnovice Dec 19 '11 at 19:08
0

As someone has already stated you don't have to use getframe, however if you insist on using it you can use

set(fig,'Renderer','zbuffer')

and this should fix your issue.

erichlf
  • 119
  • 3
  • I just tried this and it did not work. I am on R2010b on Mac OSX. The figure window is behind the dock (like everything else on my screen) and the dock appeared in my video. – Stretch Mar 16 '14 at 01:52
0

If you use getframe in many subplots, try to add at the end: I think the get frame works fine it just the rendering a bit was unpositioned.

 clf(fig)
% use 1st frame to get dimensions
[h, w, p] = size(frames(1).cdata);
hf = figure; 
% resize figure based on frame's w x h, and place at (150, 150)
set(hf,'Position', [150 150 w h]);
axis off
% Place frames at bottom left
movie(hf,frames,4,30,[0 0 0 0]);
 close(gcf)
Lucas Zamboulis
  • 2,494
  • 5
  • 24
  • 27
shalti
  • 1