kerasloadimage

Keras loaded png appears full black


Png file loaded by Keras appears fully black

I have a set of pngs generated from drawSvg program. They look fine when viewed in a normal image viewer like Paint. But when I load them via keras, the matplotlib imshow shows them fully black.

from keras.preprocessing.image import load_img,img_to_array
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TKAgg')

img_path = "output/L_Profile.png"
img = load_img(img_path, target_size=(100, 100))
print(type(img)) # <class 'PIL.Image.Image'>

x = img_to_array(img)
print(type(x)) # <class 'numpy.ndarray'>
print(x.shape) # (100, 100, 3)
plt.imshow(x) # plt.imshow(x/255.) doesnt work either
plt.show()

L_Profile.png is

enter image description here

In matplotlib show, this appears fully black. Am I doing anything wrong?

Another issue is, the shape (100,100,3) is not what want as I need to pass this to Autoencoder Dense layer. I want this to be (100,100,1). The image ideally should be just plain black and white. I tried to convert by:

img = img.convert('1')
x = img_to_array(img)
print(type(x)) # <class 'numpy.ndarray'>
print(x.shape) # (100, 100, 1)
plt.imshow(x) # plt.imshow(x/255.) doesnt work either
plt.show() # TypeError: Invalid dimensions for image data

Here plt.show() itself errors out. Not sure whats going on.

A simple workflow like opening a b&w png image into keras is not working.


Solution

  • Always be super-careful when using PNGs. PNGs unlike JPEGs may also have an alpha channel. Different software will assume a different background color when rendering a PNG with transparency. In your case the entire L-shape is encoded in the alpha channel and the three color channels are completely empty. Here's how the image looks in Mac's Preview app:

    enter image description here

    Notice that Preview uses a different background color and the problem becomes immediately apparent.

    Also note that if you want to show a grayscale image using imshow, you need to squeeze the last dimension, so that the array shape becomes (100,100).

    Here's how to load the alpha channel:

    img = load_img(img_path, color_mode='rgba', target_size=(100, 100))
    print(type(img)) # <class 'PIL.Image.Image'>
    
    x = img_to_array(img)
    print(type(x)) # <class 'numpy.ndarray'>
    print(x.shape) # (100, 100, 4)
    x = x[:,:,3]
    plt.imshow(x) # plt.imshow(x/255.) doesnt work either
    plt.show()
    

    enter image description here

    The colors in the image are simply the grayscale values mapped using the default color map. You can change the color map using the cmap= parameter of imshow.