【问题标题】:Keras: model.predict for a single imageKeras:模型.预测单个图像
【发布时间】:2017-08-18 10:13:15
【问题描述】:

我想使用 Keras 对单个图像进行预测。我已经训练了我的模型,所以我只是在加载权重。

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)

我正在使用以下方式加载图像:

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

并使用模型的预测功能:

 model.predict(img)

但我得到了错误:

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

我应该如何继续对单个图像进行预测?

【问题讨论】:

    标签: deep-learning keras


    【解决方案1】:

    由于您对模型进行了小批量训练,因此您的输入是一个形状为 [batch_size, image_width, image_height, number_of_channels] 的张量。

    在进行预测时,即使只有一张图像,也必须尊重这种形状。你的输入应该是形状:[1, image_width, image_height, number_of_channels]

    你可以很容易地在 numpy 中做到这一点。假设您有一个 5x5x3 图像:

        >>> 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)
    

    现在 x 是 4 阶张量!

    【讨论】:

    • 感谢您的回答。但是,在您的情况下,包含图像的 img 变量应该在哪里?
    • 假设我的变量x 是一个图像。我可能应该写x=cv2.imread('image.jpg')。函数 cv2.imread() 返回一个 numpy 数组。所以在你的情况下,img 是一个 numpy 数组,我的 x 变量也是如此
    • 另一种方法是x = x.reshape((1,) + x.shape)。还。 np.squeeze 可用于转换回 3 阶张量。
    • 另外请记住,如果您使用 ImageDataGenerator 加载和训练数据,您可能使用了 rescale=1./255。如果您使用它,请确保添加 np.expand_dims(image, axis=0)/255...
    • 仅仅嵌套在一个数组中也对我有用:x = np.array( [ x ] ),在这种情况下,这对我来说似乎更直观。
    【解决方案2】:

    试试:

     model.predict(img[None,...])
    

    【讨论】:

    • 数据格式化应该在预处理阶段完成,而不是在模型调用中。
    • 这是一个有效的答案。奇怪的是,这个人被否决了。是因为他没有解释吗? model.predict(img[None]) 也可以。而且它比np.expand_dims() 的东西要短很多。
    • 同意,投票赞成这个答案。 @utkarsh-ankit 不要气馁。你的回答很有帮助。请提供一行解释 - 对其他人会更有帮助
    【解决方案3】:

    即使这不能解决您的错误,如果您之前已经这样做过,请确保并重新缩放您的图像。例如,我的训练生成器如下所示:

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

    所以当我去预测单个图像时:

    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)
    

    我还必须将它重新缩放 255。

    【讨论】:

    • 感谢这对我有用。为了使用 skimage,我将 scikit-image==0.15.0 添加到 requirements.txt 包中
    【解决方案4】:

    您可以加载具有所需宽度和高度的图像,将其转换为形状为(image_width, image_height, number_of_channels) 的numpy 数组,然后将数组的形状更改为(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)
    

    【讨论】:

      【解决方案5】:
      single_test = model.predict(np.expand_dims(X_test[i], axis=0))
      

      【讨论】: