Alright, I\'m toying around with converting a PIL image object back and forth to a numpy array so I can do some faster pixel by pixel transformations than PIL\'s PixelAccess
object would allow. I\'ve figured out how to place the pixel information in a useful 3D numpy array by way of:
pic = Image.open(\"foo.jpg\")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)
But I can\'t seem to figure out how to load it back into the PIL object after I\'ve done all my awesome transforms. I\'m aware of the putdata()
method, but can\'t quite seem to get it to behave.
You\'re not saying how exactly putdata()
is not behaving. I\'m assuming you\'re doing
>>> 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
This is because putdata
expects a sequence of tuples and you\'re giving it a numpy array. This
>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)
will work but it is very slow.
As of PIL 1.1.6, the \"proper\" way to convert between images and numpy arrays is simply
>>> pix = numpy.array(pic)
although the resulting array is in a different format than yours (3-d array or rows/columns/rgb in this case).
Then, after you make your changes to the array, you should be able to do either pic.putdata(pix)
or create a new image with Image.fromarray(pix)
.
Open I
as an array:
>>> I = numpy.asarray(PIL.Image.open(\'test.jpg\'))
Do some stuff to I
, then, convert it back to an image:
>>> im = PIL.Image.fromarray(numpy.uint8(I))
Filter numpy images with FFT, Python
If you want to do it explicitly for some reason, there are pil2array() and array2pil() functions using getdata() on this page in correlation.zip.
I am using Pillow 4.1.1 (the successor of PIL) in Python 3.5. The conversion between Pillow and numpy is straightforward.
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)
One thing that needs noticing is that Pillow-style im
is column-major while numpy-style im2arr
is row-major. However, the function Image.fromarray
already takes this into consideration. That is, arr2im.size == im.size
and arr2im.mode == im.mode
in the above example.
We should take care of the HxWxC data format when processing the transformed numpy arrays, e.g. do the transform im2arr = np.rollaxis(im2arr, 2, 0)
or im2arr = np.transpose(im2arr, (2, 0, 1))
into CxHxW format.
You need to convert your image to a numpy array this way:
import numpy
import PIL
img = PIL.Image.open(\"foo.jpg\").convert(\"L\")
imgarr = numpy.array(img)
The example, I have used today:
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)