tsorn tsorn - 7 months ago 20
Python Question

PIL/Pillow convert Image to list and back again

I'm trying to open an RGB picture, convert it to grayscale, then represent it as a list of floats scaled from 0 to 1. At last, I want to convert it back again to an Image. However, in the code below, something in my conversion procedure fails, as

img.show()
(the original image) displays correctly while
img2.show()
display an all black picture. What am I missing?

import numpy as np
from PIL import Image

ocr_img_path = "./ocr-test.jpg"

# Open image, convert to grayscale
img = Image.open(ocr_img_path).convert("L")

# Convert to list
img_data = img.getdata()
img_as_list = np.asarray(img_data, dtype=float) / 255
img_as_list = img_as_list.reshape(img.size)

# Convert back to image
img_mul = img_as_list * 255
img_ints = np.rint(img_mul)
img2 = Image.new("L", img_as_list.shape)
img2.putdata(img_ints.astype(int))

img.show()
img2.show()


The image used

Answer

The solution is to flatten the array before putting it into the image. I think PIL interprets multidimensional arrays as different color bands.

img2.putdata(img_ints.astype(int).flatten())

For a more efficient way of loading images, check out

https://blog.eduardovalle.com/2015/08/25/input-images-theano/

but use image.tobytes() (Pillow) instead of image.tostring() (PIL). .