关于python:将打印保存到图像文件,而不是使用matplotlib显示它

Save plot to image file instead of displaying it using Matplotlib

我正在写一个快速而肮脏的脚本来生成动态的绘图。我使用下面的代码(来自matplotlib文档)作为起点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pylab import figure, axes, pie, title, show

# Make a square figure and axes
figure(1, figsize=(6, 6))
ax = axes([0.1, 0.1, 0.8, 0.8])

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

explode = (0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
title('Raining Hogs and Dogs', bbox={'facecolor': '0.8', 'pad': 5})

show()  # Actually, don't show, just save to foo.png

我不想在图形用户界面上显示绘图,相反,我想将绘图保存到一个文件(比如foo.png)中,以便它可以在批处理脚本中使用。我该怎么做?


当问题得到回答时,我想在使用matplotlib.pyplot.savefig时添加一些有用的提示。文件格式可以由扩展名指定:

1
2
3
4
from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

将分别给出光栅化或矢量化的输出,这两种方法都很有用。此外,您会发现pylab在图像周围留下了大量的、通常是不受欢迎的空白。移除它:

1
savefig('foo.png', bbox_inches='tight')


正如其他人所说,plt.savefig()fig1.savefig()确实是保存图像的方法。

然而,我发现在某些情况下(例如,Spyder的plt.ion():交互模式=开),总是显示出这个数字。我通过在我的大循环中强制关闭图形窗口来解决这个问题,因此在循环过程中我没有一百万个打开的图形:

1
2
3
4
5
import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png')   # save the figure to file
plt.close(fig)    # close the figure


解决方案是:

1
pylab.savefig('foo.png')

刚刚在Matplotlib文档中找到了这个链接,它正好解决了这个问题:http://matplotlib.org/faq/howto ou faq.html生成-images-without-having-a-window-appear

他们说,防止数字出现的最简单方法是通过matplotib.use()使用非交互式后端(例如agg),例如:

1
2
3
4
5
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')

我个人还是更喜欢使用plt.close( fig ),因为从那时起,您可以选择隐藏某些数字(在循环期间),但仍然可以显示用于循环后数据处理的数字。不过,它可能比选择非交互式后端慢——如果有人测试的话,这会很有趣。

更新:对于Spyder,您通常不能这样设置后端(因为Spyder通常会提前加载matplotlib,阻止您使用matplotlib.use())。

相反,使用plt.switch_backend('Agg'),或者在spyder prefs中关闭"启用支持",然后自己运行matplotlib.use('Agg')命令。

从这两个提示:一,二


如果您不喜欢"当前"图形的概念,请执行以下操作:

1
2
3
4
import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)


其他答案是正确的。但是,有时我会发现我想稍后打开图形对象。例如,我可能希望更改标签大小、添加网格或进行其他处理。在一个完美的世界中,我只需重新运行生成绘图的代码,并调整设置。唉,这个世界并不完美。因此,除了保存到PDF或PNG之外,我还添加了:

1
2
with open('some_file.pkl',"wb") as fp:
    pickle.dump(fig, fp, protocol=4)

像这样,我可以稍后加载figure对象并根据需要操作设置。

我还为堆栈中的每个函数/方法编写了带有源代码和locals()字典的堆栈,以便稍后可以确切地知道生成该图的是什么。

注意:要小心,因为有时这个方法会生成巨大的文件。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt

# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
    plt.figure(figsize=(3, 3))
    plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
    plt.title('Page One')
    pdf.savefig()  # saves the current figure into a pdf page
    plt.close()

    plt.rc('text', usetex=True)
    plt.figure(figsize=(8, 6))
    x = np.arange(0, 5, 0.1)
    plt.plot(x, np.sin(x), 'b-')
    plt.title('Page Two')
    pdf.savefig()
    plt.close()

    plt.rc('text', usetex=False)
    fig = plt.figure(figsize=(4, 5))
    plt.plot(x, x*x, 'ko')
    plt.title('Page Three')
    pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
    plt.close()

    # We can also set the file's metadata via the PdfPages object:
    d = pdf.infodict()
    d['Title'] = 'Multipage PDF Example'
    d['Author'] = u'Jouni K. Sepp\xe4nen'
    d['Subject'] = 'How to create a multipage pdf file and set its metadata'
    d['Keywords'] = 'PdfPages multipage keywords author title subject'
    d['CreationDate'] = datetime.datetime(2009, 11, 13)
    d['ModDate'] = datetime.datetime.today()

使用plot()和其他函数创建所需内容后,可以使用类似这样的子句在打印到屏幕或文件之间进行选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 5))       # size in inches
# use plot(), etc. to create your plot.

# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)  

if save_file:
    plt.savefig(save_file)
    plt.close(fig)
else:
    plt.show()


我使用了以下方法:

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt

p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)

plt.savefig('data.png')  
plt.show()  
f.close()
plt.close()

我发现保存图形后使用plt.show非常重要,否则它将不起作用。


您可以这样做:

1
2
plt.show(hold=False)
plt.savefig('name.pdf')

记住在关闭GUI绘图之前让savefig完成。这样你就可以事先看到图像。

或者,您可以使用plt.show()查看它。然后关闭GUI并再次运行脚本,但这次用plt.savefig()替换plt.show()

或者,您可以使用

1
2
3
4
fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')


如果与我一样使用Spyder IDE,则必须禁用交互模式:

plt.ioff()

(此命令在科学启动时自动启动)

如果要再次启用,请使用:

plt.ion()


解决方案:

1
2
3
4
5
6
7
8
9
10
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')

如果要显示图像并保存图像,请使用:

1
%matplotlib inline

之后import matplotlib


根据问题matplotlib(pyplot),savefig输出空白图像。

有一点需要注意:如果你使用plt.show,它应该在plt.savefig之后,否则你会给出一个空白图像。

一个详细的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc,"sgd_method")


if __name__ == '__main__':
    test_draw()

enter image description here


1
2
#write the code for the plot    
plt.savefig("filename.png")

该文件将与运行的python/jupyter文件保存在同一目录中。


1
2
import matplotlib.pyplot as plt
plt.savefig("image.png")

在Jupyter笔记本中,您必须删除plt.show(),并将plt.savefig()与其余的plt代码一起添加到一个单元中。图像仍将显示在笔记本中。


考虑到今天(这个问题提出时不可用)许多人使用jupyter笔记本作为python控制台,有一种非常简单的方法可以将绘图保存为.png,只需从jupyter笔记本调用matplotlibpylab类,绘制图形"内联"jupyter单元,然后将该图形/图像拖动到本地直接目录。奥里。别忘了第一行是%matplotlib inline