Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

opencv python MatchTemplate function with multiple matches

Tags:

python

opencv

I'am trying to find small picture in a big picture and used MatchTemplate()

img = cv2.imread("c:\picture.jpg")
template = cv2.imread("c:\template.jpg")

result = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
y,x = np.unravel_index(result.argmax(), result.shape)

Works fine I always get coords of top left corner, but it's only one point. If I have a multiple matches on big picture, how i can get all of them ?

like image 690
user2046488 Avatar asked Feb 06 '13 10:02

user2046488


2 Answers

Here's how:

result = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)

#the get the best match fast use this:
(min_x, max_y, minloc, maxloc) = cv2.minMaxLoc(result)
(x,y) = minloc

#get all the matches:
result2 = np.reshape(result, result.shape[0]*result.shape[1])
sort = np.argsort(result2)
(y1, x1) = np.unravel_index(sort[0], result.shape) # best match
(y2, x2) = np.unravel_index(sort[1], result.shape) # second best match

This is note the fastest way as the above sorts all the matches, even the totally wrong ones. If the performance matters to you, you can use the bottleneck's partsort function instead.

like image 192
b_m Avatar answered Sep 21 '22 09:09

b_m


@b_m's Answer will work, but it will find way too many matches. The matching process slides the template across the image, comparing at EVERY PIXEL. (Or almost every pixel. the scan area is reduced by the size of the template). This means that in the vicinity of a good match, you get lots of other matches that are one pixel off. If you make an image of the matching results, you can see that you get lots of matches.

import cv2
import numpy as np

image = cv2.imread('smiley.png', cv2.IMREAD_COLOR )
template = cv2.imread('template.png', cv2.IMREAD_COLOR)

h, w = template.shape[:2]

method = cv2.TM_CCOEFF_NORMED

threshold = 0.95

res = cv2.matchTemplate(image, template, method)
# min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

cv2.imwrite('output.png', 255*res)

input image:

enter image description here

use eyes as templates:

enter image description here

And look at the output. There are lots of white pixels near both eyes. You'll get quite a few high scoring answers:

enter image description here

An alternative way to find multiple copies of a template in the same image is to modify the image by writing over the found areas, and then matching again. But even better than that is to modify the results and re-running minMaxLoc. Both techniques are demonstrated in this answer.

like image 39
bfris Avatar answered Sep 20 '22 09:09

bfris