2016-12-14 140 views
1

我有一个程序,创建了很多我想保存为fig001, fig002, ...的地块。目前,我可以做的唯一方法是在我使用print()或者将它们保存到图形对象FIG中时一个一个地保存它们。计算快速的方法来保存Matlab图像作为图像(例如PNG)

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

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

我已经看过网上,特别是在其他SE问题,但我一直没有能够想出一个解决方案。有很多关于“玩弄hardcore功能”的东西。我是一个数学家,他想要一个代码来获得问题的直觉;我不是一个合适的程序员!因此,“玩弄一个功能”(可能会导致Matlab崩溃)对我来说是相当困难的!


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

+1

如果您只是对定义一条线的图上的几个点感兴趣,则可以将这些点坐标保存在文本文件中。然后您可以使用该文件快速重现图形。 – Cecilia

+0

所以是的,我只有几点,但我真的想把它们生成图形,我可以保存为'.png'文件。原因是我然后想从图表中做出'幻灯片'(例如,使用FFMPEG)。 –

+0

要回答您关于更改图像分辨率的问题:[以特定大小和分辨率保存图形](https://www.mathworks.com/help/matlab/creating_plots/save-figure-at-specific-size-and-resolution .html) – Cecilia

回答

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相关的开销,所以它可能不会更高效。

+0

让我知道你是否需要制作电影的更多细节。 – Cecilia

+0

只需添加到塞西莉亚,其原因是基于它创建的文件数量。不幸的是,matlab需要相当长的时间来打开文件然后关闭它。这就是为什么视频比一系列图像显着更快(仅打开和关闭一个文件)的原因。 –

+0

@DanielAldrich这是我发现的问题,即'print'的开销太大了。 –

1

如果您制作Matlab输出一个像这样的文件,称为“行”。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

+0

非常感谢。我要先试试'电影'选项,但如果我不能得到这个工作,那么我会看看你的! :) –