在内存中渲染MATLAB图
有没有其他方法可以使用getframe
和saveas
将graphics的内容保存到光栅图像中作进一步处理?
方法1: getframe
h = figure('visible', 'off'); a = axes('parent', h); % render using `scatter3()` or other plot function. content = frame2im(getframe(h));
这具有严重的缺点,即在调用getframe()
时执行屏幕截图,并且在循环中执行这样的渲染(即,在每次迭代时将content
保存为video帧)是有问题的。
方法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');
这种方法存在严重的写入磁盘的缺点,这在multithreading应用程序中是有问题的,而且比直接渲染到内存要慢。 因为在调用PNG编码器之前saveas()
显然会呈现给内存,所以我想要的是可能的,但是在MATLAB文档中我找不到任何只执行渲染部分的函数。
问题 :
您是否知道将任意axes
内容渲染为光栅图像的替代方法?
如果你用addframe
创build一个avi文件,然后用addframe
向它添加帧,MATLAB不会像getframe
那样打开额外的可见graphics。
avi = avifile('/path/to/output'); figure_handle = figure('visible', 'off'); % ... for something = 1:1000 cla % (draw stuff...) avi = addframe(avi, figure_handle); end
我意识到这是一个古老的线索,但最近又遇到了这个问题,所以我想总结一下我的发现。 我的主要来源是这个页面 ( caching )。 据此,有三种select:
-
直接使用ADDFRAME和数字句柄(不使用GETFRAME )。 这正是@rescdsk在他的回答中所performance的。
hFig = figure('Visible','off'); aviobj = avifile('file.avi'); for k=1:N %#plot(...) aviobj = addframe(aviobj, hFig); end aviobj = close(aviobj);
-
使用PRINT / SAVEAS / HGEXPORT将graphics导出到图像文件,然后从磁盘读取图像。 这是你在上面的问题中列出你自己的方法#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);
-
使用未logging的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);
实际上,这是其他函数直接或间接使用的基础函数。 通过在可能的情况下检查源代码,下面是相关函数的依赖关系的图示,其中
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]
另一方面,GETFRAME不会调用HARDCOPY,而是一个名为CAPTURESCREEN的未logging的内置函数(虽然看起来它将在即将到来的HG2系统中使用PRINT,其中有一个新的
-RGBImage
打印标志):getframe [M-file] --> capturescreen [builtin]
注意:由于AVIFILE现在已经被弃用,可以用(2)和(3)中较新的VIDEOWRITERreplace它,但是不能在(1)中replace它,因为它不支持直接传递graphics句柄。
以无头模式启动MATLAB: matlab -noFigureWindows
MATLAB正在无头模式下运行。 graphics窗口将不会显示。
那么就像往常一样简单地绘制和保存数据(当然,您不会看到任何graphics输出)。 例:
surf(peaks); print output.eps %# SAVEAS works as well close
我在运行R2010a的Windows机器上testing了上述内容。 我现在还没有访问Unix机器,但是我回答了过去的一个类似的问题 ,当时它工作得很好(在启动MATLAB之前,您需要取消设置$DISPLAY
variables)
编辑
另一个选项,如果你想保持你的正常的工作空间,是在后台启动一个新的MATLAB实例,将生成并保存图( 源 )。
从当前MATLAB会话的命令提示符下运行(全部在同一行):
!start /B /MIN matlab -noFigureWindows -automation -r "cd('c:\yourpath'); myscript; quit"
这将在后台启动一个新的MATLAB会话(使用COM自动化),并执行一个名为myscript
(一个简单的M文件)的脚本,其中包含所有的绘图代码:
C:\ yourpath \ myscript.m
surf(peaks); saveas(gcf, 'output.eps');
随着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);