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

Posted

技术标签:

【中文标题】PIL 图像到数组(numpy 数组到数组) - Python【英文标题】:PIL image to array (numpy array to array) - Python 【发布时间】:2012-11-13 01:48:45 【问题描述】:

我有一个 .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 数组?

【问题讨论】:

你试过numpy数组的tolist()方法吗? 【参考方案1】:

基于zenpoy's answer:

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

【讨论】:

【参考方案2】:

我强烈建议您使用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【参考方案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()

【讨论】:

【参考方案4】:

我认为您正在寻找的是:

list(im.getdata())

或者,如果图像太大而无法完全加载到内存中,则类似这样:

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

来自PIL documentation:

获取数据

im.getdata() => 序列

将图像的内容作为包含像素的序列对象返回 价值观。序列对象被展平,因此第一行的值 紧跟在第 0 行的值之后,依此类推。

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

【讨论】:

在文档中看起来不错,但仍然无法正常工作。我不得不中止进程。任何想法?谢谢 先尝试使用较小的图像,只是为了看到您得到了想要的结果,然后您可以处理由于尝试将整个图像加载到列表中并打印它而引起的内存问题。跨度> 也许不是将其转换为列表,而是使用迭代器遍历它。查看我的编辑 感谢更新。我希望我能有相应的强度矩阵(二维数组),所以我尝试了for x in im_array: matrix.append(list(x)) print matrix,它希望我再次中止 python.exe 现在这很明显:问题是 PIL 图像转换为 3d numpy 数组(或纯 Python 数组)。另外,我最后没有我想要的强度矩阵。我猜这是因为 PIL 图像以 RGB 方式编码,具有 3 个维度。需要将此编码映射到每个像素具有唯一表示的表示。您有提示吗(同时会查看文档)?谢谢

以上是关于PIL 图像到数组(numpy 数组到数组) - Python的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PIL 图像转换为 numpy 数组?

PIL打开图像的numpy数组中的元素数量错误

如何将 NumPy 数组转换为应用 matplotlib 颜色图的 PIL 图像

如何使用 PIL 对 numpy 数组进行编码,例如 opencv 的 cv2.imencode()?

将 Numpy 数组保存为图像

重新采样表示图像的 numpy 数组