在内存中渲染 MATLAB 图窗

发布于 2024-10-01 14:05:46 字数 848 浏览 11 评论 0原文

除了使用 getframe 和 saveas 将图形内容保存到光栅图像以供进一步处理之外,还有其他选择吗?

方法 1:getframe

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

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

content = frame2im(getframe(h));

这有一个严重的缺点,即在调用 getframe() 时显示图形以执行屏幕捕获,并且存在问题在循环中执行此类渲染时(即在每次迭代时将内容保存为视频帧)。

方法 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');

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

问题

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

Are there any alternatives to using getframe and saveas for saving the contents of a figure to a raster image for further processing?

Approach 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 (i.e. saving content at each iteration as a video frame).

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

Question:

Does you know of an alternate way of rendering an arbitrary axes content to a raster image?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

赢得她心 2024-10-08 14:05:46

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

  1. 使用ADDFRAME 直接使用图形句柄(不使用 GETFRAME)。这正是 @rescdsk 在他的答案中所显示的内容。

    hFig = 图('可见','关闭');
    
    aviobj = avifile('文件.avi');
    对于 k=1:N
        %#阴谋(...)
        aviobj = addframe(aviobj, hFig);
    结尾
    aviobj = 关闭(aviobj);
    
  2. 使用打印/保存/HGEXPORT 将图形导出到图像文件,然后从磁盘读回图像。这是您在上面的问题中列出的方法#2。

    hFig = 图('可见','关闭');
    设置(hFig,'PaperPositionMode','自动','InvertHardCopy','关闭')
    
    aviobj = avifile('文件.avi');
    对于 k=1:N
        %#阴谋(...)
        print(['-f' num2str(hFig)], '-zbuffer', '-r0', '-dpng', 'file.png')
        img = imread('文件.png');
        aviobj = addframe(aviobj, im2frame(img));
    结尾
    aviobj = 关闭(aviobj);
    
  3. 使用未记录的 HARDCOPY 函数来捕获内存中的图形。

    hFig = 图('可见','关闭');
    设置(hFig,'PaperPositionMode','自动')
    
    aviobj = avifile('文件.avi');
    对于 k=1:N
        %#阴谋(...)
        img = 硬拷贝(hFig, '-dzbuffer', '-r0');
        aviobj = addframe(aviobj, im2frame(img));
    结尾
    aviobj = 关闭(aviobj);
    

    事实上,这是其他函数直接或间接使用的底层函数。通过尽可能检查源代码,以下是相关函数的依赖关系的说明,其中 A --> B 表示 A 调用 B

    saveas [M 文件] -->打印[M文件] -->渲染 [私有 M 文件] -->硬拷贝 [P 文件]
    hgeexport [P 文件] -->打印[M文件] --> ...
    @avifile/addframe [M 文件] -->硬拷贝 [P 文件]
    

    另一方面,GETFRAME 不会调用 HARDCOPY,而是调用一个名为 CAPTURESCREEN 的未记录的内置函数(尽管它似乎将在即将推出的 HG2 系统,其中有一个新的 -RGBImage 打印标志):

    getframe [M 文件] -->截屏[内置]
    

注意:由于 AVIFILE 现已弃用,您可以将其替换为(2) 和 (3) 中较新的 VIDEOWRITER ,但不在(1) 因为它不支持直接传递图形句柄。

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). This is exactly what @rescdsk has shown in his answer.

    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. This is approach#2 that you listed yourself in the question above.

    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.

    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:

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

纵情客 2024-10-08 14:05:46

如果您使用 avifile 创建一个 avi 文件,然后使用 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

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('/path/to/output');
figure_handle = figure('visible', 'off');

% ...
for something = 1:1000
    cla
    % (draw stuff...)
    avi = addframe(avi, figure_handle);
end
陌路终见情 2024-10-08 14:05:46

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

MATLAB 正在无头模式下运行。
不会显示图形窗口。

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

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

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


编辑

如果您想保留正常工作区,另一种选择是在后台启动一个新的 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');

Start MATLAB in headless mode: matlab -noFigureWindows

MATLAB is running in headless mode.
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. 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)


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

Run this from the command prompt of your current MATLAB session (all on the same line):

!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:

c:\yourpath\myscript.m

surf(peaks);
saveas(gcf, 'output.eps');
泪冰清 2024-10-08 14:05:46

随着 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);

With avifile being deprecated, this is how you do it with 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文