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




