如何解决“输入形状的预期轴-1的值为1,但接收到形状为[None,256,256,3]'的输入”的错误?

时间:2020-10-29 14:05:42

标签: python keras deep-learning neural-network

我正在尝试使用keras模型。我训练了模型,并想通过网络摄像头使用它。但是,据我了解,我在训练模型时使用的输入与我从相机接收的输入不匹配。我该如何解决这个问题?

这里的火车代码:

from keras.preprocessing.image import ImageDataGenerator
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Dropout
from keras.layers import Dense
from keras.layers import Flatten

from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.models import Sequential, load_model
import tensorflow as tf
import numpy as np
import os

# plot pretty figures
import matplotlib
import matplotlib.pyplot as plt

plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12

nbatch=32

train_datagen = ImageDataGenerator ( rescale=1./255,
                                     rotation_range=12.,
                                     width_shift_range=0.2,
                                     height_shift_range=0.2,
                                     zoom_range=0.15,
                                     horizontal_flip=True)

test_datagen = ImageDataGenerator (rescale=1./255)

train_gen = train_datagen.flow_from_directory(
    'images/train/',
    target_size=(256,256),
    color_mode='grayscale',
    batch_size=nbatch,
    classes=['NONE','ONE','TWO','THREE','FOUR','FIVE'],
    class_mode='categorical'
)

test_gen = test_datagen.flow_from_directory(
    'images/test/',
    target_size=(256,256),
    color_mode='grayscale',
    batch_size=nbatch,
    classes=['NONE','ONE','TWO','THREE','FOUR','FIVE'],
    class_mode='categorical'
)

for X, y in train_gen:
    print(X.shape, y.shape)

    plt.figure(figsize=(16,16))
    for i in range(25):
        plt.subplot(5,5,i+1)
        plt.axis('off')
        plt.title('Label: {}'.format(np.argmax(y[i])))
        img= np.uint8(255*X[i,:,:,0])
        plt.imshow(img,cmap='gray')
    break

plt.show()

model = Sequential()
model.add(Conv2D(32,(3,3),activation='relu',input_shape=(256,256,1)))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(64,(3,3),activation='relu'))
model.add(Conv2D(64,(3,3),activation='relu'))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(128,(3,3),activation='relu'))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(256,(3,3),activation='relu'))
model.add(MaxPooling2D((2,2)))
model.add(Flatten())
model.add(Dense(150, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(6,activation='softmax'))

model.summary()

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['acc'])

callback_list=[EarlyStopping(monitor='val_loss',patience=10),
               ModelCheckpoint(filepath='model_6cat_2.h6',monitor='val_loss',save_best_only=True),]

os.environ["CUDA_VISIBLE_DEVİCES"] = "0"
with tf.device('/GPU:0'):
    history = model.fit_generator(
        train_gen,
        steps_per_epoch=64,
        epochs=200,
        validation_data=test_gen,
        validation_steps=28,
        callbacks=callback_list
    )

plt.figure(figsize=(16,6))
plt.subplot(1,2,1)
nepochs=len(history.history['loss'])
plt.plot(range(nepochs),history.history['loss'], 'g-', label='train')
plt.plot(range(nepochs),history.history['val_loss'], 'c-', label='test')
plt.legend(prop={'size':20})
plt.ylabel('loss')
plt.xlabel('number of epochs')
plt.subplot(1,2,2)
plt.plot(range(nepochs),history.history['acc'], 'g-', label='train')
plt.plot(range(nepochs),history.history['val_acc'], 'c-', label='test')
plt.legend(prop={'size':20})
plt.ylabel('accuracy')
plt.xlabel('number of epochs')


X_test, y_test= [], []
for ibatch, (X,y) in enumerate(test_gen):
    X_test.append(X)
    y_test.append(y)
    ibatch+=1
    if (ibatch==5*28):break

X_test = np.concatenate(X_test)
y_test = np.concatenate(y_test)
y_test = np.int32([np.argmax(r) for  r in y_test])


y_pred = np.int32([np.argmax(r) for  r in model.predict(X_test)])
match=(y_test == y_pred)
print(("Testing Accuracy = {}").format(np.sum(match)*100/match.shape[0]))

以下代码可用于预测:

model = load_model("C://Users//90544//OneDrive//Masaüstü//Yusuf// 
ödevler//kerasGiris//model_6cat_2.h6", compile = True)

  cap = cv2.VideoCapture(0)
  while 1:
    ret, frame = cap.read()
    if ret:
        frame = cv2.flip(frame, 1)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        frame = cv2.resize(frame, (256, 256))
        frameNp = image.img_to_array(frame)
        frameNp = np.expand_dims(frameNp, axis=0)

        predictions = model.predict(frameNp)
        print(predictions)

        cv2.imshow("frame", frameNp)

        k = cv2.waitKey(1) & 0xff
        if k == 27: break  # ESC pressed

    cap.release()
    cv2.destroyAllWindows()

ValueError: Input 0 of layer sequential is incompatible with the layer: expected axis -1 of input shape to have value 1 but received input with shape [None, 256, 256, 3]

我试图更改从相机获得的图像的形状,但是我无法确定尺寸应该是什么。

1 个答案:

答案 0 :(得分:1)

您可以从此行告诉模型的输入形状:

model.add(Conv2D(32,(3,3),activation='relu',input_shape=(256,256,1)))

此行表示模型基于input_shape参数拍摄形状为(256、256、1)的图像,因此该模型希望拍摄该尺寸的图像。

您的错误消息表示您使用的图像形状为(256,256,3),并且预期为1而不是3,因此您需要使通道值像灰度图像一样为1,而不是3(即BGR)

在while代码的while循环的第一行之后添加此行以进行预测:

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

此行将图像的通道从BGR更改为灰度,以匹配模型的输入尺寸通道和模型要求的输入形状。