Comment convertir une image PIL dans un tableau numpy?
-
23-08-2019 - |
Question
D'accord, je suis autour de convertir jouant un objet image PIL et-vient à un tableau numpy pour que je puisse faire quelques pixels plus rapidement par des transformations de pixels que l'objet PixelAccess
de PIL permettrait. J'ai compris comment placer les informations de pixels dans un tableau numpy 3D utile par le biais de:
pic = Image.open("foo.jpg")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)
Mais je ne peux pas sembler comprendre comment le charger de nouveau dans l'objet PIL après que je l'ai fait toutes mes transformations impressionnantes. Je suis au courant de la putdata()
méthode, mais ne peut pas sembler tout à fait pour l'obtenir se comporter.
La solution
Vous ne dites pas exactement comment putdata()
ne se comporte pas. Je suppose que vous faites
>>> 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
En effet, putdata
attend une séquence de triplets et vous donnez un tableau numpy. Ce
>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)
fonctionne, mais il est très lent.
Au PIL 1.1.6, le façon "appropriée" pour convertir entre les images et numpy tableaux est simplement
>>> pix = numpy.array(pic)
bien que la matrice résultante est sous une forme différente de la vôtre (tableau 3-d ou rangées / colonnes / rgb dans ce cas).
Alors, après avoir effectué vos modifications au tableau, vous devriez être en mesure de le faire, soit pic.putdata(pix)
ou créer une nouvelle image avec Image.fromarray(pix)
.
Autres conseils
Ouvrir I
comme un tableau:
>>> I = numpy.asarray(PIL.Image.open('test.jpg'))
Faites des choses à I
, puis, reconvertir en une image:
>>> im = PIL.Image.fromarray(numpy.uint8(I))
Filtre numpy images avec FFT, python
Si vous voulez le faire explicitement pour une raison quelconque, il y a pil2array () et array2pil () à l'aide getdata () sur cette page correlation.zip.
J'utilise Pillow 4.1.1 (le successeur de PIL) en Python 3.5. La conversion entre Pillow et numpy est simple.
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)
Une chose qui a besoin rende compte est que im
style oreiller est colonne-major tout im2arr
numpy style est rangée-major. Cependant, la fonction Image.fromarray
prend déjà cela en considération. Autrement dit, arr2im.size == im.size
et arr2im.mode == im.mode
dans l'exemple ci-dessus.
Nous devons prendre soin du format de données HxWxC lors du traitement des matrices de numpy transformées, par exemple la transformation ne im2arr = np.rollaxis(im2arr, 2, 0)
ou im2arr = np.transpose(im2arr, (2, 0, 1))
au format CxHxW.
Vous devez convertir votre image à un tableau numpy cette façon:
import numpy
import PIL
img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img)
L'exemple, je l'ai utilisé aujourd'hui:
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)
Si votre image est stockée dans un format de Blob (par exemple dans une base de données), vous pouvez utiliser la même technique expliquée par Billal Begueradj pour convertir votre image de Blobs à un tableau d'octets.
Dans mon cas, je besoin de mes images où stockées dans une colonne de blob dans une table db:
def select_all_X_values(conn):
cur = conn.cursor()
cur.execute("SELECT ImageData from PiecesTable")
rows = cur.fetchall()
return rows
J'ai ensuite créé une fonction d'aide pour changer mon jeu de données en 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
Après cela, j'ai pu utiliser les ByteArrays dans mon réseau de neurones.
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()
Vous pouvez transformer l'image en numpy en analysant l'image en fonction numpy () après squishing les caractéristiques (unnormalization)