You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

plt.savefig保存图像后尺寸缩小、画质降低的原因及解决方案咨询

问题成因与解决方案

一、问题根源分析

你的代码里有三个核心问题导致保存的图像尺寸缩小、画质下降:

  • 默认画布尺寸不匹配plt.subplots()默认创建的画布是6x4英寸(对应432x288像素,72dpi),和你1026×824的原图尺寸完全不符,所有绘图内容都会被缩放到这个小画布上。
  • 重复调用imshow与坐标轴设置冲突:你先设置了ax.imshow(img, extent=[0, 1024, 0, 768]),之后又调用了ax.imshow(img),后者会覆盖前者的extent设置;同时你手动设置的xlim(0,1024)ylim(0,768)和原图1026×824的像素范围不匹配,导致图像被裁剪或缩放。
  • 保存时未指定匹配的dpi和尺寸plt.savefig()默认使用画布的默认dpi(72),最终输出的像素尺寸就是画布英寸数×dpi,自然远小于原图。

二、修正后的代码

下面是调整后的代码,能保证保存的newimage.png和原图尺寸、画质一致:

from PIL import Image
import matplotlib.pyplot as plt

# 加载原图并获取关键参数
img = Image.open("./Python/img/img.png")
img_width, img_height = img.size
# 获取原图dpi(如果原图有记录的话,没有则手动指定,比如100)
img_dpi = img.info.get('dpi', (100, 100))[0]

# 创建和原图尺寸匹配的画布:figsize单位是英寸,计算方式为 像素尺寸/dpi
fig, ax = plt.subplots(figsize=(img_width/img_dpi, img_height/img_dpi), dpi=img_dpi)

# 绘制原图,不需要extent,让坐标轴匹配图像像素
ax.imshow(img)

# 绘制散点图,使用图像的像素坐标
x = [10, 300, 100, 400]
y = [100, 250, 450, 600]
scatter = ax.scatter(x, y, s=100, alpha=1)

# 保持y轴方向和图像一致(图像的y轴原点在左上角)
ax.invert_yaxis()
ax.xaxis.tick_top()

# 关闭坐标轴(如果不需要显示刻度的话,需要的话可以保留)
plt.axis('off')

# 保存图像时,指定dpi和避免额外边距
plt.savefig("./Python/img/newimage.png", dpi=img_dpi, bbox_inches='tight', pad_inches=0)
plt.show()

三、关键修改点说明

  • 匹配画布尺寸:根据原图的像素尺寸和dpi计算画布的figsize,确保画布大小和原图完全一致。
  • 移除重复的imshow调用:只调用一次ax.imshow(img),避免覆盖设置。
  • 保存参数优化
    • dpi=img_dpi:确保保存时的分辨率和原图一致;
    • bbox_inches='tight'pad_inches=0:去除matplotlib默认添加的边距,避免图像被裁剪。

内容的提问来源于stack exchange,提问作者vojtam

火山引擎 最新活动