PIL TypeError: Cannot handle this data type

Question:

I have an image stored in a numpy array that I want to convert to PIL.Image in order to perform an interpolation only available with PIL.

When trying to convert it through Image.fromarray() it raises the following error:

TypeError: Cannot handle this data type

I have read the answers here and here but they do not seem to help in my situation.

What I’m trying to run:

from PIL import Image

x  # a numpy array representing an image, shape: (256, 256, 3)

Image.fromarray(x)
Asked By: Jerome

||

Answers:

tl;dr

Does x contain uint values in [0, 255]? If not and especially if x ranges from 0 to 1, that is the reason for the error.


Explanation

Most image libraries (e.g. matplotlib, opencv, scikit-image) have two ways of representing images:

  • as uint with values ranging from 0 to 255.
  • as float with values ranging from 0 to 1.

The latter is more convenient when performing operations between images and thus is more popular in the field of Computer Vision.
However PIL seems to not support it for RGB images.

If you take a look here
it seems that when you try to read an image from an array, if the array has a shape of (height, width, 3) it automatically assumes it’s an RGB image and expects it to have a dtype of uint8!
In your case, however, you have an RBG image with float values from 0 to 1.


Solution

You can fix it by converting your image to the format expected by PIL:

im = Image.fromarray((x * 255).astype(np.uint8))
Answered By: Djib2011

I solved it different way.

Problem Situation:
When working with gray image or binary image, if the numpy array shape is (height, width, 1), this error will be raised also.
For example, a 32 by 32 pixel gray image (value 0 to 255)

np_img = np.random.randint(low=0, high=255, size=(32, 32, 1), dtype=np.uint8)
# np_img.shape == (32, 32, 1)
pil_img = Image.fromarray(np_img)

will raise TypeError: Cannot handle this data type: (1, 1, 1), |u1

Solution:

If the image shape is like (32, 32, 1), reduce dimension into (32, 32)

np_img = np.squeeze(np_img, axis=2)  # axis=2 is channel dimension 
pil_img = Image.fromarray(np_img)

This time it works!!

Additionally, please make sure the dtype is uint8(for gray) or bool(for binary).

Answered By: Uzzal Podder

I found a different issue for the same error in my case. The image I used was in RGBA format, so before using fromarray() function just convert it to RGB using the convert() function and it will work perfectly fine.

image_file = Image.open(image_file)
image_file = image_file.convert('RGB')

P.S.: Posting this solution as an initial step, before converting the image to np.

Answered By: Sanyam Gupta

In my case file format of the images was changed to png to jpg. It worked well when I corrected the image format of the error images.

Answered By: Naim Shant

In my case it was only because I forgotted to add the "RGB" arg in the "fromarray" func.

pil_img = Image.fromarray(np_img, 'RGB')

According to the scikit-image‘s documentation, you can convert an image to unsigned byte format, with values in [0, 255] using img_as_ubyte:

from skimage import img_as_ubyte
from PIL import Image

new_image = Image.fromarray(img_as_ubyte(image))
Answered By: SeyedPooya Soofbaf
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.