matplotlib savefig()与show()不同

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

savefig指定保存的数字的DPI(如果没有在.matplotlibrc中指定,默认值为100,看看dpi kwarg savefig )。 它不是从原来的数字的DPI中插入的。

DPI会影响文本的相对大小和行中的笔划宽度等。如果您希望事物看起来完全相同,则将fig.dpi传递给fig.savefig

例如

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

你将你的matplotlib图绘制到不同的设备上(例如,通过Quartz在屏幕上显示,或者通过使用不同function的pdf文件( plotsavefig ),其参数几乎相同,但这些参数的默认值是不一样的这两个function。

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

如果在matplotlibconfiguration文件中进行alignment,将它们alignment很简单。 模板文件包含在源代码包中,并且名为matplotlibrc.template 。 如果您在安装matplotlib时未创build一个,则可以从matplotlib源文件或matplotlib网站获取该模板。

一旦你按照你想要的方式定制了这个文件,把它重命名为matplotlibrc (没有扩展名)并保存到目录.matplotlib (注意前面的'。'),它应该在你的主目录下。

保存graphics的configuration参数从提供的matplotlibrc.template的314行开始(本节之前的第一行是:### SAVING FIGURES)。

特别是,你会想看看这些:

 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' 

在这些行下面是字体types和各种图像格式特定参数的设置。

这些用于显示的相同参数,即PLT.show() ,从matplotlibrc.template中的第277行开始(本节以行开始:### FIGURE):

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

正如您通过比较这两个参数块的值所看到的,对于savefigdisplay (show),相同figure属性的默认设置是不同的。

我已经解决了这个在我的matplotlib源,但它不是一个漂亮的修复。 但是,如果你像我一样,非常关心图表的外观,那就值得。

这个问题似乎是在渲染后端; 他们每个都得到线宽,字体大小等的正确值,但是当呈现为PDF或PNG时,它们比用show()渲染时稍大。

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

添加到我的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) 

因此,现在适合我的需求,但是,根据您在做什么,您可能需要在其他方法中实施类似的更改。 或者find一个更好的方法来做同样的事情,而不需要做太多的换行!

更新:在Github的matplotlib项目发布问题后,我能够追踪我的问题的来源:我已经改变了matplotlibrc文件中的figure.dpi设置。 如果该值不同于默认值,则即使将savefig dpi设置为与dpi的dpi相同,我的savefig()图像也会不同。 所以,不是像上面那样改变源代码,而是将figure.dpi设置保留为默认值80,并且能够使用savefig()生成图像,这看起来像来自show()的图像。

莱昂,你是否也改变了这个设置?

老问题,但显然谷歌喜欢它,所以我想我经过对这个问题的一些研究后在这里回答。

如果你从头开始创build一个graphics,你可以在创build时给它一个大小选项:

 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(宽度,高度)调整您的情节的绝对尺寸,并有助于确保两个情节相同。

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

或者,graphics大小可以在创build后更改:

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

前进允许在飞行中改变大小。

如果您在创build的图像中的边框太大,您可以使用以下方法调整这些边框:

 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) 

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