1

I am trying to do some dynamic template matching with cv2.matchTemplate. The template is:
enter image description here

and the image I am matching it to is:
enter image description here

I am adjusting the size and angle of the template and then grabbing maxVal and maxLoc from cv2.matchTemplate and storing them in a dict with maxVal as the keys. I'm then grabbing max(data.keys()) as the "best" match from result = cv2.matchTemplate(image, resized_template, cv2.TM_CCORR_NORMED). When I loop through all of the keys and plot them on the image, there are some that find the mickey head much better than max(data.keys()).

This is the region for "best" match:

#Find best match from scores
best_match = max(scores.keys())
#Output image
image_copy = color_image.copy()
#Create rectangle around best match
cv2.rectangle(image_copy, (data[best_match][1][0], data[best_match][1][1]), (data[best_match][1][0] + data[best_match][0][0], data[best_match][1][1] + data[best_match][0][1]), (255, 255, 255), 2)
plt.imshow(image_copy)

enter image description here

But this region appears to locate it much more accurately:

image_copy = color_image.copy()
for n in list(data.keys())[69:70:1]:
    #Create rectangle around best match
    cv2.rectangle(image_copy, (data[n][1][0], data[n][1][1]), (data[n][1][0] + data[n][0][0], data[n][1][1] + data[n][0][1]), (255, 255, 255), 2)
    cv2.imwrite('output_1.jpg', image_copy)
    plt.imshow(image_copy)

enter image description here

Am I miss interpreting what the maxVal from cv2.matchTemplate actually represents? If so, how can I select the actual "best" region based on some value or criteria? Here's the full code:

#Import packages 
import numpy as np 
import matplotlib.pyplot as plt 
import cv2
import imutils
import os

#Import template
template = cv2.imread(templates_dir + '\\' + os.listdir(templates_dir)[3])
gray_template = cv2.cvtColor(template, cv2.COLOR_RGB2GRAY)

#Import image
image = cv2.imread(images_dir + '\\' + os.listdir(images_dir)[5])
color_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

#Image dims
image_h = image.shape[1]
image_w = image.shape[0]

#Processing loop scaling the template
#Scores dict
scores = {}
#Data dict of structure (maxVal: (template dims, locs, angle))
data = {}

#Edge images 
template = cv2.Canny(gray_template, 80, 200)
image = cv2.Canny(gray_image, 80, 200)

#Loop through different template scales
for scale in np.linspace(0.2, 1.5, 15):
    #Loop through different template rotations
    for angle in np.linspace(0, 360, 25)[:-1]:
        #Rotate template
        template_rotated = imutils.rotate(template, angle)
        #Resize template
        resized_template = imutils.resize(template_rotated, width = int(template_rotated.shape[0] * scale))
        #Dims of resized template
        template_h = resized_template.shape[1]
        template_w = resized_template.shape[0]
        #Break from loop if the template becomes bigger than the image
        if template_h > image_h or template_w > image_w:
            break
        #Run template through image
        result = cv2.matchTemplate(image, resized_template, cv2.TM_CCORR_NORMED)
        #Get matching score and location
        (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
        #Add correlation value and result to scores
        scores[str(maxVal)] = result
        #Add info to data
        data[str(maxVal)] = ((template_h, template_w), (maxLoc[0], maxLoc[1]), angle)
    
#Find best match from scores
best_match = max(scores.keys())

#Output image
image_copy = color_image.copy()
#Create rectangle around best match
cv2.rectangle(image_copy, (data[best_match][1][0], data[best_match][1][1]), (data[best_match][1][0] + data[best_match][0][0], data[best_match][1][1] + data[best_match][0][1]), (0, 0, 255), 2)
plt.imshow(image_copy)
Luxo_Jr
  • 379
  • 1
  • 3
  • 12

0 Answers0