I'm trying to find multiple templates in an image using opencv python, according to this link.
But the problem is that multiple points returned for a single object with a slightly difference in position. Something like this:
I dont want to use cv2.minMaxLoc()
because there is multiple templates in image.
I wrote a function that delete the close positions, but I want to know is there any straightforward solution for this problem?
thanks.
One way to find multiple matches is to write over the found matches and run the match again. Edit: A better way to find multiple matches is to write over the results. In the first example we fill the matched part of results with zeroes (use ones for SQDIFF or CCORR_NORMED) , and then look for the next match in a loop.
import cv2
import numpy as np
import time
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.90
start_time = time.time()
res = cv2.matchTemplate(image, template, method)
# fake out max_val for first run through loop
max_val = 1
while max_val > threshold:
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
if max_val > threshold:
res[max_loc[1]-h//2:max_loc[1]+h//2+1, max_loc[0]-w//2:max_loc[0]+w//2+1] = 0
image = cv2.rectangle(image,(max_loc[0],max_loc[1]), (max_loc[0]+w+1, max_loc[1]+h+1), (0,255,0) )
cv2.imwrite('output.png', image)
input image:
use the eyes as template images (since there is more than one eye!)
output:
And here is the original way I did it by writing over the image. This way is way is much slower because we do n+1 matchTemplate
operations for n matches. By one measurement, this technique is 1000 times slower.
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
# fake out max_val for first run through loop
max_val = 1
while max_val > threshold:
res = cv2.matchTemplate(image, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# using top ranked score, fill in that area with green
image[max_loc[1]:max_loc[1]+h+1:, max_loc[0]:max_loc[0]+w+1, 0] = 0 # blue channel
image[max_loc[1]:max_loc[1]+h+1:, max_loc[0]:max_loc[0]+w+1, 1] = 255 # green channel
image[max_loc[1]:max_loc[1]+h+1:, max_loc[0]:max_loc[0]+w+1, 2] = 0 # red channel
cv2.imwrite('output.png', image)
output image: