PIL Image convert from I mode to P mode

1.9k Views Asked by At

I have this depth image:

enter image description here

that I load with PIL like:

depth_image = Image.open('stereo.png')

If I print the mode of the image it shows mode I, that is (32-bit signed integer pixels) according to the documentation.

This is correct since the image values range from 0 to 255. I'd like to colorize this depth image for better visualization so I tried to convert it to P mode with a palette like:

depth_image = depth_image.convert('P', palette=custom_palette)
depth_image.save("colorized.png")

But the result is a black and white image like this:

enter image description here

I'm sure the palette is ok, since there are 256 colors in int format all in a single array.

I've tried to convert it to RGB before saving like:

depth_image = depth_image.convert('RGB')

Also I tried adding the palette afterwards like:

depth_image = depth_image.putpalette(custom_palette)

And if I try to save it without converting it to RGB I get a:

    depth_image.save("here.png")
AttributeError: 'NoneType' object has no attribute 'save'

So far I'll try converting the image to a numpy array and then map the colors from there, but I was wondering what was I missing out regarding PIL. I was looking around the documentation but didn't find much regarding I to P conversion.

1

There are 1 best solutions below

1
On BEST ANSWER

I think the issue is that your values are scaled to the range 0..65535 rather than 0..255.

If you do this, you will see the values are larger than you expected:

i = Image.open('depth.png') 
n = np.array(i) 

print(n.max(),n.mean())
# prints 32257, 6437.173

So, I quickly tried:

n = (n/256).astype(np.uint8)
r = Image.fromarray(n)
r=r.convert('P') 
r.putpalette(custom_palette)     # I grabbed this from your pastebin

enter image description here