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

将Matlab图形保存为图像的计算快速方法(例如PNG),matlab,performance,matlab-figure,Matlab,Performance,Matlab Figure,我有一个程序,可以创建许多绘图,我想将其另存为fig001、fig002、。目前,我唯一能做的就是使用print()将它们逐个保存,或者将它们保存到图形对象FIG 不幸的是,我必须按顺序创建绘图(无法并行)。如果我边走边储蓄,那么这需要相当长的时间;如果我存储在FIG中,然后在所有图形上执行parfor-循环,则速度更快。然而,它仍然非常慢,这是我代码中的一个主要瓶颈 Matlab正在自动编写1200x900像素图像。实际上,它只是一个带有一些(水平)直线的图形。我真的不需要高质量的图像;也许减

我有一个程序,可以创建许多绘图,我想将其另存为
fig001、fig002、
。目前,我唯一能做的就是使用
print()
将它们逐个保存,或者将它们保存到图形对象
FIG

不幸的是,我必须按顺序创建绘图(无法并行)。如果我边走边储蓄,那么这需要相当长的时间;如果我存储在
FIG
中,然后在所有图形上执行
parfor
-循环,则速度更快。然而,它仍然非常慢,这是我代码中的一个主要瓶颈

Matlab正在自动编写
1200x900
像素图像。实际上,它只是一个带有一些(水平)直线的图形。我真的不需要高质量的图像;也许减少这个会有助于加快速度?我也不知道怎么做

我在网上看了一下,特别是其他SE问题,但我还没有找到解决方案。关于“玩弄
核心功能”有各种各样的内容。我是一个数学家,想要一个代码来获得问题的直觉;我不是一个合适的程序员!因此,“玩转函数”(这可能会导致Matlab崩溃)对我来说相当困难



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

因为您的目的是在幻灯片中使用图像。我建议拍一部电影,用它来代替。我已经运行了一些测试,保存一部电影要比保存单个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
相关的开销也很大,因此它可能不会更有效

如果您让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
#/bin/bash
#创建输出图像1200x900
转换-大小1200x900 xc:gray80 result.png
#循环,从文件“lines.txt”中一次读取一行
当读取x1 y1 x2 y2时;做
回显读取行$x1、$y1$x2、$y2
#让ImageMagick在图像上画线
convert result.png-蓝色笔划-笔划宽度5-绘制“line$x1,$y1$x2,$y2”result.png
done

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

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


另一个选项可能是使用Gnuplot,请参阅我的其他答案。

除了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个文件的~60秒(使用
saveas
)减少到7~9秒

请注意,此方法

  • 不会像
    saveas
    那样将背景颜色更改为白色
  • 除目前的数字外,似乎不支持决议和新闻部
  • 不支持保存为矢量图像(显然)

  • 如果您对图形上定义直线的几个点感兴趣,可以将这些点坐标保存在文本文件中。然后您可以使用该文件快速复制图形。因此,是的,我只有几点,但我真的想将它们生成图形,我可以将其另存为,
    .png
    文件。这样做的原因是,我想从图形中进行“幻灯片放映”(例如,使用FFMPEG)。为了回答您关于更改图像分辨率的问题:@Cecilia我更多地考虑一个特定的像素大小,但进一步看,我想我可以说“-r100”,这就给了我
    800x600
    文件。在测试中,这些文件的编写速度比
    1200x900
    文件快得多,但实际上并不比
    40x30
    文件快。它仍然比我想要的慢很多…:/您是否考虑过制作4D矩阵并将其保存为.avi或动画gif以显示幻灯片?如果您需要有关制作电影的更多详细信息,请告诉我。只需添加到Cecilia,原因是它创建的文件数。不幸的是,matlab打开一个文件然后关闭它需要相当长的时间。这就是为什么视频比一系列图像要快得多(只有一个文件可以打开和关闭)。@Danielldrich这就是我发现的问题,即
    打印的开销太大了。@Cecilia谢谢你。与其说
    frame=getframe
    ,然后将该帧添加到视频的末尾(我假设
    writeVid),是否可能更好