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

如何使用Pillow正确显示16位深度的灰度图像?

问题分析

你遇到的是PIL对16位深度灰度PNG的显示兼容性问题:

  • 该图像模式为I;16(16位无符号灰度),PIL的show()方法默认处理这类高深度图像时,未做灰度值的缩放映射,直接将16位数据按8位逻辑显示(0-255为有效范围,超出部分直接显示纯白,低于则纯黑),导致出现纯黑白异常。
  • Notebook的display函数和Aseprite重存后能正常显示,是因为前者会自动处理高深度图像的灰度映射,后者则将图像转为8位灰度后保存,避开了PIL的显示缺陷。
解决方案

以下几种方法可以解决这个问题:

方法1:手动将16位灰度映射为8位灰度

通过线性缩放把16位的0-65535范围值转换为8位的0-255范围,再显示:

from PIL import Image
import numpy as np

# 打开图像
img = Image.open('image.png')
# 确认图像模式(应该输出 I;16 或类似)
print(img.mode)

# 仅针对16位灰度图处理
if img.mode.startswith('I;16'):
    # 转为numpy数组进行缩放
    img_arr = np.array(img)
    # 线性映射到0-255
    img_8bit = ((img_arr / 65535) * 255).astype(np.uint8)
    # 转回PIL图像并显示
    img_8bit_pil = Image.fromarray(img_8bit, mode='L')
    img_8bit_pil.show()
else:
    img.show()

方法2:用Matplotlib替代PIL的show()方法

Matplotlib能正确识别16位灰度的取值范围,直接显示原始灰度:

from PIL import Image
import matplotlib.pyplot as plt

img = Image.open('image.png')
# 用灰度色图,并指定16位的取值范围
plt.imshow(img, cmap='gray', vmin=0, vmax=65535)
# 隐藏坐标轴
plt.axis('off')
plt.show()

方法3:修改PIL的转换逻辑

使用convert方法时指定转换参数,确保16位到8位的正确映射:

from PIL import Image

img = Image.open('image.png')
# 将16位灰度转为8位灰度,通过浮点模式中转保证精度
img_8bit = img.convert('L', mode='F')
img_8bit.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:47:04