Matplotlib使用imsave与savefig保存viridis色图结果不一致问题
问题原因与两种方法差异说明
1. plt.savefig 配合 plt.imshow 运行逻辑
你第一段代码中已经提前通过cmap(norm(map))将原始单通道温度数据转换为0~1范围的RGBA四通道数组,此时传入plt.imshow时,函数会直接使用数组自带的RGBA值渲染,完全忽略你额外传入的cmap参数,最终plt.savefig保存的结果和你预处理得到的RGBA值完全一致,符合你的预期。
这个方法的分辨率丢失问题来自画布dpi和尺寸的默认配置:如果要保留原始像素尺寸用该方法也可实现,只需手动匹配画布参数即可,参考写法:
h, w = 原始数据.shape dpi = 100 # 可任意取,只要保证尺寸计算正确即可 plt.figure(figsize=(w/dpi, h/dpi), dpi=dpi) plt.imshow(预处理好的RGBA数组) plt.axis('off') plt.savefig(imgpath, bbox_inches='tight', pad_inches=0)
2. plt.imsave 运行逻辑
你遇到的色图不一致问题,核心来自以下两个隐式处理逻辑:
- 如果你调用
plt.imsave时传入的是单通道原始数组:plt.imsave默认会基于传入数组的最小值、最大值做自动归一化,完全忽略你外部定义的norm实例,只有显式给plt.imsave传入vmin=2, vmax=42, cmap=cmap参数,才能得到和预处理一致的色阶效果。 - 如果你调用
plt.imsave时传入的是预处理好的RGBA数组:需要确认你的原始数据中是否存在超出vmin=2, vmax=42范围的值,cmap处理超出范围的数值时默认会钳位到色阶两端,但部分旧版本matplotlib的imsave对浮点型RGBA数组的数值范围校验逻辑和imshow不一致,若存在超出0~1范围的数值会出现颜色偏移。
另外你提到的“plt.imsave没有cmap参数”是误解,当传入单通道数组时,plt.imsave支持传入cmap、vmin、vmax参数直接完成色图映射,无需提前手动转RGBA,参考写法:
plt.imsave(imgpath, arr=原始数据, cmap=cmap, vmin=2, vmax=42, format='png')
3. 直接给plt.imshow传cmap出现相同问题的原因
当你不给plt.imshow传入norm实例,仅传cmap时,plt.imshow同样会默认基于传入数组的最小、最大值做自动归一化,不会复用你外部定义的norm参数,需要显式传入norm=norm才能保证色阶和你预期一致。
内容的提问来源于stack exchange,提问作者ozmanda
相关产品推荐
相关产品推荐

