Matplotlib等高线图的后处理

3
我有一个2D数组,想用matplotlib生成等高线图。保存为PNG(或其他光栅格式)一切正常,但是我需要将图形保存为postscript格式以在论文中使用。问题是,当我保存为postscript格式时,得到的文件相当大(几MB)。看起来Matplotlib以矢量格式保存所有内容。尽管对于坐标轴和标签而言这是有道理的,如果转换为光栅图像会使其降级,但我希望等高线图本身以光栅格式保存(我知道可以将其嵌入到postscript中)。是否有人知道如何做到这一点?我正在使用Agg后端。

你能给我们一点代码提示或者看看你的代码吗? - khan
4个回答

4

您可以设置:

plt.gcf().set_rasterized(True)

在 plt.savefig 之前


1
我不知道这个命令...但是,它的作用是将整个图形栅格化(这已经是一种效果)。我真正想要的是仅将轮廓图本身栅格化,同时保留文本(例如标签)的矢量格式。 - Spock

4

这里有一个最小的工作示例。我使用了sega_sai的代码一段时间,没有出现任何问题。

from matplotlib.collections import Collection
from matplotlib.artist import allow_rasterization
import matplotlib.pyplot as plt

class ListCollection(Collection):
     def __init__(self, collections, **kwargs):
         Collection.__init__(self, **kwargs)
         self.set_collections(collections)
     def set_collections(self, collections):
         self._collections = collections
     def get_collections(self):
         return self._collections
     @allow_rasterization
     def draw(self, renderer):
         for _c in self._collections:
             _c.draw(renderer)

def insert_rasterized_contour_plot(c):
    collections = c.collections
    for _c in collections:
        _c.remove()
    cc = ListCollection(collections, rasterized=True)
    ax = plt.gca()
    ax.add_artist(cc)
    return cc

if __name__ == '__main__':
    import numpy as np
    x, y = np.meshgrid(*(np.linspace(-1,1,500),)*2)
    z = np.sin(20*x**2)*np.cos(30*y)
    c = plt.contourf(x,y,z,30)

    plt.savefig('fig_normal.pdf')

    insert_rasterized_contour_plot(c)
    plt.savefig('fig_rasterized.pdf')

在我的电脑上,结果如下:
fig_normal.pdf:文件大小为5810 KByte,需要大约5秒钟才能在Adobe Reader中呈现。
fig_rasterized.pdf:文件大小为60 KByte,并直接在Adobe Reader中呈现。

3

很遗憾,我没有成功运行这个或者这个答案中的解决方案。然而,我找到了一个非常简单的一行代码的解决办法。

所以,可以设置轴的光栅化级别。

ax.set_rasterization_zorder(Z)

在这种方式下,所有zorder小于Z的对象都将被光栅化。对我来说,它看起来有点像这样:
plt.contourf(<all plotting properties>, zorder=-2)
ax.set_rasterization_zorder(-1)

这样一来,轮廓以栅格格式呈现,但其上方的所有其他对象(线条、文本)均为矢量格式。对于我的图形而言,大小从约4 Mb 减小到了约400 kb。


1

好的,最终我找到了自己问题的答案。这需要在matplotlib邮件列表中进行艰难的挖掘,因此我将相关线程链接在这里,希望它对其他人也有帮助,并且可能更容易找到(顺便说一句,没有人回复那个发消息的可怜人)。

我将在这里用文字总结这个想法。必须使用set_rasterized方法,就像sega_sai建议的那样。但是,与我在评论中解释的将整个图形应用于该方法不同,该方法必须应用于组成轮廓图的线条。诀窍是首先为它们创建一个“容器”,并对其进行光栅化,而不是对每条单独的线进行光栅化(这是我已经尝试过并且效果很差的事情)。这很好地起作用。在我链接的讨论中,您可以找到执行此操作的代码。


3
如果您能提供一个 MWE(最小工作示例),那么对于其他希望在未来解决您的问题的人来说,这个答案会更加有用! - Hooked

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接