Kaushal28
Kaushal28

Reputation: 543

Can't reshape the numpy array containing PNG images

I've trained a Handwritten image classifier using Keras library in Python. Initially I've used standard MNIST dataset for training and testing purpose. But now I want to use my own data set for testing, in which all the images are size 900*1200*3 instead of 28*28*1

So I need to reshape all the images before testing. I'm using following code to reshape but it give errors.

Code:

bb =  lol.reshape(lol.shape[0], 28, 28, 1).astype('float32')

where lol is my numpy array containing 55 images of shape (900,1200,3)

and the Error log is as following:

ValueError                                Traceback (most recent call last)
<ipython-input-46-87da95da73e9> in <module>()
     24 #     # you can show every image
     25 #     img.show()
---> 26 bb =  lol.reshape(lol.shape[0], 28, 28, 1).astype('float32')
     27 # model = loaded_model
     28 # classes = model.predict(bb)

ValueError: cannot reshape array of size 178200000 into shape (55,28,28,1)

So what am I doing wrong? Can I get accurate predictions even after resizing the large images to very small images of 28*28? Thanks for help.

Upvotes: 0

Views: 4595

Answers (2)

Djib2011
Djib2011

Reputation: 7442

What you are doing is wrong. You can't reshape an array of (55, 900, 1200, 3) into an array of (55, 28, 28, 1), because you are trying to store 55*900*1200*3=178200000 elements in an array that can store only 55*28*28=43120 elements.

You want to do two things:

1) Convert your rgb image (indicated by the last dimension which is the 3 channels) into grayscale (1 channel). The simplest way to do this is (R+B+G)/3. All python libraries that have to do with images (PIL, OpenCV, skimage, tensorflow, keras, etc) have this already implemented. Example:

from skimage.color import rgb2gray
gray = rgb2gray(original)

2) Resize the image from 900x1200 to 28x28. Again you can do this in all major image-related python libraries. Example:

from skimage.transform import resize
resized = resize(gray, (28,28))

Now if you want to do this in all 55 images you can either write a function that transforms one image and map it across your array, or use a simple for loop and populate your new array one image at a time.

In your case the code should look something like this:

num_images = lol.shape[0] # 55 in your case
resized_images = np.zeros(shape=(num_images, 28, 28, 1)) # your final array
for i in range(num_images):
    gray = rgb2gray(lol[i,:,:,:]) # gray.shape should be (900,1200,1)
    resized = resize(gray, (28,28)) # resized.shape should be (28,28,1)
    resized_images[i,:,:,:] = resized # resized_images.shape should be (55,28,28,1)

Upvotes: 2

Colin Dickie
Colin Dickie

Reputation: 910

It would be more intuitive to process each image individually, which would also give you the best chance of preserving some information.

Try using the PIL library:

import numpy
from PIL import Image

lol = numpy.zeros((55,900,1200,3),dtype=numpy.uint8)
new_array = numpy.zeros((lol.shape[0],28,28),dtype=numpy.float32)

for i in range(lol.shape[0]):
    img = Image.fromarray(lol[i])
    img_resize = img.resize((28,28))
    img_mono = img_resize.convert('L')
    arr = numpy.array(img_mono,dtype=numpy.uint8)
    new_array[i] = arr

Upvotes: 1

Related Questions