图像分类器Keras预测

时间:2017-09-06 14:53:02

标签: keras conv-neural-network

我按照Keras博客上的教程进行操作,我遇到以下问题:一旦模型被训练,我该如何选择图像并对其进行分类?

我知道 train_generator.class_indices 在模型中有类。

目标是引入图像的路径并返回相应的类。

以下是代码:

#libraries used

from keras import backend as K
from keras import applications
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.optimizers import SGD

import cv2

from PIL import Image

import matplotlib.pyplot as plt

from scipy.misc import imread

import numpy as np

%matplotlib inline

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

train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 3000
nb_validation_samples = 1200
epochs = 10 #50
batch_size = 16

n_classes = 3

# Get data

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(rescale=1. / 255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(train_data_dir, target_size=(img_width, img_height),\
                                                batch_size=batch_size,class_mode = 'categorical') # class_mode='binary'

validation_generator = test_datagen.flow_from_directory(validation_data_dir, target_size=(img_width, img_height),\
                                                    batch_size=batch_size, class_mode='categorical') #class_mode = 'categorical


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(n_classes))
model.add(Activation('softmax')) #sigmoid

model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) #loss binary_crossentropy
# on the other model
#model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])

model.fit_generator(train_generator, steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,validation_data=validation_generator, validation_steps = nb_validation_samples // batch_size)

修改1:

我编写了以下函数,它不起作用:

def predict(model, img, target_size):
    if img.size != target_size:
        img = img.resize(target_size)

    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    preds = model.predict(x)
    return preds[0]


target_size = (150, 150)
model = load_model(model_name)

img_path = 'image_test/test1.jpg'
img = Image.open(img_path)
fig = plt.figure()
plt.imshow(img)
plt.show()
preds = predict(model, img, target_size)
preds

编辑2

出现错误:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-55-516f01bf49e9> in <module>()
     17 plt.imshow(img)
     18 plt.show()
---> 19 preds = predict(model, img, target_size)
     20 preds

<ipython-input-55-516f01bf49e9> in predict(model, img, target_size)
      3         img = img.resize(target_size)
      4 
----> 5     x = image.img_to_array(img)
      6     x = np.expand_dims(x, axis=0)
      7     x = preprocess_input(x)

AttributeError: 'numpy.ndarray' object has no attribute 'img_to_array'

编辑3 :解决方案如下(我们必须重塑这个数字):

def predict(model, img, target_size):
    if img.size != target_size:
        img = img.resize(target_size)

    x = img.getdata() #.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = (x/255.)
    print("shape = ", x.shape)
    x = x.reshape(1,150,150,3)
    preds = model.predict(x)
    return preds[0]


target_size = (150, 150)

img_path = 'image_test/bird.jpg'
img = Image.open(img_path)
fig = plt.figure()
plt.imshow(img)
plt.show()
preds = predict(model, img, target_size)
preds

2 个答案:

答案 0 :(得分:1)

从发生器获取模型预期的确切形状:

X, Y = train_generator.next()  #or next(train_generator)

现在看看:

print(X.shape)
print(X.max())

获取图像库,例如Pillow(from PIL import Image),然后将所需的文件加载到数组中(该方法取决于库)。

确保此加载数组中的最大值与X中的最大值兼容(例如,您可能必须将数组除以255)

您可以创建包含多个图像的数组,或仅创建图像,但请确保在第一维中考虑批量大小:

oneImageBatch = oneImageArray.reshape((1,)+oneImageArray.shape)

然后使用model.predict(oneImageBatch)

答案 1 :(得分:1)

这肯定会有用。

from keras.preprocessing import image

targ_size = (150, 150)

def predict(model, img_path):
    x = image.load_image(img_path, target_size=targ_size)
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    preds = model.predict(x)
    return preds


model = load_model(model_name)
img_path = 'image_test/test1.jpg'
preds = predict(model, img_path)

这将返回每个类的概率数组。如果你想知道它是哪一个类,那就这样做:

pred_class = np.argmax(pred, axis=-1)