将matplotlib填充等高线图保存为.pdf或.eps格式时出现走样问题

11

我正在使用matplotlib.pyplot.contourf()函数生成一个带有填充颜色的等高线图。调用该函数时的参数为:

contourf(xvec,xvec,w,levels,cmap=matplotlib.cm.jet)

何处

xvec = numpy.linspace(-3.,3.,50)
levels = numpy.linspace(-0.01,0.25,100)

并且w是我的数据。

生成的图在屏幕上看起来非常好,但是当我使用matplotlib.pyplot.savefig()保存为pdf时,生成的pdf会有很多锯齿状(我认为是这样)的问题。调用savefig的方法只是savefig('filename.pdf')。我已经尝试过使用dpi参数,但没有成功。调用matplotlib.get_backend()显示'TkAgg'。

我将附上一个保存为pdf的图形,与保存为png的图形(类似于屏幕上的样子)进行比较,以演示问题:

无锯齿的png:https://dl.dropbox.com/u/6042643/wigner_g0.17.png

带锯齿的pdf:https://dl.dropbox.com/u/6042643/wigner_g0.17.pdf

如果有其他细节可以提供,以帮助您给出答案,请告诉我。我应该提到,保存为.eps也会产生类似的糟糕结果,但pdf更清晰地显示了问题。我的目标是最终得到一个可以附加在latex文档中作为科学论文发表的制作质量.eps。如果我能找到一种给出满意结果的方法,我会接受一些解决方案,例如先保存为一种格式,然后转换。

最好,

阿恩


这些看起来像是Moiré patterns。在PDF中,该图案会根据缩放级别而改变。 - tacaswell
2
@arne:链接的文件已经失效了 - 有没有可能替换一下? - Chris H
2个回答

20

使用@pelson提供的有用答案一段时间后,我终于找到了一个适当的解决方案来解决这个长期存在的问题(目前在Matplotlib 3中),它不需要多次调用等高线或将图形光栅化。

有关更详细的说明和示例,请参见我的原始答案此处

总之,解决方案包括以下几行:

cnt = plt.contourf(x, y, z)

for c in cnt.collections:
    c.set_edgecolor("face")

plt.savefig('test.pdf')

7
我不知道PDF中轮廓的描绘如此糟糕。你说得对,我认为轮廓在matplotlib之外的PDF渲染器中被反锯齿化了。因此,我认为您需要特别小心选择用来查看结果PDF的应用程序——我看到的最好的行为是使用GIMP,但我相信还有很多其他表现良好的查看器。

为了解决这个问题(当使用GIMP查看PDF时),我能够“光栅化”matplotlib生成的轮廓,以避免丑陋的白线问题:

import matplotlib.pyplot as plt
import numpy as np


xs, ys = np.mgrid[0:30, 0:40]
data = (xs - 15) ** 2 + (ys - 20) ** 2 + (np.sin(ys) + 10) ** 2

cs = plt.contourf(xs, ys, data, 60, cmap='jet')

# Rasterize the contour collections
for c in cs.collections:
    c.set_rasterized(True)

plt.savefig('test.pdf')

这样可以生成一个等高线图,不会出现你所展示的问题。

另一种可行的方法可能更好,就是通过在等高线下方放置彩色线条来欺骗反锯齿处理。

import matplotlib.pyplot as plt
import numpy as np


xs, ys = np.mgrid[0:30, 0:40]
data = (xs - 15) ** 2 + (ys - 20) ** 2 + (np.sin(ys) + 10) ** 2

# contour the plot first to remove any AA artifacts
plt.contour(xs, ys, data, 60, cmap='jet', lw=0.1)
cs = plt.contourf(xs, ys, data, 60, cmap='jet')

plt.savefig('test.pdf')

我应该指出,如果我将这个图形保存为“.ps”而不是“.pdf”,我就看不到这些问题,也许这是第三种选择。
希望这能帮助你使论文看起来完美无缺。

2
嗨,pelson。我选择了你的第二个解决方案,它运行得非常好。非常感谢。 - arne
我也可以确认这种行为,如果我保存带有级别的contourf()函数,无论是在PS、EPS、PDF中,但不是在SVG输出中。同时,通过GhostScript运行此类PS/EPS/PDF并以300dpi输出PNG,则不会出现问题,但在Acrobat、SumatraPDF(使用由GhostScript背后的同一团队设计的mupdf引擎)、CorelDraw、Ipe等中查看PDF时,都会显示此伪影。 - theta
更进一步说,轮廓并没有轮廓线,而是轮廓与绘图窗口的白色背景之间存在微小的间隙,这就是显示为轮廓轮廓线的东西。 - theta
@pelson的等高线技巧很好,它似乎可以很好地填补间隙。另一个方法是在调用contourf()之前使用imshow()绘制数组 - 这样绘图背景将与等高线边界相匹配,间隙将不可见。或者当然也可以使用SVG并将其打印到PDF或PS中... - theta
我在SVG中遇到了同样的问题,你的第二个解决方案解决了它 - 但是我不得不手动指定zorder,因为我有一些使用fill_between生成的阴影叠加层,而等高线位于其上方。 - Chris H
谢谢pelson,你的第二个解决方案很好用,即使在极地等高线图中也是如此。更好的是,可以设置zorder=1.5,以便正确排序等高线。 - Hongcheng Ni

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