根据this link,我试图使用opencv python在图像中查找多个模板。
但问题是,对于单个对象返回多个点,位置略有不同。 像这样:
我不想使用cv2.minMaxLoc()
,因为图片中有多个模板。
我写了一个删除关闭位置的函数,但我想知道这个问题是否有任何直接的解决方案?
感谢。
答案 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)
输入图片:
将眼睛用作模板图像(因为有一只以上的眼睛!)
输出:
这是我通过覆盖图像来实现的原始方式。这种方法的速度要慢得多,因为我们对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)
输出图像:
答案 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)