Detección de objetos de propuesta de región con OpenCV, Keras y TensorFlow

En este artículo, aprenderemos a implementar la detección de objetos de propuesta de región con OpenCV, Keras y TensorFlow.

Instala todas las dependencias

Use el comando pip para instalar todas las dependencias

pip install tensorflow keras imutils
pip install opencv-contrib-python

Nota: asegúrese de instalar el paquete OpenCV anterior; de lo contrario, podría enfrentar errores de importación.

Paso 1: Lea la imagen y aplique el método de búsqueda selectiva de OpenCV

En este paso, leeremos la imagen y le aplicaremos el método de búsqueda selectiva de OpenCV. Este método devolverá una lista de rectángulos que son básicamente la región de interés. OpenCV nos proporciona dos métodos diferentes para esta búsqueda selectiva, uno es el método » RÁPIDO » y el otro es el método » Preciso «, debe decidir cuál usar según su caso de uso.

Ahora que tenemos los rectángulos antes de continuar, intentemos visualizar qué regiones de interés devuelve.

Python3

import numpy as np
import cv2
 
# this is the model we'll be using for
# object detection
from tensorflow.keras.applications import Xception
 
# for preprocessing the input
from tensorflow.keras.applications.xception import preprocess_input
from tensorflow.keras.applications import imagenet_utils
from tensorflow.keras.preprocessing.image import img_to_array
from imutils.object_detection import non_max_suppression
 
# read the input image
img = cv2.imread('Assets/img2.jpg')
 
# instanciate the selective search
# segmentation algorithm of opencv
search = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
 
# set the base image as the input image
search.setBaseImage(img)
 
# since we'll use the fast method we set it as such
search.switchToSelectiveSearchFast()
 
# you can also use this for more accuracy:
# search.switchToSelectiveSearchQuality()
rects = search.process()  # process the image
 
roi = img.copy()
for (x, y, w, h) in rects:
 
    # Check if the width and height of
    # the ROI is atleast 10 percent
    # of the image dimensions and only then
    # show it
    if (w / float(W) < 0.1 or h / float(H) < 0.1):
        continue
 
    # Let's visualize all these ROIs
    cv2.rectangle(roi, (x, y), (x + w, y + h),
                  (0, 200, 0), 2)
 
roi = cv2.resize(roi, (640, 640))
final = cv2.hconcat([cv2.resize(img, (640, 640)), roi])
cv2.imshow('ROI', final)
cv2.waitKey(0)

Producción:

 

Estas son todas las Regiones de interés que recibe nuestra función después de filtrar los ROI que no son lo suficientemente grandes, es decir, si el ROI tiene menos del 10% de ancho o alto que el de la imagen entonces no lo consideraremos. .

Paso 2: cree una lista de arrays de entrada final y cuadros delimitadores utilizando ROI

Crearemos dos listas separadas que contengan la imagen en formato RGB y otra lista tendrá las coordenadas del cuadro delimitador. Estas listas se utilizarán para la predicción y la creación de cuadros delimitadores, respectivamente. También nos aseguraremos de que solo hagamos predicciones sobre un ROI lo suficientemente grande, por ejemplo, que tenga al menos el 20 % del ancho o el alto de nuestra imagen.

Python3

rois = []
boxes = []
(H, W) = img.shape[:2]
rois = []
boxes = []
(H, W) = img.shape[:2]
 
for (x, y, w, h) in rects:
   
    # check if the ROI has atleast
    # 20% the size of our image
    if w / float(W) < 0.2 or h / float(H) < 0.2:
        continue
 
    # Extract the Roi from image
    roi = img[y:y + h, x:x + w]
     
    # Convert it to RGB format
    roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
     
    # Resize it to fit the input requirements of the model
    roi = cv2.resize(roi, (299, 299))
 
    # Further preprocessing
    roi = img_to_array(roi)
    roi = preprocess_input(roi)
 
    # Append it to our rois list
    rois.append(roi)
 
    # now let's store the box co-ordinates
    x1, y1, x2, y2 = x, y, x + w, y + h
    boxes.append((x1, y1, x2, y2))

Ahora que tenemos nuestra región de interés que hemos filtrado y también preprocesado, usémosla para crear predicciones usando nuestro modelo.

Paso 3: generar predicciones usando el modelo

Estamos usando el modelo ResNet50 de los modelos preentrenados de Keras, principalmente porque no es pesado para la máquina y también tiene una alta precisión. Entonces, primero, crearemos nuestra instancia de modelo y luego pasaremos nuestra entrada -> Lista de ROI y generaremos predicciones.

En código se vería así: 

# —- Modelo—– #

modelo = Xception(pesos=’imagenet’)

# Convertir la lista de ROIS en arrays para predicciones

input_array = np.array(rois)

print(“La forma de la array de entrada es ;” ,input_array.shape)

#—- Hacer predicciones —#

preds = modelo.predecir(input_array)

preds = imagenet_utils.decode_predictions(preds, top=1)

Ahora que tenemos predicciones, mostremos el resultado en la imagen.

Paso 4: Crear diccionario de objetos

En este paso, crearemos un nuevo diccionario que básicamente contiene la etiqueta como la clave como el cuadro delimitador y la probabilidad como los valores. Esto nos permitirá acceder fácilmente a las predicciones para cada etiqueta y aplicarles non_max_suppression. Podemos hacer esto recorriendo las predicciones y filtrando las predicciones con más del 90% de confianza (puede cambiarlo según sus necesidades). Veamos el código:

Python3

# Initiate the dictionary
objects = {}
for (i, pred) in enumerate(preds):
   
    # extract the prediction tuple
    # and store it's values
     iD = pred[0][0]
    label = pred[0][1]
     prob = pred[0][2]
     
  if prob >= 0.9:
     
        # grab the bounding box associated
        # with the prediction and
        # convert the coordinates
        box = boxes[i]
 
        # create a tuple using box and probability
        value = objects.get(label, [])
         
        # append the value to the list for the label
        value.append((box, prob))
         
         # Add this tuple to the objects
        # dictionary that we initiated
        objects[label] = value

Producción:

{‘img’: [((126, 295, 530, 800), 0,5174897), ((166, 306, 497, 613), 0,510667), ((176, 484, 520, 656), 0,56631094), (( 161, 304, 499, 613), 0,55209666), ((161, 306, 504, 613), 0,6020483), ((161, 306, 499, 613), 0,54256636), ((140, 305, 499, 800) , 0,5012991), ((144, 305, 516, 800), 0,50028765), ((162, 305, 499, 642), 0,84315413), ((141, 306, 517, 800), 0,5257749), ((173, 433, 433, 610), 0,56347036)], ‘fósforo’: [((169, 633, 316, 800), 0,56465816), ((172, 633, 313, 800), 0,7206488), ((333, 639, 467, 800), 0,60068905), ((169, 633, 314, 800), 0,693922), ((172, 633, 314, 800), 0,70851576), ((167, 632, 314, 800), 0,6374499), ((172, 633, 316, 800), 0,5995729), ((169, 640, 307, 800), 0,67480534)], ‘guillotina’: [((149, 591, 341, 800), 0,59910816), (( 149, 591, 338, 800), 0,7370558), ((332, 633, 469, 800), 0,5568006), ((142, 591, 341, 800), 0,6165994),((332, 634, 468, 800), 0,63907826), ((332, 633, 468, 800), 0,57237893), ((142, 590, 321, 800), 0,6664309), ((331, 635, 467, 800), 0.5186203), ((332, 634, 467, 800), 0.58919555)], ‘water_tower’: [((144, 596, 488, 800), 0.50619787)], ‘barber_chair’: [((165, 465, 461, 576), 0.5565266)]}

Como puede ver, es un diccionario donde la etiqueta, ‘silla mecedora’, es la clave y tenemos una lista de tuplas que tienen cuadros delimitadores y probabilidades almacenadas para esta etiqueta como valores.

Paso 5: Muestre el objeto detectado en la imagen

Mire el diccionario de objetos nuevamente si aún no lo sabe, tenemos múltiples cuadros delimitadores para una sola etiqueta, entonces, ¿no habrá un grupo en la imagen si lo muestra directamente en la imagen? 

Por lo tanto, necesitamos usar el método non_max_suppression que nos resolverá este problema. Pero para usar esta función necesitamos una array de cuadros delimitadores y una array de probabilidades, y nos devuelve una array de cuadros delimitadores.

Python3

# Loop through the labels
# for each label apply the non_max_suppression
for label in objects.keys():
   
    # clone the original image
    # o that we can draw on it
    img_copy = img.copy()
    boxes = np.array([pred[0] for pred in objects[label]])
    proba = np.array([pred[1] for pred in objects[label]])
    boxes = non_max_suppression(boxes, proba)
 
    # Now unpack the co-ordinates of the bounding box
    (startX, startY, endX, endY) = boxes[0]
 
    # Draw the bounding box
    cv2.rectangle(img_copy, (startX, startY),
                  (endX, endY), (0, 255, 0), 2)
    y = startY - 10 if startY - 10 > 10 else startY + 10
 
    # Put the label on the image
    cv2.putText(img_copy, label, (startX, y),
                cv2.FONT_HERSHEY_SIMPLEX, 0.45, (255, 0), 2)
 
    # Show the image
    cv2.imshow("Regional proposal object detection", img_copy)
    cv2.waitKey(0)

A continuación se muestra la implementación completa:

Python3

# import the packages
import numpy as np
import cv2
 
# this is the model we'll be using for
# object detection
from tensorflow.keras.applications import Xception
 
# for preprocessing the input
from tensorflow.keras.applications.xception import preprocess_input
from tensorflow.keras.applications import imagenet_utils
from tensorflow.keras.preprocessing.image import img_to_array
from imutils.object_detection import non_max_suppression
 
# read the input image
img = cv2.imread('/content/img4.jpg')
 
# instanciate the selective search
# segmentation algorithm of opencv
search = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
 
# set the base image as the input image
search.setBaseImage(img)
search.switchToSelectiveSearchFast()
 
# you can also use this for more accuracy ->
# search.switchToSelectiveSearchQuality()
rects = search.process()  # process the image
 
rois = []
boxes = []
(H, W) = img.shape[:2]
for (x, y, w, h) in rects:
   
    # check if the ROI has atleast
    # 20% the size of our image
    if w / float(W) < 0.1 or h / float(H) < 0.1:
        continue
 
    # Extract the Roi from image
    roi = img[y:y + h, x:x + w]
     
    # Convert it to RGB format
    roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
     
    # Resize it to fit the input requirements of the model
    roi = cv2.resize(roi, (299, 299))
 
    # Further preprocessing
    roi = img_to_array(roi)
    roi = preprocess_input(roi)
 
    # Append it to our rois list
    rois.append(roi)
 
    # now let's store the box co-ordinates
    x1, y1, x2, y2 = x, y, x + w, y + h
    boxes.append((x1, y1, x2, y2))
 
# ------------ Model--------------- #
model = Xception(weights='imagenet')
 
 
# Convert ROIS list to arrays for predictions
input_array = np.array(rois)
print("Input array shape is ;", input_array.shape)
 
#---------- Make Predictions -------#
preds = model.predict(input_array)
preds = imagenet_utils.decode_predictions(preds, top=1)
 
 
# Initiate the dictionary
objects = {}
for (i, pred) in enumerate(preds):
   
    # extract the prediction tuple
    # and store it's values
    iD = pred[0][0]
    label = pred[0][1]
    prob = pred[0][2]
 
    if prob >= 0.9:
 
        # grab the bounding box associated
        # with the prediction and
        # convert the coordinates
        box = boxes[i]
 
        # create a tuble using box and probability
        value = objects.get(label, [])
         
        # append the value to the list for the label
        value.append((box, prob))
         
        # Add this tuple to the objects dictionary
        # that we initiated
        objects[label] = value
 
 
# Loop through the labels
# for each label apply the non_max_suppression
for label in objects.keys():
   
    # clone the original image so that we can
    # draw on it
    img_copy = img.copy()
    boxes = np.array([pred[0] for pred in objects[label]])
    proba = np.array([pred[1] for pred in objects[label]])
    boxes = non_max_suppression(boxes, proba)
 
    # Now unpack the co-ordinates of the bounding box
    (startX, startY, endX, endY) = boxes[0]
 
    # Draw the bounding box
    cv2.rectangle(img_copy, (startX, startY),
                  (endX, endY), (0, 255, 0), 2)
    y = startY - 10 if startY - 10 > 10 else startY + 10
 
    # Put the label on the image
    cv2.putText(img_copy, label, (startX, y),
                cv2.FONT_HERSHEY_SIMPLEX, 0.45, (255, 0), 2)
 
    # Show the image
    cv2.imshow("Regional proposal object detection", img_copy)
    cv2.waitKey(0)

Producción:

 

Publicación traducida automáticamente

Artículo escrito por bobde_yagyesh y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *