0

I am reading this picture,

enter image description here

Using the following Python,

import numpy as np
from PIL import Image as im
from matplotlib import pyplot as plt

image = np.array(im.open("optimised.png"))
print(image.shape)
plt.imshow(image)
plt.show()

But this plots a greyscaled image,

enter image description here

Further, the shape is printed as (57, 86) where I expect this to be something like (57, 86, 3).

I opened the image in an image viewer and sure enough, it has color,

enter image description here

What is happening here?

scribe
  • 673
  • 2
  • 6
  • 17
  • Your image is a palette image (a.k.a. Indexed image) see here https://stackoverflow.com/a/52307690/2836621 Matplotlib therefore sees the only the palette indices and thinks it's greyscale, so it applies its `viridis` colourmap. In essence, Ture's explanation is most accurate and Ganesh's implementation is most useful. – Mark Setchell Apr 16 '23 at 07:41
  • Similar question, with answer: https://stackoverflow.com/questions/62983567/png-file-shows-bluish-image-when-using-plt-imshow – Warren Weckesser Apr 16 '23 at 16:26

3 Answers3

2

What is happening, is that your image is an indexed-colour image, i.e. each pixel is stored as a single integer, which acts as an index into a table of colours. When PIL presents the image as a numpy array, you get only this single integer.

If you want RGB for each pixel, converting as suggested in the answer by Ganesh should do the trick. Alternatively, you can dig out the palette with image.getpalette() and apply it yourself with some numpy magic.

Ture Pålsson
  • 6,088
  • 2
  • 12
  • 15
1

I don't have much expertise but, I suspect here, im.open may be taking grayscale mode. May be you need to try .convert after opened.

image = np.array(im.open("optimised.png").convert("RGB"))

Also (57,86) is a 2d arry and when you give 3d array (57,86,3) in this last number 3 represents 3 channels red, blue and green. Hope this helps.

Ganesh Nemade
  • 1,504
  • 12
  • 17
0

No need to convert it to a numpy array

from PIL import Image
import matplotlib.pyplot as plt

image = Image.open("optimised.png")
# To see the image using Pillow
image.show()
# To see the image using matplotlib
plt.imshow(image)
plt.show()

About the function show from Image.

Two images, one using Pillow, the other using matplotlib

David
  • 435
  • 3
  • 12
  • It's the pixel values that I care about. The plotting is just for debugging so I do need the numpy array. – scribe Apr 16 '23 at 05:12