在内存中渲染MATLAB图

And*_*ron 24 video matlab image screen-capture off-screen

是否有任何替代方法可以使用getframesaveas将图形内容保存到光栅图像中以进行进一步处理?

方法1: getframe

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

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

content = frame2im(getframe(h));
Run Code Online (Sandbox Code Playgroud)

这具有显示图形在调用中执行屏幕捕获的严重缺点,getframe()并且当在循环中执行这样的渲染时(即,content在每次迭代时将其保存为视频帧)存在问题.

方法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');
Run Code Online (Sandbox Code Playgroud)

这种方法具有写入磁盘的严重缺点,这在多线程应用程序中存在问题,并且比直接渲染到内存要慢.因为saveas()在调用PNG编码器之前显然会渲染到内存,所以我想要的是可能的,但我在MATLAB文档中找不到任何只执行渲染部分的函数.

问题:

您是否知道将任意axes内容渲染到光栅图像的替代方法?

Amr*_*mro 17

我意识到这是一个老线程,但我最近又遇到了这个问题,所以我想总结一下我的发现.我的主要来源是此页面(缓存).根据它,有三种选择:

  1. 直接使用ADDFRAME和数字句柄(不使用GETFRAME).这正是@rescdsk在答案中所表现出来的.

    hFig = figure('Visible','off');
    
    aviobj = avifile('file.avi');
    for k=1:N
        %#plot(...)
        aviobj = addframe(aviobj, hFig);
    end
    aviobj = close(aviobj);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用PRINT/SAVEAS/HGEXPORT将图形导出到图像文件,然后从磁盘读回图像.这是你在上面的问题中列出的方法#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);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用未记录的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);
    
    Run Code Online (Sandbox Code Playgroud)

    实际上,这是其他函数直接或间接使用的基础函数.通过在可能的情况下检查源代码,这里是相关函数的依赖关系的说明,其中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]
    
    Run Code Online (Sandbox Code Playgroud)

    另一方面,GETFRAME不会调用HARDCOPY,而是一个名为CAPTURESCREEN的未记录的内置函数(虽然它似乎将使用PRINT用于即将出现的新打印标志的HG2系统-RGBImage):

    getframe [M-file] --> capturescreen [builtin]
    
    Run Code Online (Sandbox Code Playgroud)

注意:由于现在不推荐使用AVIFILE,您可以将其替换为(2)和(3)中较新的VIDEOWRITER,但不能替换为(1),因为它不支持直接传递数字句柄.


res*_*dsk 9

如果用它创建一个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
Run Code Online (Sandbox Code Playgroud)

  • 啊,太糟糕了.我正在查看"addframe"的来源,似乎中间数据似乎没有以有用的方式存储.在`addframe`的`getFrameForFigure`子函数中,看起来有一个名为`hardcopy`的无记录函数可以检索图形的内容,但当然它没有文档+可能会改变... (2认同)

Amr*_*mro 6

以无头模式启动MATLAB: matlab -noFigureWindows

MATLAB以无头模式运行.图窗口不会显示.

然后像往常一样简单地绘制并保存图形(当然,您不会看到任何图形输出).例:

surf(peaks);
print output.eps     %# SAVEAS works as well
close
Run Code Online (Sandbox Code Playgroud)

我在运行R2010a的Windows机器上测试了上述内容.我现在无法访问Unix机器,但我过去回答了类似的问题,当时它运行得很好($DISPLAY在启动MATLAB之前需要取消设置变量)


编辑

如果你想保持正常的工作空间,另一个选择是在后台启动一个新的MATLAB实例,它将生成并保存图().

从当前MATLAB会话的命令提示符运行此命令(全部在同一行):

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

这将在后台启动一个新的MATLAB会话(使用COM Automation),并执行一个myscript包含所有绘图代码的脚本(一个简单的M文件):

C:\ yourpath\myscript.m

surf(peaks);
saveas(gcf, 'output.eps');
Run Code Online (Sandbox Code Playgroud)