我有一个形状为 (10000,1296) 的数组 (numpy),我想将其保存为 10,000 张 36x36 大小的图像。数组中的所有值都在 (0,255)
范围内。所以我使用这段代码来做到这一点(效果很好):
for i, line in enumerate(myarray):
img = Image.new('L',(36,36))
img.putdata(line)
img.save(str(i)+'.png')
我想用 Image.fromarray
方法替换此代码,但与原始方法相比,生成的图片变形得面目全非。首先我尝试了这个:
myarray = myarray.reshape(10000,36,36)
for i, line in enumerate(myarray):
img = Image.fromarray(line, 'L')
img.save(str(i)+'.png')
这没用。所以为了调试我想我会尝试一个项目并这样做:
Image.fromarray(myarray[0].reshape(36,36), 'L').save('test.png')
又一次 - 乱码扭曲的图像。
所以我认为 fromarray
没有像我想的那样工作,或者我的 reshape
太天真了,弄乱了数据,但我无法解决这个问题。欢迎任何想法。
最佳答案
PIL 的 L
模式是一种灰度模式,用于表示亮度的数据
(亮度)。数据应为 0 到 255 之间的整数。如果您通过使用 mode='L'
将 NumPy 数组传递给 Image.fromarray
创建 PIL 图像,dtype数组的长度应该是 uint8
。因此使用
myarray = myarray.astype('uint8')
确保传递给 Image.fromarray
的数组具有 dtype uint8
。
uint8
是无符号的 8 位整数。 float32
是 32 位 float 。它们的宽度是 uint8
的 4 倍。 Image.fromarray
将 NumPy 数组中的基础数据视为 uint8
,读取足够的字节来填充图像,并忽略其余部分。所以每个 32 位 float 变成四个 8 位整数,每个 8 位整数为不同的像素着色。
换句话说,以下断言
通过:
import numpy as np
from PIL import Image
line = np.arange(256).reshape(16, 16).astype('float32')
img = Image.fromarray(line, 'L')
line2 = np.asarray(img)
assert (line.view('uint8').ravel()[:256].reshape(16, 16) == line2).all()
这就是为什么在不转换为 uint8
的情况下使用 myarray
会产生乱码图像的原因。
或者,您可以不将 myarray
转换为 uint8
读取 mode='F'
中的数据( float 模式):
import numpy as np
from PIL import Image
line = np.arange(256).reshape(16, 16).astype('float32')
img = Image.fromarray(line, 'F').convert('L')
img.save('/tmp/out.png')
产生
参见 this page获取所有可能的 PIL 模式的列表。
关于python - PIL.Image.fromarray 在 np.reshape 之后产生扭曲的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44996127/