从PIL图像获取32位RGBA numpy数组

4 投票
1 回答
6897 浏览
提问于 2025-04-18 18:46

假设我加载了一张图片,代码是:

> image = Image.open('temp.png')

<PngImagePlugin.PngImageFile image mode=RGBA size=1200x600 at 0x112F0C488>

注意,这张图片的尺寸是 1200x600

我想把这张图片转成一个二维的 numpy 数组,每个元素存放一个32位的整数。

如果我这样做:

np.array(image).shape

我得到的是:

(600,1200, 4)

我该如何把它转换成一个 32 位的 RGBA 二维 numpy 数组呢?

1 个回答

5

1. 索引

你可能对NumPy处理图像的索引方式有些误解。NumPy更喜欢使用一种叫做行优先索引的方式来处理图像,这种方式的顺序是(y, x, c),具体原因可以参考这里的说明

使用[列优先索引]的缺点是可能会影响性能。通常在处理数组时,数据是按顺序访问的,这可以是隐式的(在数组操作中)或者显式的(通过循环访问图像的行)。如果这样做,数据的访问顺序就会变得不理想。随着第一个索引的增加,实际上是访问了内存中相隔很远的元素,这样的内存访问速度通常很慢。

如果你更喜欢使用列优先索引(x, y, c),并且不介意可能的性能损失,那么可以使用numpy.transpose来调整索引的顺序:

np.array(image).transpose((1, 0, 2))

不过,NumPy的文档建议你还是习惯这种方式:

我们建议你学习在访问数组元素时反转索引的常规顺序。虽然这可能有点不习惯,但这更符合Python的语义和数据的自然顺序。

2. 颜色通道

数组的第三个轴表示每个像素的4个颜色通道,分别是(红色, 绿色, 蓝色, 透明度)。对于大多数应用来说,这比单个32位数字更有用。例如,你可以通过写image[...,3]来提取透明度通道。

如果你真的想要32位的颜色值,可以使用ndarray.view方法来查看相同的图像数据,但使用不同的dtype,然后使用numpy.reshape来去掉最后一个轴(因为它现在是多余的):

a = np.array(image)
a.view(dtype=np.uint32).reshape(a.shape[:-1])

撰写回答