关于python:如何将PIL图像转换为numpy数组?

How to convert a PIL Image into a numpy array?

好吧,我在玩弄把pil图像对象来回转换成一个numpy数组,这样我就可以进行比pil的PixelAccess对象所允许的更快的逐像素转换。我已经了解了如何通过以下方式将像素信息放置在一个有用的三维numpy数组中:

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

但是,在我完成了所有出色的转换之后,我似乎还不知道如何将它重新加载到pil对象中。我知道putdata()方法,但似乎不能让它正常工作。


你不是说putdata()的行为到底有多不正常。我假设你在做

1
2
3
4
5
>>> 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数组。这个

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

会有用的,但很慢。

从pil 1.1.6开始,在图像和numpy数组之间转换的"正确"方法很简单

1
>>> pix = numpy.array(pic)

虽然结果数组的格式与您的不同(在本例中为三维数组或行/列/rgb)。

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


以数组形式打开I

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

I做点什么,然后把它转换回图像:

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

用fft、python过滤麻木的图像

如果出于某种原因想要显式地执行此操作,那么在correlation.zip中的该页上有使用getdata()的pil2array()和array2pil()函数。


我在python 3.5中使用了枕头4.1.1(PIL的继承者)。枕头和麻木之间的转换很简单。

1
2
3
4
5
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)

需要注意的一件事是,枕头式的im是柱大调,而麻木式的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格式。


您需要通过以下方式将图像转换为numpy数组:

1
2
3
4
5
import numpy
import PIL

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


我今天使用的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)


1
2
3
4
5
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

您可以将图像转换为numpy通过将图像解析为numpy()函数,然后挤压出特征(非规范化)


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

在我的例子中,我需要存储在数据库表的blob列中的图像:

1
2
3
4
5
def select_all_X_values(conn):
    cur = conn.cursor()
    cur.execute("SELECT ImageData from PiecesTable")    
    rows = cur.fetchall()    
    return rows

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

在这之后,我可以在我的神经网络中使用字节射线。

1
plt.imshow(imagesList[0])