Pregunta Clasificación Keras - Detección de Objetos


Estoy trabajando en una clasificación y luego detección de objetos con Keras y Python. Clasifiqué gatos / perros con un 80% de precisión, estoy de acuerdo con el resultado actual por ahora. Mi pregunta es ¿cómo puedo detectar un gato o un perro de una imagen de entrada? Estoy completamente confundido. Quiero usar mis propias alturas y no preconcebidas de internet.

Aquí está mi código actualmente:

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

Entonces, ahora que clasifiqué el gato y el perro, ¿cómo y qué debo hacer para ingresar una imagen y revisarla para encontrar un gato o un perro con una caja delimitadora? Soy completamente nuevo en esto y ni siquiera estoy seguro de si estoy abordando esto de manera correcta. Gracias.

ACTUALIZAR Hola. Lamento publicar resultados tan tarde y no pude trabajar en esto durante unos días. Estoy importando una imagen y reformulándola a la forma 1,3,150,150 ya que la forma 150,150 produce un error:

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

Importación de imagen:

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

Luego he cambiado def predic_function (x) a:

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)

Ahora cuando corro:

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

Obtengo salida como el mejor cuadro delimitador: Ninguno

Entonces corrí solo:

model.predict(img)

Y consigue lo siguiente:

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

Entonces, no está comprobando si es un gato o un perro ... ¿Alguna idea?

NOTA: cuando def predetemos función (x) está usando:

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

Obtengo la salida como, marca casillas y da la mejor.


14
2018-01-26 22:19


origen


Respuestas:


el modelo de aprendizaje automático que construyó y la tarea que está tratando de lograr no son lo mismo. el modelo intenta resolver una tarea de clasificación, mientras que su objetivo es detectar un objeto dentro de la imagen, que es un tarea de detección de objetos.

la clasificación tiene una pregunta booleana mientras que la detección tiene más de dos respuestas.

¿Qué puedes hacer?

Puedo sugerirte tres posibilidades para intentar:


1. use ventana deslizante combinada con su modelo

recortar cuadros de tamaños definidos (por ejemplo, de 20X20 a 160X160) y usar ventana deslizante. para cada ventana, trate de predecir la probabilidad de que sea un perro y finalmente tome la ventana máxima que pronosticó.

esto generará múltiples candidatos para el cuadro delimitador y elegirá el cuadro delimitador con la probabilidad más alta que haya obtenido.

esto puede ser lento ya que necesitamos predecir en cientos + muestras.

otra opción es intentar implementar RCNN (otro enlace) o Faster-RCNN red en la parte superior de su red. Estas redes básicamente reducen el número de candidatos de ventana de cuadro delimitador para usar.

Actualización - Ejemplo de ventana deslizante informática

el siguiente código muestra cómo hacer el algoritmo de la ventana deslizante. puedes cambiar los parámetros

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

ejemplo de salida:

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. entrenar una nueva red para la tarea de detección de objetos

puedes echar un vistazo al dataset pascal (ejemplos aquí) que contiene 20 clases y dos de ellos son gatos y perros.

el conjunto de datos contiene la ubicación de los objetos como el objetivo Y.


3. usa la red existente para esta tarea

Por último, pero no menos importante, puede reutilizar la red existente o incluso hacer "transferencia de conocimiento" (ejemplo de keras aquí) para su tarea específica.

echa un vistazo a los siguientes convnets-keras lib.

así que elija su mejor método para actualizarnos con los resultados.


13
2018-01-27 12:59