Coincidencia de múltiples plantillas con OpenCV

En este tutorial, vamos a ver cómo realizar la coincidencia de múltiples plantillas con OpenCV .

Lo guiaremos a través de todo el proceso de coincidencia de múltiples plantillas usando OpenCV. Para este tutorial, necesitará una comprensión básica de la visión por computadora con OpenCV y tendrá todas las dependencias instaladas en su entorno de trabajo.

¿Qué es la coincidencia de plantillas?

Podría pensar en ello como la forma más primitiva/simple de detección de objetos. Básicamente, tratamos de encontrar la plantilla dada en la imagen de entrada que se nos proporciona.

¿En qué se diferencia de la coincidencia de una sola plantilla?

En la coincidencia de una sola plantilla, usa el método cv2.matchTemplate y luego usa minMaxLoc para obtener la coordenada del punto más probable que coincida con nuestra plantilla y el cuadro delimitador de creación en la imagen, pero en la coincidencia de varias plantillas, después de usar el cv2.matchTemplate filtraremos todos los puntos que son mayores que un umbral (pasarlo como entrada o definirlo manualmente) y luego usaremos la supresión n on-maxima (NMS) para suavizar múltiples detecciones y crear cuadros delimitadores alrededor del imagen.

Sin NMS:

Obtendríamos que se detectaran varias cajas, como:

matchtemplate genera una cantidad de cuadros delimitadores para cada objeto, incluso con una confianza baja

Con NMS: 

el cuadro delimitador ahora se suaviza sin ningún desorden

Implementación paso a paso

Paso 1: Cargue la entrada y la imagen de la plantilla

Usaremos la función cv2.imread() para cargar primero la imagen y también la plantilla a comparar. Hemos tomado las siguientes imágenes: 

Modelo:

 

Coincidencia de imágenes:

 

 

Python3

# Reading the image and the template
img = cv2.imread('Assets/img3.png')
temp = cv2.imread('Assets/logo_2.png')

Paso 2: Conviértelos a escala de grises

Convertiremos ambas imágenes a escala de grises porque facilita el cálculo y los algoritmos son mucho más precisos en imágenes en escala de grises.

Python3

# Converting them to grayscale
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
temp_gray = cv2.cvtColor(temp,cv2.COLOR_BGR2GRAY)

Paso 3: usa el método cv2.matchTemplate

Usaremos cv2.matchTemplate(), como se mencionó anteriormente, para hacer coincidir la plantilla con la imagen.

cv2.matchTemplate(): 

Pasamos la imagen y la plantilla y también el método que usaremos. Hay diferentes métodos disponibles para la coincidencia de plantillas.

Python3

# Passing the image to matchTemplate method 
match = cv2.matchTemplate(image=img_gray, 
                          templ=temp_gray, 
                          method=cv2.TM_CCOEFF_NORMED)

Paso 4: filtrar los puntos más probables mediante el uso de un valor de umbral

Plantilla de coincidencia, devolveremos todos los cuadros delimitadores incluso con poca precisión, por lo que tendremos que filtrarlos. Además, debe recordar que el archivo cv2 . El método matchTemplate nos devuelve las coordenadas como una lista de tuplas, por lo que las almacenaremos por separado en una lista y luego recorreremos cada una para crear una nueva tupla con los cuatro puntos necesarios para el cuadro delimitador, como se muestra a continuación,

Python3

# Select rectangles with
# confidence greater than threshold
(y_points, x_points) = np.where(match >= thresh)
  
# initialize our list of bounding boxes
boxes = list()
  
# store co-ordinates of each bounding box
# we'll create a new list by looping
# through each pair of points
for (x, y) in zip(x_points, y_points):
    
    # update our list of boxes
    boxes.append((x, y, x + W, y + H))

Paso 5: use la supresión no máxima -> esto se usa para suprimir múltiples cuadros delimitadores para el mismo objeto

Ahora aplicaremos NMS en los cuadros delimitadores para suavizar todas las predicciones y darnos un cuadro delimitador definido para cada objeto.

Python3

# apply non-maxima suppression to the rectangles
# this will create a single bounding box
# for each object
boxes = non_max_suppression(np.array(boxes))

Paso 6: Mostrar las detecciones en la imagen

Finalmente, muestre nuestras predicciones en la imagen dibujando el cuadro delimitador.

Python3

# loop over the final bounding boxes
for (x1, y1, x2, y2) in boxes:
    
    # draw the bounding box on the image
    cv2.rectangle(img, (x1, y1), (x2, y2),
    (255, 0, 0),3)
      
# Show the template and the final output
cv2.imshow("Template" ,temp)
cv2.imshow("After NMS", img)
cv2.waitKey(0)

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

Python3

import cv2
import numpy as np
from imutils.object_detection import non_max_suppression
  
# Reading the image and the template
img = cv2.imread('Assets/img3.png')
temp = cv2.imread('Assets/logo_2.png')
  
# save the image dimensions
W, H = temp.shape[:2]
  
# Define a minimum threshold
thresh = 0.4
  
# Converting them to grayscale
img_gray = cv2.cvtColor(img, 
                        cv2.COLOR_BGR2GRAY)
temp_gray = cv2.cvtColor(temp,
                         cv2.COLOR_BGR2GRAY)
  
# Passing the image to matchTemplate method
match = cv2.matchTemplate(
    image=img_gray, templ=temp_gray, 
  method=cv2.TM_CCOEFF_NORMED)
  
# Select rectangles with
# confidence greater than threshold
(y_points, x_points) = np.where(match >= thresh)
  
# initialize our list of rectangles
boxes = list()
  
# loop over the starting (x, y)-coordinates again
for (x, y) in zip(x_points, y_points):
    
    # update our list of rectangles
    boxes.append((x, y, x + W, y + H))
  
# apply non-maxima suppression to the rectangles
# this will create a single bounding box
boxes = non_max_suppression(np.array(boxes))
  
# loop over the final bounding boxes
for (x1, y1, x2, y2) in boxes:
    
    # draw the bounding box on the image
    cv2.rectangle(img, (x1, y1), (x2, y2),
                  (255, 0, 0), 3)
  
# Show the template and the final output
cv2.imshow("Template", temp)
cv2.imshow("After NMS", img)
cv2.waitKey(0)
  
# destroy all the windows 
# manually to be on the safe side
cv2.destroyAllWindows()

Producción:

 

Sin imagen de plantilla coincidente:

 

Nota: Recuerde usar una imagen pequeña para la plantilla ~ 15-20 Kb (alrededor de 50K-60K píxeles) porque de lo contrario, el algoritmo no podrá resolverlo, porque entonces el cálculo aumentará exponencialmente, como lo hace nuestro programa. t destinado a, lo que a su vez hace que nuestro programa sea cada vez menos preciso.

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 *