You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PIL Image加载保存图像时像素值异常变化问题解决

结论

你的猜测不成立,像素值偏差不是PIL自动归一化导致的,不存在可关闭的PIL自动归一化开关,问题根源是使用JPG格式保存二值掩码。

原因分析
  • JPG是有损压缩格式,设计目标是压缩自然摄影图像,会通过丢弃高频信息、量化相邻像素值的方式减小文件体积,这个过程会不可逆地修改原始像素值。你生成的掩码只有0、1两个取值,属于对像素精度要求极高的标注数据,JPG压缩时会在0和1的像素交界处生成大量中间值,重新加载后即使经过数值截断,像素分布也会和原始值产生极大差异。
  • 从你给出的运行结果也能佐证问题:第一次统计像素总数为148148+39352=187500,刚好等于2502503的三通道图像总像素数;第二次统计总数为62288+212=62500,仅为250*250的单通道像素数,说明你读取图像的代码本身也存在错误,进一步放大了数值偏差。
  • PIL处理uint8类型的图像数组时,不会主动做归一化操作,Image.fromarray会直接读取数组的原始像素值,没有默认开启的自动数值处理逻辑。
修复方案
  • 禁止使用JPG格式存储分割掩码、标注类对像素精度有严格要求的数据,替换为PNG等无损压缩格式,这也是图像分割领域保存掩码的通用规范。如果不需要可视化,也可以直接将数组/张量保存为npy、pt格式,完全避免格式转换的损耗。
  • 修正代码中的错误读取接口,PIL读取本地图像应使用Image.open()方法,不存在PIL.create()的官方读取接口。
  • 修正后的可运行代码如下:
import torch
import numpy as np
from PIL import Image

# 生成二值掩码
tensor_img = torch.where(torch.Tensor(250, 250, 3) > 0, 1, 0)
img_arr = tensor_img.numpy().astype(np.uint8)
print(np.unique(img_arr, return_counts=True))

# 无损保存为PNG格式
img = Image.fromarray(img_arr)
img.save("tmp.png")

# 正确读取图像
img = Image.open("tmp.png")
print(torch.tensor(np.array(img)).unique(return_counts=True))

运行上述代码后,重新加载的掩码像素分布会和原始值完全一致。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 14:21:08