🦒 Detección de objetos con YOLOv3 (80 categorías) usando DNN de OpenCV | Python

Por Administrador

Hemos venido trabajando con el módulo dnn de OpenCV para la detección de rostros y de objetos (20 categorías) en imágenes. En esta ocasión veremos como aplicar detección de objetos usando YOLOv3, que nos permitirá detectarlos de entre 80 categorías. Así que… ¡Vamos con la programación!

CONTENIDO

Detección de objetos con YOLOv3 (80 categorías) usando DNN de OpenCV

  • Instalación de packages
  • ¡Vamos con la programación!
  • Referencias

Detección de objetos con YOLOv3 (80 categorías) usando DNN de OpenCV

Nuestro objetivo en esta ocasión será usar YOLOv3 junto con el módulo DNN de OpenCV para detectar objetos en imágenes, para ello necesitaremos de 3 archivos.

Puedes dar clic en estos archivos y se descargarán automáticamente. O podrías visitar el tutorial de OpenCV para el uso de YOLO que te dejo a continuación: https://opencv-tutorial.readthedocs.io/en/latest/yolo/yolo.html

Por otro lado, si te sientes atraído por la construcción de la red, puedes visitar este post: https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b El cual posee una explicación más extendida de toda la estructura y procedimiento para construir YOLOv3.

Este detector de objetos nos permitirá detectar objetos de entre 80 categorías. Cada una de ellas se encuentra descrita en el archivo coco.names. Estas son: person, bicycle, car, motorbike, aeroplane, bus, train, truck, boat, traffic light, fire hydrant, stop sign, parking meter, bench, bird, cat, dog, horse, sheep, cow, elephant, bear, zebra, giraffe, backpack, umbrella, handbag, tie, suitcase, frisbee, skis, snowboard, sports ball, kite, baseball bat, baseball glove, skateboard, surfboard, tennis racket, bottle, wine glass, cup, fork, knife, spoon, bowl, banana, apple, sandwich, orange, broccoli, carrot, hot dog, pizza, donut, cake, chair, sofa, pottedplant, bed, diningtable, toilet, tvmonitor, laptop, mouse, remote, keyboard, cell phone, microwave, oven, toaster, sink, refrigerator, book, clock, vase, scissors, teddy bear, hair drier, toothbrush.

Instalación de Packages

Vamos a instalar OpenCV con pip install opencv-contrib-python. Si digitamos pip freeze podremos ver todos los paquetes instalados.

Figura 1: Lista de los módulos instalados.

Te preguntarás, ¿de dónde sale Numpy?, si no lo habíamos instalado. Pues bien, al momento de instalar OpenCV, también se instala Numpy.

IMPORTANTE: Hay que tomar en cuenta que para el uso del módulo dnn, debemos contar con versiones igual o superiores a OpenCV 3.3. 

¡Vamos con la programación!

Para una explicación más detallada del programa que veremos a continuación, por favor dirígete al video que he preparado en mi canal, en donde explico paso a pasito cada procedimiento efectuado. ¡Anímate a verlo 😉!.

import cv2
import numpy as np

# --------------- READ DNN MODEL ---------------
# Model configuration
config = "model/yolov3.cfg"
# Weights
weights = "model/yolov3.weights"
# Labels
LABELS = open("model/coco.names").read().split("\n")
#print(LABELS, len(LABELS))
colors = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")
#print("colors.shape:", colors.shape)

# Load model
net = cv2.dnn.readNetFromDarknet(config, weights)

# --------------- READ THE IMAGE AND PREPROCESSING ---------------
image = cv2.imread("Images/imagen_0005.jpg")
height, width, _ = image.shape

# Create a blob
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
                              swapRB=True, crop=False)
#print("blob.shape:", blob.shape)

# --------------- DETECTIONS AND PREDICTIONS ---------------
ln = net.getLayerNames()
#print("ln:", ln)

# ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()] 
ln = [ln[i - 1] for i in net.getUnconnectedOutLayers()]
#print("ln:", ln)

net.setInput(blob)
outputs = net.forward(ln)
#print("outputs:", outputs)

boxes = []
confidences = []
classIDs = []

for output in outputs:
     for detection in output:
          #print("detection:", detection)
          scores = detection[5:]
          classID = np.argmax(scores)
          confidence = scores[classID]

          if confidence > 0.5:
               #print("detection:", detection)
               #print("classID:", classID)
               box = detection[:4] * np.array([width, height, width, height])
               #print("box:", box)
               (x_center, y_center, w, h) = box.astype("int")
               #print((x_center, y_center, w, h))
               x = int(x_center - (w / 2))
               y = int(y_center - (h / 2))
               #cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

               boxes.append([x, y, w, h])
               confidences.append(float(confidence))
               classIDs.append(classID)

idx = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.5)
print("idx:", idx)

if len(idx) > 0:
     for i in idx:
          (x, y) = (boxes[i][0], boxes[i][1])
          (w, h) = (boxes[i][2], boxes[i][3])

          color = colors[classIDs[i]].tolist()
          text = "{}: {:.3f}".format(LABELS[classIDs[i]], confidences[i])
          cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
          cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,
                         0.5, color, 2)

cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Al probar el programa podremos obtener resultados como los siguientes:

Figura 2: Detección de objetos con YOLOv3.

Como podemos visualizar, tenemos distintos colores para los cuadros delimitadores que rodean los objetos y para las etiquetas. Estos colores variarán cada vez que ejecutemos el programa, pero se mantendrán para cada objeto.

Figura 3: Detección de objetos con YOLOv3.

Figura 4: Detección de objetos con YOLOv3.

Y bien, esto ha sido todo por el tutorial de hoy. ¡Espero que te haya gustado! 😊 Nos vemos en el siguiente… ¡Qué te vaya súper bien!.

Referencias

🔗 Tutorial OpenCV para YOLO: https://opencv-tutorial.readthedocs.io/en/latest/yolo/yolo.html
🔗 Post YOLOv3: https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b

🔗 https://docs.opencv.org/4.5.3/d6/d0f/group__dnn.html#ga29f34df9376379a603acd8df581ac8d7
🔗 https://docs.opencv.org/3.4/d6/d0f/group__dnn.html#ga9d118d70a1659af729d01b10233213ee
🔗 https://pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/
🔗 https://learnopencv.com/deep-learning-based-object-detection-using-yolov3-with-opencv-python-c/
🔗 https://stackoverflow.com/questions/66701910/why-nmsboxes-is-not-eleminating-multiple-bounding-boxes