Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template matching with multiple objects in OpenCV Python

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:

enter image description here

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.

like image 583
Salman Avatar asked May 29 '18 07:05

Salman


1 Answers

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:

enter image description here

use the eyes as template images (since there is more than one eye!)

enter image description here

output:

enter image description here

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:

enter image description here

like image 146
bfris Avatar answered Oct 06 '22 23:10

bfris