简体   繁体   中英

How to classify a new image with a trained CNN?

I have followed a tutorial and created a CNN with Keras on the MNIST dataset. I want to test my model on a brand new image I have downloaded. My understanding is that I have to convert the image to black and white, then convert it to a numpy array. From there I should be able to input the numpy array into model.predict but I get an error. Is there an easy way to test my model on a new image by simply providing the path of my new image to the model? Below is the code I tried

from PIL import Image 
from numpy import asarray
img = Image.open("Eight.png") # open colour image
img = img.convert('1') # convert image to black and white
img.save('eight_BW.png')

# load the image and convert into 
# numpy array 
img = Image.open('eight_bw.png') 
  
# asarray() class is used to convert 
# PIL images into NumPy arrays 
numpydata = asarray(img, dtype=int) 
  
# <class 'numpy.ndarray'> 
print(type(numpydata)) 
  
#  shape 
print(numpydata.shape) 

model.predict(numpydata)

<class 'numpy.ndarray'> (55, 72)

ValueError: Input 0 of layer sequential_2 is incompatible with the layer: : expected min_ndim=4, found ndim=2. Full shape received: [None, 72]

Below is the model code:

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

print(x_train.shape, y_train.shape)

x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train)
y_test = keras.utils.to_categorical(y_test)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

batch_size = 128
num_classes = 10
epochs = 10

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adadelta(),metrics=['accuracy'])

hist = model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_test, y_test))
print("The model has successfully trained")

model.save('mnist.h5')
print("Saving the model as mnist.h5")

Add these two lines after numpydata = asarray(img, dtype=int) and Tada!

numpydata = np.expand_dims(numpydata, 0)
numpydata = np.expand_dims(numpydata, -1)

Why: First of all the model accepts a batch of image. So you can pass it for example 32 images simultaneously. But if you want to pass the model just one image, your batch has just one image and the models input shape should be (1, ..image_shape..) (extra dimension at the beginning has been implemented by numpydata = np.expand_dims(numpydata, 0) ). On the other hand your image should have three dimension (height, width, channels) even if your image has one channel (channel == 1) so we added the extra dimension to the end by numpydata = np.expand_dims(numpydata, -1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM