matplotlib显示的图与从show()窗口保存的图不同

1 投票
1 回答
2156 浏览
提问于 2025-04-18 05:31

我用matplotlib的imshow()来绘制比较复杂的数据,所以我喜欢先看看图像是否正常,然后再保存。通常我会先调用plt.show(),看看图像是否没问题,然后在显示窗口里手动保存。不过最近我遇到了一些奇怪的事情。当我保存图像时,得到的图片却很不对劲,尽管在matplotlib的互动窗口里看起来一切正常。

如果我先放大到某个特定位置,然后再保存我看到的内容,保存的图像就没问题。

这是正确的图像(在放大后保存的小区域):enter image description here

而这个图像是我在保存所有内容后,放大到大约同一区域的结果:approx

出于某种原因,第二个图像里的像素要大得多!这对我来说非常糟糕——如你所见,里面的细节丢失了很多。

不幸的是,我的代码比较复杂,无法用随机生成的数据重现这个问题。这个问题是在我开始分别绘制两个三角形后出现的:我用np.loadtxt()读取了两个巨大的数据文件,然后用np.triu(data1)np.tril(data2)处理,屏蔽了零、缺失值、负无穷和正无穷,然后用plt.imshow(data, interpolation='none', origin='lower', extent=extent)在同一个坐标轴上绘制它们。我还做了很多其他的事情来让图像看起来更好,但我想这些应该没关系,因为之前一切都很顺利。

如果你需要我代码中的其他具体信息,以帮助解决这个问题,请告诉我。

1 个回答

1

当你把图像保存为png或jpg格式时,其实就是把它转换成了一定数量的像素,这个过程叫做“栅格化”。如果你想保持图像的高分辨率,有几个方法可以选择:

  • 使用非常高的 dpi 参数,比如900。这样保存图像会比较慢,而且很多图片查看器打开时也会花点时间,但信息是完整的,你随时可以裁剪。
  • 保存图像的数据,也就是你用来制作图表的具体数字。每当你需要查看时,可以在Matplotlib的交互模式下加载这些数据,找到你想要的部分,然后再保存。
  • 使用SVG格式:这是一种矢量图形格式,所以你不受像素的限制。

下面是如何使用SVG的方法:

import matplotlib
matplotlib.use('SVG')
import matplotlib.pyplot as plt

# Generate the image
plt.imshow(image, interpolation='none')
plt.savefig('output_image')

补充:

要保存真正的SVG格式,你需要从一开始就使用SVG后端,但不幸的是,这与交互模式不兼容。有些后端,比如GTKCairo,似乎可以同时支持这两种模式,但结果仍然是栅格化的,而不是一个真正的SVG。

这可能是matplotlib中的一个bug,至少据我所知,这一点并没有被记录下来。

撰写回答