将Matlab图形保存为图像的计算快速方法(例如PNG)

时间:2016-12-14 17:07:40

标签: matlab performance matlab-figure

我有一个程序可以创建很多我希望保存为fig001, fig002, ...的图表。目前,我能做到这一点的唯一方法就是在我使用print()时将它们逐个保存,或者将它们保存到图形对象FIG中。

不幸的是,我必须按顺序创建绘图(不能并行化)。如果我保存,那么这需要相当长的时间;如果我存储在FIG然后执行parfor - 遍历所有数字,那么这会更快。但是,它仍然很慢,这是我的代码中的一个主要瓶颈。

Matlab自动编写1200x900像素图像。实际上,它只是一个图形,上面有一些(水平)直线。我真的不需要高质量的图像;也许减少这将有助于加快速度?我也找不到如何做到这一点。

我已经在网上看过,特别是在其他SE问题上,但我还没有找到解决方案。有关于“玩hardcore功能”的各种内容。我是一名数学家,他希望代码能够对问题有所了解;我不是一个合适的程序员!因此,“玩一个函数”(这可能导致Matlab崩溃)对我来说相当困难!

我已经使用Matlab movie函数对此进行了排序。谢谢塞西莉亚的帮助!

3 个答案:

答案 0 :(得分:3)

因为您打算在幻灯片中使用图像。我建议制作一部电影并使用它。我已经进行了一些测试,保存电影比保存单个png要快得多。在我的简单测试中,我看到加速了5倍。

numImages = 25;

%Saving one figure at a time
tic;
for i= 1:numImages
    x = 0:0.1:2*pi;
    y = i*sin(x);    
    plot(x, y);

    fig = gcf;
    print('img.png', '-dpng', '-r50'); %Downsample resolution
end
toc;

tic;

%Saving a movie
v = VideoWriter('mov.avi');
open(v);
for i = 1:numImages
    x = 0:0.1:2*pi;
    y = i*sin(x);
    plot(x, y);

    drawnow; %Force the figure to render
    frame = getframe; %Convert the figure to a movie frame
    writeVideo(v, frame); %Write the frame to the movie file
end
close(v);

toc;

使用writeVideo还具有永不将整部电影存储在内存中的优势。相反,当捕获每个帧时,它立即被写入文件。一个缺点是因为帧需要以正确的顺序写入,所以不能使用parfor

您还可以考虑制作电影矩阵。每个元素都是一个框架。因此,要初始化矩阵的大小,您需要类似

的内容
numImages = 25;
mov(numImages) = struct('cdata',[],'colormap',[]);  

然后使用parfor,您可以按正确的顺序将所有图片分配到mov矩阵。循环结束后,您可以使用VideoWriter将影片写入文件。但是,在生成数据时,您需要将整部电影保留在内存中,并且会产生与parfor相关的开销,因此最终可能无法提高效率。

答案 1 :(得分:1)

如果您使 Matlab 输出这样的文件,称为“lines.txt”,每行描述输出图像上一行的x1,y1和x2,y2:

10 100 600 100
50 400 800 400
100 820 350 820

然后你可以使用 ImageMagick 来绘制这样的行:

#!/bin/bash

# Create the output image, 1200x900
convert -size 1200x900 xc:gray80 result.png

# Loop, reading one line at a time from the file "lines.txt"
while read x1 y1 x2 y2; do

   echo Read line $x1,$y1 $x2,$y2

   # Tell ImageMagick to draw the line on the image
   convert result.png -stroke blue -strokewidth 5 -draw "line $x1,$y1 $x2,$y2" result.png
done < lines.txt

enter image description here

显然,您可以绘制非水平线,并且可以在x,y坐标和/或厚度之后输出颜色......

ImageMagick 安装在大多数Linux发行版上,可用于OSX和Windows。有更有效的方法来绘制线条,但这可能足以让你开始。

另一种选择可能是使用 Gnuplot ,请参阅我的其他答案here

答案 2 :(得分:1)

除了Cecilia的答案,建议使用getframe生成电影,我想补充说getframe也可用于提高保存静态图像的速度。将其与frame2im组合以将图形转换为栅格化图像,然后使用imwrite将栅格化图像保存到文件中。

frame = getframe(fig); % fig is the figure handle to save
[raster, raster_map] = frame2im(frame); % raster is the rasterized image, raster_map is the colormap
if isempty(raster_map)
    imwrite(raster, fig_file);
else
    imwrite(raster, raster_map, fig_file); % fig_file is the path to the image
end

在我的特定情况下,使用此方法,用于保存数字的时间从19个文件(使用saveas)的约60秒减少到7~9秒。

请注意此方法

  1. 不会将背景颜色更改为白色saveas;
  2. 似乎不支持除当前数字之外的分辨率和dpi;
  3. 不支持将其另存为矢量图像(显然)。