Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keras: model.predict for a single image

I'd like to make a prediction for a single image with Keras. I've trained my model so I'm just loading the weights.

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
import numpy as np
import cv2

# dimensions of our images.
img_width, img_height = 150, 150



def create_model():
  if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
  else:
    input_shape = (img_width, img_height, 3)

  model = Sequential()
  model.add(Conv2D(32, (3, 3), input_shape=input_shape))
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))

  model.add(Conv2D(32, (3, 3)))
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))

  model.add(Conv2D(64, (3, 3)))
  model.add(Activation('relu'))
  model.add(MaxPooling2D(pool_size=(2, 2)))

  model.add(Flatten())
  model.add(Dense(64))
  model.add(Activation('relu'))
  model.add(Dropout(0.5))
  model.add(Dense(1))
  model.add(Activation('sigmoid'))

  return model


img = cv2.imread('./test1/1.jpg')
model = create_model()
model.load_weights('./weight.h5')
model.predict(img)

I'm loading the image using:

img = cv2.imread('./test1/1.jpg')

And using the predict function of the model:

 model.predict(img)

But I get the error:

ValueError: Error when checking : expected conv2d_1_input to have 4 dimensions, but got array with shape (499, 381, 3)

How should I proceed to have predictions on a single image ?

like image 238
Graham Slick Avatar asked Mar 25 '17 13:03

Graham Slick


People also ask

Does keras predict use GPU?

keras models will transparently run on a single GPU with no code changes required.


4 Answers

Since you trained your model on mini-batches, your input is a tensor of shape [batch_size, image_width, image_height, number_of_channels].

When predicting, you have to respect this shape even if you have only one image. Your input should be of shape: [1, image_width, image_height, number_of_channels].

You can do this in numpy easily. Let's say you have a single 5x5x3 image:

    >>> x = np.random.randint(0,10,(5,5,3))
    >>> x.shape
    >>> (5, 5, 3)
    >>> x = np.expand_dims(x, axis=0)
    >>> x.shape
    >>> (1, 5, 5, 3)

Now x is a rank 4 tensor!

like image 109
vega Avatar answered Oct 04 '22 09:10

vega


Even though this doesn't solve your error, make sure and rescale your image if you have done that previously. For instance, my training generator looks like:

train_datagen = ImageDataGenerator(
   rotation_range=40,
   zoom_range=[0.7, 0.9],
   horizontal_flip=True,
   rescale=1./255
)

So when I go to predict a single image:

from PIL import Image
import numpy as np
from skimage import transform
def load(filename):
   np_image = Image.open(filename)
   np_image = np.array(np_image).astype('float32')/255
   np_image = transform.resize(np_image, (256, 256, 3))
   np_image = np.expand_dims(np_image, axis=0)
   return np_image

 image = load('my_file.jpg')
 model.predict(image)

I have to also rescale it by 255.

like image 36
VocoJax Avatar answered Oct 04 '22 08:10

VocoJax


You can load the image with desired width and height, convert it to a numpy array with the shape of (image_width, image_height, number_of_channels) and then change the shape of the array to (1, image_width, image_height, number_of_channels). (batch_size =1)

import numpy as np
from keras.preprocessing import image

img_width, img_height = 150, 150
img = image.load_img('image_path/image_name.jpg', target_size = (img_width, img_height))
img = image.img_to_array(img)
img = np.expand_dims(img, axis = 0)

model.predict(img)
like image 31
Nafis Avatar answered Oct 04 '22 07:10

Nafis


single_test = model.predict(np.expand_dims(X_test[i], axis=0))
like image 35
Scott Avatar answered Oct 04 '22 08:10

Scott