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

如何将PIL的Image来回转换为NumPy数组,以便我可以比PIL的PixelAccess更快地进行逐像素转换?我可以通过以下方式将其转换为NumPy数组:

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

但我如何加载它回到PIL Image后,我已经修改了数组?pic.putdata()不能正常工作。

755744 次浏览

你没有说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开始,“proper"在图像和numpy数组之间转换的方法是简单的

>>> pix = numpy.array(pic)

尽管结果数组的格式与您的不同(在这种情况下是3d数组或rows/columns/rgb)。

然后,在对数组进行更改之后,你应该能够执行pic.putdata(pix)或使用Image.fromarray(pix)创建一个新图像。

I作为数组打开:

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

I执行一些操作,然后将其转换回图像:

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

来源:使用FFT, Python过滤numpy图像

如果你出于某种原因想显式地做它,有pil2array()和array2pil()函数使用getdata()在correlation.zip中的这个页面上。

你需要将你的图像转换为numpy数组:

import numpy
import PIL


img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img)

我今天用的例子是:

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)

我使用的是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风格的im是列为主,而numpy风格的im2arr是行为主。然而,函数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格式。

如果你的图像以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

然后我创建了一个helper函数来将我的数据集更改为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])
def imshow(img):
img = img / 2 + 0.5     # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()

您可以将图像转换为numpy 通过将图像解析为numpy()函数后压除特征(非归一化)

转换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)