
Matplotlib 默认保存图像时会因 DPI 设置、后端压缩及 bbox_inches 处理导致尺寸失真;正确做法是禁用自动缩放、显式指定 DPI 并选用无损格式(如 PNG),同时通过 pil_kwargs 精确控制保存行为。
matplotlib 默认保存图像时会因 dpi 设置、后端压缩及 bbox_inches 处理导致尺寸失真;正确做法是禁用自动缩放、显式指定 dpi 并选用无损格式(如 png),同时通过 `pil_kwargs` 精确控制保存行为。
在使用 Matplotlib 的 plt.savefig() 保存图像时,原始像素尺寸丢失(如从 (1224, 370) 变为 (948, 284))并非偶然——这是由多个默认参数协同作用导致的常见陷阱。根本原因在于:
- figsize 以英寸为单位,若未按实际像素与 DPI 换算设置,会导致画布物理尺寸失配;
- dpi 参数控制输出分辨率,但 savefig(dpi=120) 并不等价于“保存为 120 DPI 像素图”,而是将 figure 按该 DPI 渲染后栅格化,而 figure 本身尺寸(英寸)若不匹配原始像素,则必然缩放;
- bbox_inches='tight' 会裁剪空白边距,但可能意外引入亚像素插值或边界对齐误差;
- 更关键的是:若文件扩展名未明确指定(如路径中无 .png),Matplotlib 可能回退到 PDF 后端,而 PDF 是矢量格式,其光栅化过程受压缩、采样和设备无关坐标系影响,极易破坏像素级精度。
✅ 正确解决方案(三步到位):
弃用 plt.figure(figsize=...),改用 plt.figure(figsize=(w/dpi, h/dpi), dpi=dpi) 精确匹配像素
例如原始图像为 1224×370 像素,希望以 100 DPI 保存,则设 figsize=(12.24, 3.70),dpi=100。强制使用 PNG 格式并关闭所有干扰项
显式指定 .png 扩展名,并禁用 bbox_inches 和 pad_inches(或设为 0),避免自动裁剪。启用 PIL 级精细控制(关键!)
利用 pil_kwargs 传递 quality=100, optimize=False, compress_level=0(PNG)等参数,彻底绕过 Matplotlib 内部光栅化路径,委托 PIL 直接写入原始像素数据。
以下是修复后的完整代码示例:
Matplotlib Linux版 3.11.1 官方下载,来自 PyPI 官方发布,适合 Python 图表绘制、数据分析、科研可视化和 Jupyter Notebook 环境安装。
import matplotlib.pyplot as plt
from PIL import Image
# 加载原始图像
img = Image.open(r"D:\ML_project\pro\dataset\training\images\000000.png")
width, height = img.size
print(f"原始尺寸: {img.size}") # (1224, 370)
# 创建严格匹配像素的 figure(假设目标 DPI 为 100)
dpi = 100
plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi)
plt.axis('off')
plt.imshow(img, aspect='equal') # aspect='equal' 防止宽高比拉伸
# 关键:显式指定 .png 格式 + 禁用 bbox_inches + 使用 pil_kwargs
plt.savefig(
r"D:\ML_project\pro\dataset2\training\images\000000.png",
dpi=dpi,
bbox_inches='tight',
pad_inches=0,
facecolor='white',
edgecolor='none',
# 下面参数确保 PIL 直接写入,不经过 Matplotlib 光栅化
pil_kwargs={'quality': 100, 'optimize': False, 'compress_level': 0}
)
plt.close() # 及时释放内存
# 验证保存结果
saved_img = Image.open(r"D:\ML_project\pro\dataset2\training\images\000000.png")
print(f"保存后尺寸: {saved_img.size}") # 应仍为 (1224, 370)⚠️ 注意事项:
- 绝对不要依赖 mpl.rcParams['pdf.compression'] = False:PDF 后端本质不适合作为像素级图像保存工具,即使关闭压缩,其坐标系与像素网格仍不一一对应。
- aspect='auto' 会拉伸图像以填满 axes,务必改为 'equal' 或省略(默认即 'equal')。
- Windows 路径中的反斜杠需用原始字符串(r"...")或双斜杠,避免转义错误。
- 若需批量处理,建议直接使用 PIL 进行增强与保存(如 img.save(...)),仅在需要绘图叠加时才用 Matplotlib。
总结:Matplotlib 的 savefig 本质是“渲染 figure → 光栅化 → 写入”,而非“复制像素”。要保留原始尺寸,必须让 figure 物理尺寸(英寸)× DPI = 像素尺寸,并交由 PIL 承担最终写入——这才是可靠、可复现的像素保真方案。

















