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

Python 如何将PIL图像转换为numpy数组?,python,image,numpy,python-imaging-library,numpy-ndarray,Python,Image,Numpy,Python Imaging Library,Numpy Ndarray,好的,我正在玩弄如何将一个PIL图像对象来回转换为一个numpy数组,这样我可以做一些比PIL的PixelAccess对象更快的逐像素转换。我已经通过以下方式了解了如何将像素信息放置在有用的3D numpy阵列中: pic = Image.open("foo.jpg") pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3) 但在我完成了所有很棒的转换之后,我似乎不知道如何将其加载回PIL对象。我知道putda

好的,我正在玩弄如何将一个PIL图像对象来回转换为一个numpy数组,这样我可以做一些比PIL的
PixelAccess
对象更快的逐像素转换。我已经通过以下方式了解了如何将像素信息放置在有用的3D numpy阵列中:

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

但在我完成了所有很棒的转换之后,我似乎不知道如何将其加载回PIL对象。我知道
putdata()
方法,但似乎无法让它正常工作。

您并不是说
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开始,简单来说

>>> pix = numpy.array(pic)
尽管生成的数组的格式与您的不同(在本例中为三维数组或行/列/rgb)


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

以数组形式打开
I

>>> I = numpy.asarray(PIL.Image.open('test.jpg'))
I
执行一些操作,然后将其转换回图像:

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


如果出于某种原因要显式执行此操作,则correlation.zip中有使用getdata()的pil2array()和array2pil()函数。

您需要通过以下方式将图像转换为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)
我在Python3.5中使用Pillow4.1.1(PIL的继承者)。枕头和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)
需要注意的一点是,枕头样式
im
是列主调,而numpy样式
im2arr
是行主调。但是,函数
Image.fromarray
已经考虑到了这一点。也就是说,在上述示例中,
arr2im.size==im.size
arr2im.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
在这之后,我能够在我的神经网络中使用ByteArray

plt.imshow(imagesList[0])
可以将图像转换为numpy
通过在挤出特征(非规范化)后将图像解析为numpy()函数,将
numpy转换为PIL
图像和
PIL转换为numpy

import numpy as np
from PIL import Image

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

def NumpyToPil(img):
    return Image.fromarray(img)

首先,它不应该是pic.putdata(数据)吗?而numpy.asarray(pic)生成一个只读数组,所以您需要调用numpy.array(pic),而您没有回答这个问题。。。从您提供的链接来看,它似乎是pic=Image.fromarray(pix)。修正你的答案,我会接受它。谢谢这张…
图片。FROMARY
没有列在PIL文档(!)中,所以如果不是因为这个,我永远也找不到它。该页面将
numpy.asarray(pic)
列为转换的“正确”方式,而不是
numpy.array(pic)
。按照<代码>数组< /代码>将生成一个副本,而 AsStase将不会(但是<<代码> Asase结果将是只读的)。这里警告(从我自己的错误):您还需要考虑数据的规模和范围。在许多使用情况下,您会使用0-255字节渲染图像,但您可能希望这些图像在numpy数组中转换为例如0.0-1.0。来自uint8的某些单位转换可以做到这一点,但在本例中,它不能。。所以请检查:)第二个答案更好。@ArditS::您是不是先导入图像的?是否安装了PIL?是否需要进行
uint8
转换?
numpy.asarray(Image.open(filename))
似乎适用于.jpg图像,但不适用于.png。结果显示为
数组(,dtype=object)
。似乎没有明显命名的
PngImagePlugin.PngImageFile
对象方法来解决这个问题。我想我应该把这个问题作为一个新问题来问,但它与这个主题非常相关。有人知道这里出了什么问题吗?@Rebs:这就是为什么速度要快得多的原因:
getdata()
返回一个类似object()的序列,但是枕头图像实现了
\uuuuu数组\uu接口
,它可以使用
numpy
访问图像的原始字节,而不必通过迭代器(请参阅和)。您甚至可以使用
numpy.array(PIL.Image.open('test.jpg'))
@jez在将图像对象转换为numpy之前检查图像对象是否已关闭。同样的情况也发生在我身上,我发现我在某处关闭了图像对象。这种转换方式保留了图像,但会导致颜色丢失。无论如何,为了避免颜色丢失?@moondra如果我理解你的问题,你可以用
替换
。convert(“L”)
。convert(“RGB”)
“L”生成灰度图像,即
pic.size[0]
pic.size[1]
应该交换(即
重塑(pic.size[1],pic.size[0],3)
),因为
size
width x height
x*y
,而矩阵排序是
rows x columns
。这是最干净的示例,包括导入语句(感谢您提供的详细信息)。让我们投票表决这个答案,以提高可见性。我发现,当我将PIL绘制的图像转换为numpy数组时,在数组上使用matplotlib imshow时,它显示为颠倒的,需要使用
np.flipud
进行修复。虽然我的PIL图像是使用
ImageDraw.Draw
从头开始创建的。我认为人们必须小心他们坐标的来源。
import numpy as np
from PIL import Image

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

def NumpyToPil(img):
    return Image.fromarray(img)