2

I am using the function cv.matchTemplate to try to find template matches.

result = cv.matchTemplate(img, templ, match_method)

After I run the function I have a bunch of answers in list result. I want to filter the list to find the best n matches. The data in result just a large array of numbers so I don't know what criteria to filter based on. Using extremes = cv.minMaxLoc(result, None) filters the result list in an undesired way before converting them to locations.

The match_method is cv.TM_SQDIFF. I want to:

  • filter the results down to the best matches
  • Use the results to obtain the locations

How can I acheive this?

Josh Sharkey
  • 1,008
  • 9
  • 34
  • 1
    [This tutorial](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_template_matching/py_template_matching.html#template-matching) should get you started. Read at the bottom of the page for finding multiple matches. – J.D. Jul 10 '19 at 20:12
  • This is helpful! thank you – Josh Sharkey Jul 10 '19 at 20:20

2 Answers2

2

You can treshold the result of matchTemplate to find locations with sufficient match. This tutorial should get you started. Read at the bottom of the page for finding multiple matches.

import numpy as np

threshold = 0.2
loc = np.where( result <= threshold) # filter the results
for pt in zip(*loc[::-1]): #pt marks the location of the match
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

Keep in mind depending on the function you use will determine how you filter. cv.TM_SQDIFF tends to zero as the match quality increases so setting the threshold closer to zero filters out worse. The opposite is true for cv.TM CCORR cv.TM_CCORR_NORMED cv.TM_COEFF and cv.TM_COEFF_NORMED matching methods (better tends to 1)

Josh Sharkey
  • 1,008
  • 9
  • 34
J.D.
  • 4,511
  • 2
  • 7
  • 20
2

The above answer does not find the best N matches as the question asked. It filters out answers based on a threshold leaving open the (likely) possibility that you still have more than N results or zero results that beat the threshold.

To find the N 'best matches' we're looking for the N highest numbers in a 2d array and retrieving their indexes so we know the location. We can use nump.argpartition to find the highest N indexes in a 1d array and numpy.ndarray.flatten with numpy.unravel_index to go back and forth between a 2d and 1d array like so:

find_num = 5
result   = cv.matchTemplate(img, templ, match_method)
idx_1d   = np.argpartition(result.flatten(), -find_num)[-find_num:]
idx_2d   = np.unravel_index(idx_1d, result.shape)

From here you have the x,y locations of the top 5 matches.

Thomas Mouton
  • 473
  • 4
  • 7