-1

template image

I'm trying to code a python script that uses the cv2 library to template match an image. I have figured out how to detect one instance of the template in the image, taking into account if the template has a different scale, but i can't seem to figure out how to find multiple instances of a template in an image taking into account the scale as well.

I tried finding the first match, blocking it, then running the scan again, but the second scan can't find the template correctly.image with bounding boxes image to find

Does anyone know what can I do for it to detect both instances?

Here is the code im running:

import numpy as np
import imutils
import glob
import cv2
from imutils.object_detection import non_max_suppression


imagen_a_detectar = r"C:\Users\OMEN\OneDrive\Documentos\TEC\PROYECTO RESIDEO\REPO\SCRUMsinCUM\software\Deteccion Iconos\flecha50.jpg"
imagen_a_comparar = r"C:\Users\OMEN\OneDrive\Documentos\TEC\PROYECTO RESIDEO\REPO\SCRUMsinCUM\software\Deteccion Iconos\HomeAuto3.png"

template = cv2.imread(imagen_a_detectar)
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 50, 200)
(tH, tW) = template.shape[:2]

for imagePath in glob.glob(imagen_a_comparar):
    image = cv2.imread(imagePath)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    found = None
    threshold = 0.9

    for scale in np.linspace(0.2, 1.0, 20)[::-1]:
        scalem = scale
        resized = imutils.resize(gray, width = int(gray.shape[1] * scale))
        r = gray.shape[1] / float(resized.shape[1])

        if resized.shape[0] < tH or resized.shape[1] < tW:
            break
        edged = cv2.Canny(resized, 50, 200)

        result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

        if found is None or max_val > found[0]:
            found = (max_val, max_loc, r)


    (_, max_loc, r) = found
    (startX, startY) = (int(max_loc[0] * r), int(max_loc[1] * r))
    (endX, endY) = (int((max_loc[0] + tW) * r), int((max_loc[1] + tH) * r))
    m1 = cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), -1)

    gray2 = cv2.cvtColor(m1, cv2.COLOR_BGR2GRAY)
    resized2 = imutils.resize(gray2, width = int(gray.shape[1] * scalem))
    r2 = gray.shape[1] / float(resized.shape[1])
    edged2 = cv2.Canny(resized2, 50, 200)

    result2 = cv2.matchTemplate(edged2, template, cv2.TM_CCOEFF_NORMED)
    min_val2, max_val2, min_loc2, max_loc2 = cv2.minMaxLoc(result2)
    found2 = (max_val2, max_loc2, r2)
    
    (_, max_loc2, r2) = found2
    (startX2, startY2) = (int(max_loc2[0] * r2), int(max_loc2[1] * r2))
    (endX2, endY2) = (int((max_loc2[0] + tW) * r2), int((max_loc2[1] + tH) * r2))

    m2 = cv2.rectangle(m1, (startX2, startY2), (endX2, endY2), (0, 0, 255), -1)

    cv2.imshow("Image", m2)
    cv2.waitKey(0)
    print(str(endX) + ' ' +str(endY)+ ' ' +str(r))

1 Answers1

0

Basically the code from this answer, slightly modified:

import cv2
import numpy as np

img_rgb = cv2.imread('image.png')
tmp_rgb = cv2.imread('template.png')

for template in [tmp_rgb, np.flip(tmp_rgb, axis=1)]:
    w, h = template.shape[:-1]
    res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
    threshold = .8
    loc = np.where(res >= threshold)
    for pt in zip(*loc[::-1]):
        cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)

plt.imshow(img_rgb)

enter image description here

Michael Hodel
  • 2,845
  • 1
  • 5
  • 10
  • Thank you for your input, but I already had that working. The problem I am facing is that one of detecting multiple instances of the template when the scale of the template is different from the scale of the image. – Jorge Garcia Jun 01 '23 at 00:51