PIL 图像转数组(numpy 数组到数组)- Python

24

我有一张 .jpg 图片,我想将其转换为Python数组,因为我已经编写了处理纯Python数组的处理程序。

看起来PIL图像支持转换为numpy数组,根据文档,我写了这个:

from PIL import Image
im = Image.open("D:\Prototype\Bikesgray.jpg")
im.show()

print(list(np.asarray(im)))

这将返回一个numpy数组列表。另外,我尝试过使用

list([list(x) for x in np.asarray(im)])

由于失败,它根本没有返回任何内容。

我该如何从PIL转换为数组,或者简单地从numpy数组转换为Python数组?


2
你尝试过使用NumPy数组的tolist()方法吗? - joeln
我们称它们为“列表”,而不是数组,对于原生的Python数据类型来说。“数组”指的是numpy中的东西,或者从“array”标准库模块中获取的内容,或者一些其他第三方库。 - Karl Knechtel
4个回答

23

我强烈建议您使用Image对象的tobytes函数。经过一些时间检查,这样更加高效。

def jpg_image_to_array(image_path):
  """
  Loads JPEG image into 3D Numpy array of shape 
  (width, height, channels)
  """
  with Image.open(image_path) as image:         
    im_arr = np.fromstring(image.tobytes(), dtype=np.uint8)
    im_arr = im_arr.reshape((image.size[1], image.size[0], 3))                                   
  return im_arr

我在笔记本电脑上运行的时间表显示:
In [76]: %timeit np.fromstring(im.tobytes(), dtype=np.uint8)
1000 loops, best of 3: 230 µs per loop

In [77]: %timeit np.array(im.getdata(), dtype=np.uint8)
10 loops, best of 3: 114 ms per loop

```


np.fromstring已被弃用,请使用np.frombuffer代替。 - dexteritas

17

我认为你在寻找的是:

list(im.getdata())

或者,如果图像太大而无法完全加载到内存中,可以像这样处理:

for pixel in iter(im.getdata()):
    print pixel

来自PIL文档:

getdata

im.getdata() => 序列

将图像内容作为序列对象返回,其中包含像素值。序列对象被展平,因此第一行的值直接跟在第零行的值后面,依此类推。

请注意,该方法返回的序列对象是内部PIL数据类型,仅支持某些序列操作,包括迭代和基本序列访问。要将其转换为普通序列(例如用于打印),请使用list(im.getdata())。


文档看起来不错,但仍然无法正常工作。我不得不中止进程。有什么想法吗?谢谢。 - kiriloff
先尝试使用较小的图像,以确定您是否获得了所需的结果,然后再处理由于尝试将整个图像加载到列表并打印而导致的内存问题。 - zenpoy
也许不需要将其转换为列表,只需使用迭代器遍历即可。请参考我的编辑。 - zenpoy
现在很明显:问题在于PIL图像转换为3D numpy数组(或普通的Python数组)。此外,最终我没有所需的强度矩阵。我想这是因为PIL图像以RGB方式编码,具有3个维度。需要将此编码映射到一种表示方法,每个像素都具有独特的表示。您有什么提示吗(同时会查看文档)?谢谢。 - kiriloff
@octoback 正确,.convert('L') 转换为灰度。 - Martin Thoma
显示剩余4条评论

7

基于zenpoy的回答:

import Image
import numpy

def image2pixelarray(filepath):
    """
    Parameters
    ----------
    filepath : str
        Path to an image file

    Returns
    -------
    list
        A list of lists which make it simple to access the greyscale value by
        im[y][x]
    """
    im = Image.open(filepath).convert('L')
    (width, height) = im.size
    greyscale_map = list(im.getdata())
    greyscale_map = numpy.array(greyscale_map)
    greyscale_map = greyscale_map.reshape((height, width))
    return greyscale_map

3
我使用numpy.fromiter来反转8灰度位图,但没有任何副作用的迹象。
import Image
import numpy as np

im = Image.load('foo.jpg')
im = im.convert('L')

arr = np.fromiter(iter(im.getdata()), np.uint8)
arr.resize(im.height, im.width)

arr ^= 0xFF  # invert
inverted_im = Image.fromarray(arr, mode='L')
inverted_im.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接