Coincidencia de plantillas usando OpenCV en Python

La coincidencia de plantillas es una técnica para encontrar áreas de una imagen que son similares a un parche (plantilla). 
Un parche es una pequeña imagen con ciertas características. El objetivo de la coincidencia de plantillas es encontrar el parche/plantilla en una imagen. 
Para encontrarlo, el usuario debe proporcionar dos imágenes de entrada:  Imagen de origen (S)  : la imagen para encontrar la plantilla e  Imagen de plantilla (T) : la imagen que se encuentra en la imagen de origen. 
 

  • Es básicamente un método para buscar y encontrar la ubicación de una imagen de plantilla en una imagen más grande.
  • La idea aquí es encontrar regiones idénticas de una imagen que coincidan con una plantilla que proporcionamos, dando un umbral 
    • El umbral depende de la precisión con la que queramos detectar la plantilla en la imagen de origen.
    • Por ejemplo, si estamos aplicando el reconocimiento facial y queremos detectar los ojos de una persona, podemos proporcionar una imagen aleatoria de un ojo como plantilla y buscar la fuente (el rostro de una persona).
    • En este caso, dado que los “ojos” muestran una gran cantidad de variaciones de persona a persona, incluso si establecemos el umbral en 50% (0.5), el ojo será detectado.
    • En los casos en que se busquen plantillas casi idénticas, el umbral debe establecerse alto. (t>=0.8)

¿Cómo funciona la coincidencia de plantillas?

  • La imagen de la plantilla simplemente se desliza sobre la imagen de entrada (como en la convolución 2D)
  • Se comparan la plantilla y el parche de la imagen de entrada debajo de la imagen de la plantilla.
  • El resultado obtenido se compara con el umbral.
  • Si el resultado es superior al umbral, la parte se marcará como detectada.
  • En la función cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) el primer parámetro es la imagen principal, el segundo parámetro es la plantilla a comparar y el tercer parámetro es el método utilizado para la comparación.

Python

# Python program to illustrate
# template matching
import cv2
import numpy as np
 
# Read the main image
img_rgb = cv2.imread('mainimage.jpg').
 
# Convert it to grayscale
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
 
# Read the template
template = cv2.imread('template',0)
 
# Store width and height of template in w and h
w, h = template.shape[::-1]
 
# Perform match operations.
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
 
# Specify a threshold
threshold = 0.8
 
# Store the coordinates of matched area in a numpy array
loc = np.where( res >= threshold)
 
# Draw a rectangle around the matched region.
for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,255,255), 2)
 
# Show the final image with the matched area.
cv2.imshow('Detected',img_rgb)

Limitaciones de la coincidencia de plantillas: 
 

  1. Las ocurrencias de patrones deben preservar la orientación de la imagen del patrón de referencia (plantilla)
  2. Como resultado, no funciona para versiones rotadas o escaladas de la plantilla, ya que un cambio en la forma/tamaño/corte, etc. de la plantilla del objeto dará una coincidencia falsa.
  3. El método es ineficaz cuando se calcula la imagen de correlación de patrones para imágenes medianas y grandes, ya que el proceso lleva mucho tiempo.

Para evitar el problema causado por los diferentes tamaños de la plantilla y la imagen original, podemos usar la escala múltiple . En caso de que, solo porque las dimensiones de su plantilla no coincidan con las dimensiones de la región en la imagen que desea hacer coincidir, no significa que no pueda aplicar la coincidencia de plantilla. 
 

Mecanismo de escalado múltiple en Coincidencia de plantillas

El proceso de escalado múltiple es el siguiente: 
 

  1. Haga un bucle sobre la imagen de entrada en varias escalas (es decir, haga que la imagen de entrada sea cada vez más pequeña).
  2. Aplique la coincidencia de plantillas mediante cv2.matchTemplate y realice un seguimiento de la coincidencia con el mayor coeficiente de correlación (junto con las coordenadas x, y de la región con el mayor coeficiente de correlación).
  3. Después de recorrer todas las escalas, tome la región con el mayor coeficiente de correlación y utilícela como su región «emparejada».

Python

# Python program to illustrate
# multiscaling in template matching
import cv2
import numpy as np
  
# Read the main image
img_rgb = cv2.imread('mainimage.jpg')
  
# Convert to grayscale
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
  
# Read the template
template = cv2.imread('template',0)
  
# Store width and height of template in w and h
w, h = template.shape[::-1]
found = None
 
for scale in np.linspace(0.2, 1.0, 20)[::-1]:
 
    # resize the image according to the scale, and keep track
    # of the ratio of the resizing
    resized = imutils.resize(img_gray, width = int(img_gray.shape[1] * scale))
    r = img_gray.shape[1] / float(resized.shape[1])
  
    # if the resized image is smaller than the template, then break
    # from the loop
    # detect edges in the resized, grayscale image and apply template
    # matching to find the template in the image edged
    # = cv2.Canny(resized, 50, 200) result = cv2.matchTemplate(edged, template,
    # cv2.TM_CCOEFF) (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
    # if we have found a new maximum correlation value, then update
    # the found variable if found is None or maxVal > found[0]:
    if resized.shape[0] < h or resized.shape[1] < w:
            break
    found = (maxVal, maxLoc, r)
  
# unpack the found variable and compute the (x, y) coordinates
# of the bounding box based on the resized ratio
(_, maxLoc, r) = found
(startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
(endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
 
# draw a bounding box around the detected result and display the image
cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
cv2.imshow("Image", image)
cv2.waitKey(0)

Explicación paso a paso del código anterior: 
 

  • Después de almacenar el ancho y el alto de la plantilla en w y r, inicializamos una variable encontrada para realizar un seguimiento de la región y la escala de la imagen con la mejor coincidencia. A partir de ahí, comenzamos a recorrer las múltiples escalas de la imagen usando la función np.linspace. Esta función acepta tres argumentos, el valor inicial, el valor final y el número de porciones de fragmentos iguales en el medio. En este ejemplo, comenzaremos desde el 100 % del tamaño original de la imagen y trabajaremos hasta llegar al 20 % del tamaño original en 20 porciones porcentuales del mismo tamaño.
  • Luego cambiamos el tamaño de la imagen de acuerdo con la escala actual y calculamos la relación entre el ancho anterior y el ancho nuevo; como verá más adelante, es importante que llevemos un registro de esta relación. Realizamos una verificación para asegurarnos de que la imagen de entrada sea más grande que nuestra coincidencia de plantilla. Si la plantilla es más grande, entonces nuestra llamada cv2.matchTemplate generará un error, por lo que simplemente saldremos del ciclo si este es el caso.
  • En este punto, podemos aplicar la coincidencia de plantillas a nuestra imagen redimensionada: 
    • La función cv2.minMaxLoc toma nuestro resultado de correlación y devuelve una tupla de 4 que incluye el valor de correlación mínimo, el valor de correlación máximo, la coordenada (x, y) del valor mínimo y la coordenada (x, y) de el valor máximo, respectivamente. Solo estamos interesados ​​en el valor máximo y la coordenada (x, y), por lo que mantenemos los máximos y descartamos los mínimos.
  • Después de eso, inspeccionamos las regiones de la imagen que se emparejan en cada iteración de la escala. A partir de ahí, actualizamos nuestra variable encontrada para realizar un seguimiento del valor de correlación máximo encontrado hasta el momento, la coordenada (x, y) del valor máximo, junto con la relación entre el ancho de la imagen original y el ancho de la imagen redimensionada actual. .
  • Después de haber recorrido todas las escalas de la imagen, desempaquetamos nuestra variable encontrada y luego calculamos nuestras coordenadas de inicio y finalización (x, y) de nuestro cuadro delimitador. Se tiene especial cuidado en multiplicar las coordenadas del cuadro delimitador por la proporción para garantizar que las coordenadas coincidan con las dimensiones originales de la imagen de entrada.
  • Finalmente, dibujamos nuestro cuadro delimitador y lo mostramos en nuestra pantalla.

Este artículo es una contribución de Pratima Upadhyay . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a contribuir@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 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 *