Estoy tratando de usar un modelo de keras. He entrenado modelo y quiero usarlo desde webcam. Sin embargo, hasta donde tengo entendido, las entradas que utilizo mientras entreno el modelo y las entradas que recibo de la cámara no coinciden. ¿Cómo soluciono este problema?

Aquí el código para el tren:

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

Aquí el código para predecir:

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]

Traté de cambiar la forma de la imagen que obtuve de la cámara, pero no pude decidir cuáles deberían ser las dimensiones.

2
codcod55 29 oct. 2020 a las 17:05

1 respuesta

La mejor respuesta

Puede distinguir la forma de entrada de un modelo a partir de esta línea:

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

Esta línea significa que el modelo toma una imagen de forma (256, 256, 1) basada en el argumento input_shape, por lo tanto, el modelo espera tomar imágenes de ese tamaño.

Su mensaje de error significa que usó una imagen de forma (256, 256, 3) y esperaba 1 en lugar de 3, por lo que debe hacer que el valor de los canales sea 1 como en la imagen de escala de grises en lugar de 3, que es BGR.

Agregue esta línea después de la primera línea en el ciclo while en el código para predecir:

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

Esta línea cambia los canales de la imagen de BGR a escala de grises para hacer coincidir los canales de tamaño de entrada para el modelo y la forma de entrada solicitada por el modelo.

1
Mina Abd El-Massih 29 oct. 2020 a las 15:52