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

使用Numpy与Pillow生成图像:像素0-255转0-1后显示差异排查

问题:Numpy+Pillow生成图像显示不一致的原因

我用Python的Numpy和Pillow库生成示例图像,操作步骤如下:

  • 第一张图像:用np.random.randint(0, 255)生成形状为(16,16,3)的三维数组(像素值范围0-255),再通过PIL.Image.fromarray()转为图像;
  • 第二张图像:将上述数组除以255,把像素值缩放到0-1区间,同样用PIL.Image.fromarray()转换。

我原本预期两张图像显示效果一致,但实际绘图后差异明显,请问问题出在哪里?

附上代码:

import numpy as np
import matplotlib.pyplot as plt
import PIL

img_array_1 = np.random.randint(low=0, high=255, size=(16, 16, 3))
img_0_255 = PIL.Image.fromarray(img_array_1, 'RGB')

img_array_2 = (img_array_1 / 255)
img_0_1 = PIL.Image.fromarray(img_array_2, 'RGB')

plt.subplot(1, 2, 1)
plt.title("像素值0-255")
plt.imshow(img_0_255)

plt.subplot(1, 2, 2)
plt.title("像素值0-1")
plt.imshow(img_0_1)
plt.show()

结果图:两张图像的显示效果差异


核心问题原因

Pillow的Image.fromarray函数对RGB模式的输入数组类型有严格要求:
当指定'RGB'模式时,输入数组必须是uint8(8位无符号整数)类型,对应像素值范围0-255。你生成的img_array_2是浮点类型(float64),传入fromarray并指定'RGB'模式时,Pillow无法正确解析这种类型的数组,导致生成的图像数据异常,最终显示效果和预期完全不同。

另外补充:np.random.randint默认生成int64类型数组,虽然Pillow能兼容处理,但显式指定dtype=np.uint8更符合图像数据规范,可避免潜在问题。


解决方法

要让两张图像显示一致,有两种可行方案:

方案1:直接用Matplotlib显示浮点数组(跳过Pillow转换)

Matplotlib的plt.imshow支持直接解析0-1范围的浮点数组,无需转成Pillow图像:

import numpy as np
import matplotlib.pyplot as plt
import PIL

# 显式指定uint8类型,符合图像数据规范
img_array_1 = np.random.randint(low=0, high=255, size=(16, 16, 3), dtype=np.uint8)
img_0_255 = PIL.Image.fromarray(img_array_1, 'RGB')

# 生成0-1范围的浮点数组
img_array_2 = img_array_1 / 255.0

plt.subplot(1, 2, 1)
plt.title("像素值0-255")
plt.imshow(img_0_255)

plt.subplot(1, 2, 2)
plt.title("像素值0-1")
plt.imshow(img_array_2)  # 直接传递浮点数组给imshow
plt.show()

方案2:将浮点数组转回uint8类型后再转Pillow

如果必须通过Pillow处理,需要先把0-1的浮点数组恢复到0-255范围,再转为uint8类型:

import numpy as np
import matplotlib.pyplot as plt
import PIL

img_array_1 = np.random.randint(low=0, high=255, size=(16, 16, 3), dtype=np.uint8)
img_0_255 = PIL.Image.fromarray(img_array_1, 'RGB')

# 先转回0-255范围,再转uint8类型
img_array_2 = (img_array_1 / 255.0) * 255
img_array_2 = img_array_2.astype(np.uint8)
img_0_1 = PIL.Image.fromarray(img_array_2, 'RGB')

plt.subplot(1, 2, 1)
plt.title("像素值0-255")
plt.imshow(img_0_255)

plt.subplot(1, 2, 2)
plt.title("0-1转回uint8")
plt.imshow(img_0_1)
plt.show()

内容的提问来源于stack exchange,提问作者Saber Vatankhah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:27:20