Raj Prabhu
Raj Prabhu

Reputation: 81

How to predict a single image with Keras ImageDataGenerator?

I have trained the CNN to classify images on 3 class. while training the model i have used ImageDataGenerator class from keras to apply preprocessing function on image and rescale it. Now my network is trained with a good accuracy on test set, but i don't know how to apply preprocessing function on single image prediction. If i use ImageDataGenerator it looks for directory. Suggest me some alternatives to do preprocessing function and rescaling on single image. see my code below

TRAINING SET:

train_datagen = ImageDataGenerator(preprocessing_function = tf.keras.applications.vgg16.preprocess_input,
                                   rescale = 1./255,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)
training_set = train_datagen.flow_from_directory('./training_set',
                                                 target_size = (224, 224),
                                                 batch_size = 10,
                                                 class_mode = 'categorical')

TESTING SET:

test_datagen =ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input,                                                            
                                                         rescale = 1./255)
test_set = test_datagen.flow_from_directory('./test_set',
                                            target_size = (224, 224),
                                            batch_size = 10,
                                            shuffle=False,
                                            class_mode = 'categorical') 

Now,im unable to apply preprocessing function and rescaling on single image before prediction. SINGLE PREDICTION:

single_datagen = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input,
                                   rescale = 1./255)
single_test = single_datagen.flow_from_directory('./single_prediction/cc.jpg',
                                            target_size = (224, 224),
                                            batch_size = 1,
                                            class_mode = 'categorical') 

ERROR: NotADirectoryError: [Errno 20] Not a directory: './single_prediction/cc.jpg'

Upvotes: 7

Views: 7548

Answers (3)

DonCarleone
DonCarleone

Reputation: 859

The following should work for you:

from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import preprocess_input

img_path = './test_set/<class_name>/img1.jpg'
img = image.load_img(img_path, target_size=(224, 224))
#convert to array so that we can pass into preprocess_function
img = image.img_to_array(img)
#preprocess using the same function used for training
img = preprocess_input(img, data_format=None)
#normalize image
img = img/255.0
#transform image array to a tensor
img = np.expand_dims(img, axis=0)

model.predict(img)

Should output something looking this:

array([[7.5399306e-17, 1.0000000e+00]], dtype=float32)

Note: It is essential that all of your test data is being preprocessed the same way as was done with the train / verify data. Note how we rescale/normalize the pixel values using img = img/255.0. Without preprocessing the image correctly, you'd be testing on data that it was not trained for.

Upvotes: 0

David Obembe
David Obembe

Reputation: 121

When you wish to predict a single image, you can use the following code.

It returns a list of probabilities of each class based on how the folders (classes) in your train dataset were arranged. So the first index of the returned list is the first folder (or class) in your train dataset and so on. The index with the highest probability is your predicted class.

from keras.preprocessing.image import load_img, img_to_array, ImageDataGenerator
from keras.applications.vgg16 import preprocess_input

#load the image
my_image = load_img('your_single_image.jpeg', target_size=(224, 224))

#preprocess the image
my_image = img_to_array(my_image)
my_image = my_image.reshape((1, my_image.shape[0], my_image.shape[1], my_image.shape[2]))
my_image = preprocess_input(my_image)

#make the prediction
prediction = model.predict(my_image)

You can return a much clearer result by rounding the results to whole numbers using the list comprehension below.

import numpy as np
[np.round(x) for x in prediction]

The element with index 1 is your predicted class.

Upvotes: 4

Gerry P
Gerry P

Reputation: 8112

The image data generator looks at the directory you specify and searches for sub directories within that directory that specify the classes. So create a directory called './single_prediction. Within that directory create a single sub directory call it test. Within that sub directory named test place the images that you want to test. Alternatively you can write some python code to produce the pre-processed images. Create a directory called test and place your images in it. I have not tested it but the code below should work.

import cv2
import numpy as np
import os
data_list=[]
dir=r'c:\test'
test_list=os.listdir(dir) # create a list of the files in the directory
batch_size=len(test_list) # determine number of files to process
for f in test_list:  # iterate through the files
    fpath=os.path.join (dir, f) # create path to the image file
    img=cv2.imread(fpath) # read image using cv2
    img=cv2.resize(img, (224,224)) # resize the image
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # cv2 creates bgr images, convert to rgb images
    img=tf.keras.applications.vgg16.preprocess_input(img)   # apply the Vgg16 preprocess function
    data_list.append(img)  # append processed image to the list
data=np.array(data_list)/255 # convert to an np array and rescale images
print (data.shape, batch_size)
predictions=model.predict(data,batch_size=batch_size, verbose=0 )
trials=len (predictions)
for i in range(0,trials):
    predicted_class=predictions[i].argmax() # get index of highest probability
    print (test_list[i], predicted_class) # print file name and class prediction

    

Upvotes: 0

Related Questions