模板与OpenCV Python中的多个对象匹配

时间:2018-05-29 07:49:12

标签: python opencv image-processing computer-vision template-matching

根据this link,我试图使用opencv python在图像中查找多个模板。

但问题是,对于单个对象返回多个点,位置略有不同。 像这样:

enter image description here

我不想使用cv2.minMaxLoc(),因为图片中有多个模板。 我写了一个删除关闭位置的函数,但我想知道这个问题是否有任何直接的解决方案? 感谢。

2 个答案:

答案 0 :(得分:1)

查找多个匹配项的一种方法是覆盖找到的匹配项,然后再次运行匹配项。 编辑:查找多个匹配项的一种 更好 方法是在 结果 上书写。在第一个示例中,我们用0填充结果的匹配部分(对于SQDIFF或CCORR_NORMED使用1),然后在循环中查找下一个匹配项。

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)

输入图片:

enter image description here

将眼睛用作模板图像(因为有一只以上的眼睛!)

enter image description here

输出:

enter image description here

这是我通过覆盖图像来实现的原始方式。这种方法的速度要慢得多,因为我们对n个匹配项进行了n + 1 matchTemplate个操作。从一项测量来看,该技术要慢1000倍。

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)

输出图像:

enter image description here

答案 1 :(得分:0)

在为我自己的数据集运行 bfris 的方法时,我注意到 while 循环在某些特殊情况下可能无限期地卡住,所以这是我的改进版本:

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
prev_min_val, prev_max_val, prev_min_loc, prev_max_loc = None, None, None, None
while max_val > threshold:
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
    # Prevent infinite loop. If those 4 values are the same as previous ones, break the loop.
    if prev_min_val == min_val and prev_max_val == max_val and prev_min_loc == min_loc and prev_max_loc == max_loc:
        break
    else:
        prev_min_val, prev_max_val, prev_min_loc, prev_max_loc = min_val, max_val, min_loc, max_loc
    
    if max_val > threshold:
        # Prevent start_row, end_row, start_col, end_col be out of range of image
        start_row = max_loc[1] - h // 2 if max_loc[1] - h // 2 >= 0 else 0
        end_row = max_loc[1] + h // 2 + 1 if max_loc[1] + h // 2 + 1 <= res.shape[0] else res.shape[0]
        start_col = max_loc[0] - w // 2 if max_loc[0] - w // 2 >= 0 else 0
        end_col = max_loc[0] + w // 2 + 1 if max_loc[0] + w // 2 + 1 <= res.shape[1] else res.shape[0]

        res[start_row: end_row, start_col: end_col] = 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)