I have a .jpg image that I would like to convert to Python array, because I implemented treatment routines handling plain Python arrays.
It seems that PIL images support conversion to numpy array, and according to the documentation I have written this:
from PIL import Image
im = Image.open("D:\Prototype\Bikesgray.jpg")
im.show()
print(list(np.asarray(im)))
This is returning a list of numpy arrays. Also, I tried with
list([list(x) for x in np.asarray(im)])
which is returning nothing at all since it is failing.
How can I convert from PIL to array, or simply from numpy array to Python array?
I think what you are looking for is:
list(im.getdata())
or, if the image is too big to load entirely into memory, so something like that:
for pixel in iter(im.getdata()):
print pixel
from PIL documentation:
getdata
im.getdata() => sequence
Returns the contents of an image as a sequence object containing pixel
values. The sequence object is flattened, so that values for line one
follow directly after the values of line zero, and so on.
Note that the sequence object returned by this method is an internal
PIL data type, which only supports certain sequence operations,
including iteration and basic sequence access. To convert it to an
ordinary sequence (e.g. for printing), use list(im.getdata()).
I highly recommend you use the tobytes
function of the Image
object. After some timing checks this is much more efficient.
def jpg_image_to_array(image_path):
"""
Loads JPEG image into 3D Numpy array of shape
(width, height, channels)
"""
with Image.open(image_path) as image:
im_arr = np.fromstring(image.tobytes(), dtype=np.uint8)
im_arr = im_arr.reshape((image.size[1], image.size[0], 3))
return im_arr
The timings I ran on my laptop show
In [76]: %timeit np.fromstring(im.tobytes(), dtype=np.uint8)
1000 loops, best of 3: 230 µs per loop
In [77]: %timeit np.array(im.getdata(), dtype=np.uint8)
10 loops, best of 3: 114 ms per loop
```
Based on zenpoy's answer:
import Image
import numpy
def image2pixelarray(filepath):
"""
Parameters
----------
filepath : str
Path to an image file
Returns
-------
list
A list of lists which make it simple to access the greyscale value by
im[y][x]
"""
im = Image.open(filepath).convert('L')
(width, height) = im.size
greyscale_map = list(im.getdata())
greyscale_map = numpy.array(greyscale_map)
greyscale_map = greyscale_map.reshape((height, width))
return greyscale_map
I use numpy.fromiter to invert a 8-greyscale bitmap, yet no signs of side-effects
import Image
import numpy as np
im = Image.load('foo.jpg')
im = im.convert('L')
arr = np.fromiter(iter(im.getdata()), np.uint8)
arr.resize(im.height, im.width)
arr ^= 0xFF # invert
inverted_im = Image.fromarray(arr, mode='L')
inverted_im.show()