简体   繁体   English

在内存中渲染MATLAB图

[英]Render MATLAB figure in memory

Are there any alternatives to using getframe and saveas for saving the contents of a figure to a raster image for further processing? 有没有其他方法可以使用getframesaveas将图形的内容保存为光栅图像以便进一步处理?

Approach 1: getframe 方法1: getframe

h = figure('visible', 'off');
a = axes('parent', h);

% render using `scatter3()` or other plot function.

content = frame2im(getframe(h));

This has the serious drawback of showing the figure to perform a screen capture in the call to getframe() and it is problematic when performing such a render in a loop (ie saving content at each iteration as a video frame). 这具有显示图形在对getframe()的调用中执行屏幕捕获的严重缺点,并且当在循环中执行这样的渲染(即,在每次迭代时将content保存为视频帧)时存在问题。

Approach 2: saveas 方法2: saveas

h = figure('visible', 'off');
a = axes('parent', h);

% render using `scatter3()` or other plot function.

saveas(h, '/path/to/file.png');
content = imread(/path/to/file.png');

This approach has the serious drawback of writing to disk, which is problematic in multithreaded applications, as well as being slower than rendering directly to memory. 这种方法具有写入磁盘的严重缺点,这在多线程应用程序中存在问题,并且比直接渲染到内存要慢。 Since saveas() will obviously render to memory before invoking the PNG encoder, what I want is possible, but I can't find any function it in the MATLAB documentation that only performs the rendering part. 因为saveas()显然会在调用PNG编码器之前渲染到内存中,所以我想要的是可能的,但我在MATLAB文档中找不到任何只执行渲染部分的函数。

Question : 问题

Does you know of an alternate way of rendering an arbitrary axes content to a raster image? 您是否知道将任意axes内容渲染到光栅图像的替代方法?

I realize this is an old thread, but I ran into this problem again lately, so I wanted to summarize my findings. 我意识到这是一个老线程,但我最近又遇到了这个问题,所以我想总结一下我的发现。 My main source is this page ( cached ). 我的主要来源是此页面缓存 )。 According to it, there are three alternatives: 根据它,有三种选择:

  1. using ADDFRAME directly with the figure handle (without using GETFRAME ). 直接使用ADDFRAME和数字句柄(不使用GETFRAME )。 This is exactly what @rescdsk has shown in his answer. 这正是@rescdsk在答案中所表现出来的。

     hFig = figure('Visible','off'); aviobj = avifile('file.avi'); for k=1:N %#plot(...) aviobj = addframe(aviobj, hFig); end aviobj = close(aviobj); 
  2. using PRINT / SAVEAS / HGEXPORT to export the figure to an image file, then reading the image back from disk. 使用PRINT / SAVEAS / HGEXPORT将图形导出到图像文件,然后从磁盘读回图像。 This is approach#2 that you listed yourself in the question above. 这是你在上面的问题中列出的方法#2。

     hFig = figure('Visible','off'); set(hFig, 'PaperPositionMode','auto', 'InvertHardCopy','off') aviobj = avifile('file.avi'); for k=1:N %#plot(...) print(['-f' num2str(hFig)], '-zbuffer', '-r0', '-dpng', 'file.png') img = imread('file.png'); aviobj = addframe(aviobj, im2frame(img)); end aviobj = close(aviobj); 
  3. using the undocumented HARDCOPY function to capture the figure in-memory. 使用未记录的HARDCOPY函数捕获内存中的数字。

     hFig = figure('Visible','off'); set(hFig, 'PaperPositionMode','auto') aviobj = avifile('file.avi'); for k=1:N %#plot(...) img = hardcopy(hFig, '-dzbuffer', '-r0'); aviobj = addframe(aviobj, im2frame(img)); end aviobj = close(aviobj); 

    In fact, this is the underlying function that other functions use either directly or indirectly. 实际上,这是其他函数直接或间接使用的基础函数。 By inspecting the source codes where possible, here is an illustration of the dependencies of the related functions where A --> B denotes A calls B : 通过在可能的情况下检查源代码,这里是相关函数的依赖关系的图示,其中A --> B表示A calls B

     saveas [M-file] --> print [M-file] --> render [private M-file] --> hardcopy [P-file] hgexport [P-file] --> print [M-file] --> ... @avifile/addframe [M-file] --> hardcopy [P-file] 

    On the other hand, GETFRAME does not call HARDCOPY but an undocumented built-in function named CAPTURESCREEN (although it seems that it will be using PRINT for the upcoming HG2 system where there is a new -RGBImage print flag): 另一方面,GETFRAME不调用HARDCOPY,而是一个名为CAPTURESCREEN的未记录的内置函数(虽然它似乎将在即将到来的HG2系统中使用PRINT,其中有一个新的-RGBImage打印标志):

     getframe [M-file] --> capturescreen [builtin] 

Note: Since AVIFILE is now deprecated, you can replace it with the newer VIDEOWRITER in (2) and (3), but not in (1) since it does not support passing figure handle directly. 注意:由于现在不推荐使用AVIFILE ,您可以将其替换为(2)和(3)中较新的VIDEOWRITER ,但不能替换为(1),因为它不支持直接传递数字句柄。

If you create an avi file with avifile , and then add frames to it with addframe , MATLAB doesn't open up extra visible figures like it does with getframe . 如果创建一个AVI文件avifile ,然后添加帧将其与addframe ,喜欢与不MATLAB开不起来的额外可见人物getframe

avi = avifile('/path/to/output');
figure_handle = figure('visible', 'off');

% ...
for something = 1:1000
    cla
    % (draw stuff...)
    avi = addframe(avi, figure_handle);
end

Start MATLAB in headless mode: matlab -noFigureWindows 在无头模式下启动MATLAB: matlab -noFigureWindows

MATLAB is running in headless mode. MATLAB以无头模式运行。 Figure windows will not be displayed. 图窗口不会显示。

then simply plot and save the figures as usual (you won't see any graphical output of course). 然后像往常一样简单地绘制并保存图形(当然,您不会看到任何图形输出)。 Example: 例:

surf(peaks);
print output.eps     %# SAVEAS works as well
close

I tested the above on a Windows machine running R2010a. 我在运行R2010a的Windows机器上测试了上述内容。 I don't have access to a Unix machine right now, but I answered a similar question in the past, and it worked just fine at the time (you will need to unset the $DISPLAY variable before starting MATLAB) 我现在无法访问Unix机器,但我过去回答了类似的问题 ,当时它运行得很好(你需要在启动MATLAB之前取消设置$DISPLAY变量)


EDIT 编辑

Another option, in case you want to keep your normal workspace, is to start a new MATLAB instance in the background which will generate and save the plots ( source ). 如果你想保持正常的工作空间,另一个选择是在后台启动一个新的MATLAB实例,它将生成并保存图( )。

Run this from the command prompt of your current MATLAB session (all on the same line): 从当前MATLAB会话的命令提示符运行此命令(全部在同一行):

!start /B /MIN matlab -noFigureWindows 
                      -automation 
                      -r "cd('c:\yourpath'); myscript; quit"

This will start a new MATLAB session in the background (using COM Automation), and execute a script called myscript (a simple M-file) that contains all your plotting code: 这将在后台启动一个新的MATLAB会话(使用COM Automation),并执行一个名为myscript的脚本(一个简单的M文件),其中包含所有的绘图代码:

c:\\yourpath\\myscript.m C:\\ yourpath \\ myscript.m

surf(peaks);
saveas(gcf, 'output.eps');

With avifile being deprecated, this is how you do it with VideoWriter: 随着avifile的弃用,这就是你使用VideoWriter的方法:

hFig = figure('Visible','off');
set(hFig, 'PaperPositionMode','auto')

aviobj = VideoWriter('file','Archival');
for k=1:N
    %#plot(...)
    img = hardcopy(hFig, '-dzbuffer', '-r0');
    writeVideo(aviobj, im2frame(img));
end
close(aviobj);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM