web-dev-qa-db-fra.com

Classification Keras - Détection d'objets

Je travaille sur une classification puis sur la détection d'objets avec Keras et Python. J'ai classé les chats/chiens avec une précision de 80% +, je suis d'accord avec le résultat actuel pour l'instant. Ma question est de savoir comment détecter un chat ou un chien à partir d'une image d'entrée? Je suis complètement confus. Je veux utiliser mes propres hauteurs et non celles pré-formées d'Internet.

Voici mon code actuellement:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
import numpy as np
import matplotlib.pyplot as plt
import matplotlib

from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

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

train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2000 #1000 cats/dogs
nb_validation_samples = 800 #400cats/dogs
nb_Epoch = 50
#########################################################################################################

#MODEL
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(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'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])


# 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)
##########################################################################################################
#TEST AUGMENTATION
img = load_img('data/train/cats/cat.0.jpg')  # this is a PIL image
x = img_to_array(img)  # this is a Numpy array with shape (3, 150, 150)
x = x.reshape((1,) + x.shape)  # this is a Numpy array with shape (1, 3, 150, 150)

# the .flow() command below generates batches of randomly transformed images
# and saves the results to the `preview/` directory
i = 0
for batch in train_datagen.flow(x, batch_size=1,
                          save_to_dir='data/TEST AUGMENTATION', save_prefix='cat', save_format='jpeg'):
    i += 1
    if i > 20:
        break  # otherwise the generator would loop indefinitely
##########################################################################################################
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

#PREPARE TRAINING DATA
train_generator = train_datagen.flow_from_directory(
        train_data_dir, #data/train
        target_size=(img_width, img_height),  #RESIZE to 150/150
        batch_size=32,
        class_mode='binary')  #since we are using binarycrosentropy need binary labels

#PREPARE VALIDATION DATA
validation_generator = test_datagen.flow_from_directory(
        validation_data_dir,  #data/validation
        target_size=(img_width, img_height), #RESIZE 150/150
        batch_size=32,
        class_mode='binary')


#START model.fit
history =model.fit_generator(
        train_generator, #train data
        samples_per_Epoch=nb_train_samples,
        nb_Epoch=nb_Epoch,
        validation_data=validation_generator,  #validation data
        nb_val_samples=nb_validation_samples)


model.save_weights('savedweights.h5')
# list all data in history
print(history.history.keys())

#ACC VS VAL_ACC
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy ACC VS VAL_ACC')
plt.ylabel('accuracy')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# summarize history for loss
#LOSS VS VAL_LOSS
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss LOSS vs VAL_LOSS')
plt.ylabel('loss')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()


model.load_weights('first_try.h5')

Alors maintenant, depuis que j'ai classé chat et chien, comment et que dois-je faire pour saisir une image et la parcourir pour y trouver un chat ou un chien avec une boîte englobante? Je suis complètement nouveau dans ce domaine et je ne sais même pas si je m'y attaque correctement? Je vous remercie.

MISE À JOUR Bonjour, Désolé de publier les résultats si tard, n'a pas pu travailler dessus pendant quelques jours. J'importe une image et la remodèle en forme 1,3,150,150 car la forme 150,150 apporte une erreur:

Exception: Error when checking : expected convolution2d_input_1 to have 4 dimensions, but got array with shape (150L, 150L)

Importation d'image:

#load test image
img=load_img('data/prediction/cat.155.jpg')
#reshape to 1,3,150,150
img = np.arange(1* 150 * 150).reshape((1,3,150, 150))
#check shape
print(img.shape)

Ensuite, j'ai changé def pred__unction (x) en:

def predict_function(x):
    # example of prediction function for simplicity, you
    # should probably use `return model.predict(x)`
   # random.seed(x[0][0])
  #  return random.random()
   return model.predict(img)

Maintenant, quand je cours:

best_box = get_best_bounding_box(img, predict_function)
print('best bounding box %r' % (best_box, ))

J'obtiens la sortie comme meilleure boîte englobante: Aucune

Alors j'ai couru juste:

model.predict(img)

Et obtenez ce qui suit:

model.predict(img)
Out[54]: array([[ 0.]], dtype=float32)

Donc ce n'est pas du tout vérifier si c'est un chat ou un chien ... Des idées?

REMARQUE: lorsque def prev) la fonction (x) utilise:

random.seed(x[0][0])
   return random.random()

J'obtiens la sortie sous forme de cases à cocher et donne la meilleure.

18
Powisss

le modèle d'apprentissage automatique que vous avez construit et la tâche que vous essayez d'accomplir ne sont pas les mêmes. le modèle essaie de résoudre une tâche de classification tandis que votre objectif est de détecter un objet à l'intérieur de l'image, qui est un tâche de détection d'objet .

la classification a une question booléenne tandis que la question de détection a plus de deux réponses.

Que pouvez-vous faire?

Je peux vous proposer trois possibilités:


1. utilisez une fenêtre coulissante combinée avec votre modèle

recadrer des boîtes de tailles définies (par exemple de 20X20 à 160X160) et utiliser une fenêtre coulissante. pour chaque fenêtre, essayez de prédire la probabilité que ce soit un chien et finalement prenez la fenêtre maximale sur laquelle vous avez prédit.

cela générera plusieurs candidats pour la boîte englobante et vous choisirez la boîte englobante en utilisant la probabilité la plus élevée que vous avez obtenue.

cela peut être lent, car nous devons prédire sur des centaines d'échantillons.

une autre option consiste à essayer d'implémenter RCNN ( n autre lien ) ou Faster-RCNN réseau au-dessus de votre réseau. Ces réseaux réduisent essentiellement le nombre de candidats de fenêtres de boîte englobante à utiliser.

Mise à jour - Exemple de fenêtre coulissante informatique

le code suivant montre comment faire l'algorithme de fenêtre coulissante. vous pouvez modifier les paramètres.

import random
import numpy as np

WINDOW_SIZES = [i for i in range(20, 160, 20)]


def get_best_bounding_box(img, predict_fn, step=10, window_sizes=WINDOW_SIZES):
    best_box = None
    best_box_prob = -np.inf

    # loop window sizes: 20x20, 30x30, 40x40...160x160
    for win_size in window_sizes:
        for top in range(0, img.shape[0] - win_size + 1, step):
            for left in range(0, img.shape[1] - win_size + 1, step):
                # compute the (top, left, bottom, right) of the bounding box
                box = (top, left, top + win_size, left + win_size)

                # crop the original image
                cropped_img = img[box[0]:box[2], box[1]:box[3]]

                # predict how likely this cropped image is dog and if higher
                # than best save it
                print('predicting for box %r' % (box, ))
                box_prob = predict_fn(cropped_img)
                if box_prob > best_box_prob:
                    best_box = box
                    best_box_prob = box_prob

    return best_box


def predict_function(x):
    # example of prediction function for simplicity, you
    # should probably use `return model.predict(x)`
    random.seed(x[0][0])
    return random.random()


# dummy array of 256X256
img = np.arange(256 * 256).reshape((256, 256))

best_box = get_best_bounding_box(img, predict_function)
print('best bounding box %r' % (best_box, ))

exemple de sortie:

predicting for box (0, 0, 20, 20)
predicting for box (0, 10, 20, 30)
predicting for box (0, 20, 20, 40)
...
predicting for box (110, 100, 250, 240)
predicting for box (110, 110, 250, 250)
best bounding box (140, 80, 160, 100)


2. former un nouveau réseau pour la tâche de détection d'objets

vous pouvez jeter un oeil au ensemble de données Pascal ( exemples ici ) qui contient 20 classes et deux d'entre eux sont des chats et des chiens.

l'ensemble de données contient l'emplacement des objets comme cible Y.


3. utiliser le réseau existant pour cette tâche

enfin, vous pouvez réutiliser le réseau existant ou même effectuer un "transfert de connaissances" (exemple de keras ici) pour votre tâche spécifique.

jetez un oeil à ce qui suit convnets-keras lib.

alors choisissez votre meilleure méthode pour aller nous mettre à jour avec les résultats.

17
ShmulikA