matplotlib savefig()与show()的图不同


72

当我用来show()在中绘制图形时X,这些图形看起来非常好。但是,当我开始使用它savefig()来生成大量图形时,所savefig()生成图形的字体,线条,多边形看上去都比所show()生成图形小。我的环境是Ubuntu,后端show()Qt4Agg。如何使show()图和savefig()图看起来一致?

Answers:


77

savefig指定所保存图形的DPI(如果未在.matplotlibrc中指定,则默认值为100,请查看到的dpikwargsavefig)。它不是从原始图形的DPI插入的。

DPI影响文本的相对大小和线条的笔划宽度等。如果您希望外观看起来相同,请传递fig.dpifig.savefig

例如

import matplotlib.pyplot as plt

fig = plt.figure()
plt.plot(range(10))
fig.savefig('temp.png', dpi=fig.dpi)

30

您可以使用参数几乎相同的不同函数(plotsavefig)将matplotlib图绘制到不同的设备(例如,通过Quartz在屏幕上显示,通过pdf呈现到pdf文件),但是这些参数的默认值不同两种功能。

换句话说,在savefig默认参数是从不同的默认的显示参数。

如果在matplotlib配置文件中进行对齐,则很简单。模板文件包含在源软件包中,名为matplotlibrc.template。如果在安装matplotlib时未创建模板,则可以从matplotlib源文件或matplotlib网站获取此模板。

按照所需方式自定义此文件后,将其重命名为matplotlibrc(无扩展名),并将其保存到应位于主目录中的目录.matplotlib(注意前导'。')中。

用于保存图形的config参数从提供的matplotlibrc.template中的314行开始(此部分之前的第一行是:###保存图形)。

特别是,您将需要查看以下内容:

savefig.dpi       : 100         # figure dots per inch
savefig.facecolor : white       # figure facecolor when saving
savefig.edgecolor : white       # figure edgecolor when saving
savefig.extension : auto        # what extension to use for savefig('foo'), or 'auto'

这些行下方是字体类型和各种图像格式特定参数的设置。

这些相同的参数进行显示,即PLT.show() ,开始在约线277一个在matplotlibrc.template(本节前面有线:###图):

figure.figsize   : 8, 6          
figure.dpi       : 80            
figure.facecolor : 0.75       
figure.edgecolor : white     

通过比较这两个参数块的值可以看到,savefigdisplay(显示)的同一图形属性的默认设置是不同的。


更改这些配置与show()和savefig()之间保持一致的字体大小和线宽不匹配。虽然我想补充一点,从Qt Widget手动保存图表是可以的。只有在不正常的情况下,才使用savefig()
Leon

21

这是个老问题,但显然Google对此很喜欢,因此我认为在对这个问题进行了一些研究之后,我在这里给出了答案。

如果您从头开始创建图形,则可以在创建时为其提供尺寸选项:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(3, 6))

plt.plot(range(10)) #plot example
plt.show() #for control

fig.savefig('temp.png', dpi=fig.dpi)

figsize(width,height)调整图的绝对尺寸,并有助于确保两个图看起来相同。

如另一个答案所述,dpi选项会影响文本的相对大小和线条的笔触宽度等。使用dpi = fig.dpi选项可确保show()savefig的相对大小都相同()

另外,图形大小可以在创建后通过以下方式更改:

fig.set_size_inches(3, 6, forward=True)

前进可以随时更改大小。

如果在创建的图像中边框太大时遇到问题,可以使用以下方法之一进行调整:

plt.tight_layout()
#or:
plt.tight_layout(pad=2)

要么:

fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight')
#or:
fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight', pad_inches=0.5)

第一个选项仅使布局和边框最小化,第二个选项允许手动调整边框。这些技巧至少帮助我解决了不同的savefig()show()图像的问题。


4

我已经在matplotlib源代码中修复了此问题,但这并不是一个很好的解决方案。但是,如果您像我一样对图形的外观非常讲究,那是值得的。

问题似乎出在渲染后端。它们每个都获得了正确的线宽,字体大小等值,但是当以PDF或PNG呈现时,比使用show()呈现时要大一些。

我在文件matplotlib / backends / backend_agg.py中为生成PNG的源代码添加了几行。您可以对使用的每个后端进行类似的更改,或者找到在单个位置进行更巧妙的更改的方法;)

添加到我的matplotlib / backends / backend_agg.py文件中:

    # The top of the file, added lines 42 - 44
42  # @warning: CHANGED FROM SOURCE to draw thinner lines
43  PATH_SCALAR = .8
44  FONT_SCALAR = .95

    # In the draw_markers method, added lines 90 - 91
89  def draw_markers(self, *kl, **kw):
90      # @warning: CHANGED FROM SOURCE to draw thinner lines
91      kl[0].set_linewidth(kl[0].get_linewidth()*PATH_SCALAR)
92      return self._renderer.draw_markers(*kl, **kw)

    # At the bottom of the draw_path method, added lines 131 - 132:
130 else:
131     # @warning: CHANGED FROM SOURCE to draw thinner lines
132     gc.set_linewidth(gc.get_linewidth()*PATH_SCALAR)
133     self._renderer.draw_path(gc, path, transform, rgbFace)

    # At the bottom of the _get_agg_font method, added line 242 and the *FONT_SCALAR
241     font.clear()
242     # @warning: CHANGED FROM SOURCE to draw thinner lines
243     size = prop.get_size_in_points()*FONT_SCALAR
244     font.set_size(size, self.dpi)

这样就可以满足我目前的需求,但是,根据您的工作,您可能希望在其他方法中实现类似的更改。或者找到一种更好的方法来进行相同的操作而无需进行太多的行更改!

更新:将问题发布到Github的matplotlib项目后,我能够找到问题的根源:我已经更改了matplotlibrc文件中的fig.dpi设置。如果该值与默认值不同,即使我将savefig dpi设置为与数字dpi相同,我的savefig()图像也会有所不同。因此,无需像上面那样更改源,我只是将fig.dpi设置保持为默认值80,并且能够使用savefig()生成图像,这些图像看起来像show()中的图像。

莱昂,您还更改了该设置吗?


刚刚在这里添加了一个问题,希望可以创建更好的解决方案:github.com/matplotlib/matplotlib/issues/786
Karmel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.