376

好吧,我正在尝试将 PIL 图像对象来回转换为 numpy 数组,这样我就可以进行比 PILPixelAccess对象允许的更快的逐像素转换。我已经想出了如何通过以下方式将像素信息放置在有用的 3D numpy 数组中:

pic = Image.open("foo.jpg")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)

但是在我完成了所有很棒的转换之后,我似乎无法弄清楚如何将它加载回 PIL 对象中。我知道这种putdata()方法,但似乎无法让它发挥作用。

4

8 回答 8

386

你不是说到底是如何putdata()不行为。我假设你在做

>>> pic.putdata(a)
Traceback (most recent call last):
  File "...blablabla.../PIL/Image.py", line 1185, in putdata
    self.im.putdata(data, scale, offset)
SystemError: new style getargs format but argument is not a tuple

这是因为putdata需要一个元组序列,而你给它一个 numpy 数组。这

>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)

会工作,但速度很慢。

从 PIL 1.1.6 开始,在图像和 numpy 数组之间进行转换的“正确”方式很简单

>>> pix = numpy.array(pic)

尽管结果数组的格式与您的格式不同(在这种情况下为 3-d 数组或行/列/rgb)。

然后,在对数组进行更改后,您应该可以pic.putdata(pix)使用Image.fromarray(pix).

于 2008-12-21T20:46:21.473 回答
275

I作为数组打开:

>>> I = numpy.asarray(PIL.Image.open('test.jpg'))

做一些事情I,然后将其转换回图像:

>>> im = PIL.Image.fromarray(numpy.uint8(I))

资料来源:使用 FFT、Python 过滤 numpy 图像

如果您出于某种原因要明确执行此操作,则在此页面上的 correlation.zip 中有使用 getdata() 的 pil2array() 和 array2pil() 函数。

于 2009-07-08T02:33:17.417 回答
106

我在 Python 3.5 中使用 Pillow 4.1.1(PIL 的继任者)。Pillow 和 numpy 之间的转换很简单。

from PIL import Image
import numpy as np
im = Image.open('1.jpg')
im2arr = np.array(im) # im2arr.shape: height x width x channel
arr2im = Image.fromarray(im2arr)

需要注意的一件事是 Pillow-styleim是 column-major 而 numpy-styleim2arr是 row-major。但是,该功能Image.fromarray已经考虑到了这一点。也就是说,arr2im.size == im.sizearr2im.mode == im.mode上面的例子中。

在处理转换后的 numpy 数组时,我们应该注意 HxWxC 数据格式,例如进行转换im2arr = np.rollaxis(im2arr, 2, 0)im2arr = np.transpose(im2arr, (2, 0, 1))转换为 CxHxW 格式。

于 2017-06-17T16:41:07.043 回答
33

您需要以这种方式将图像转换为 numpy 数组:

import numpy
import PIL

img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img) 
于 2016-06-07T09:18:59.997 回答
27

转换Numpy to PIL图像和PIL to Numpy

import numpy as np
from PIL import Image

def pilToNumpy(img):
    return np.array(img)

def NumpyToPil(img):
    return Image.fromarray(img)
于 2020-05-30T17:07:47.443 回答
3

我今天使用的示例:

import PIL
import numpy
from PIL import Image

def resize_image(numpy_array_image, new_height):
    # convert nympy array image to PIL.Image
    image = Image.fromarray(numpy.uint8(numpy_array_image))
    old_width = float(image.size[0])
    old_height = float(image.size[1])
    ratio = float( new_height / old_height)
    new_width = int(old_width * ratio)
    image = image.resize((new_width, new_height), PIL.Image.ANTIALIAS)
    # convert PIL.Image into nympy array back again
    return array(image)
于 2017-02-03T20:32:16.080 回答
0

如果您的图像以 Blob 格式存储(即在数据库中),您可以使用 Billal Begueradj 解释的相同技术将图像从 Blob 转换为字节数组。

就我而言,我需要将图像存储在 db 表的 blob 列中:

def select_all_X_values(conn):
    cur = conn.cursor()
    cur.execute("SELECT ImageData from PiecesTable")    
    rows = cur.fetchall()    
    return rows

然后我创建了一个辅助函数来将我的数据集更改为 np.array:

X_dataset = select_all_X_values(conn)
imagesList = convertToByteIO(np.array(X_dataset))

def convertToByteIO(imagesArray):
    """
    # Converts an array of images into an array of Bytes
    """
    imagesList = []

    for i in range(len(imagesArray)):  
        img = Image.open(BytesIO(imagesArray[i])).convert("RGB")
        imagesList.insert(i, np.array(img))

    return imagesList

在此之后,我能够在我的神经网络中使用 byteArrays。

plt.imshow(imagesList[0])
于 2019-02-15T07:00:21.403 回答
-2
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

您可以通过在挤压出特征(非标准化)后将图像解析为 numpy() 函数来将图像转换为 numpy

于 2019-05-25T14:56:25.640 回答