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
相关产品推荐
相关产品推荐

