我有一个项目,我想在类似于以下图片的图像中定位一堆箭头:ibb.co/dSCAYQ,
使用以下模板:ibb.co/jpRUtQ
我正在使用Python中的cv2模板匹配功能。我的算法是将模板旋转360度并对每个旋转进行匹配。我得到了以下结果:ibb.co/kDFB7k
正如您所看到的,它工作得很好,除了两个箭头非常接近,以至于另一个箭头在模板的黑色区域中。
我正在尝试使用遮罩,但似乎cv2根本不应用我的遮罩,即使该遮罩数组具有任何值,匹配结果也是相同的。已经尝试了两天,但cv2的有限文档没有帮助。
这是我的代码:
import numpy as np
import cv2
import os
from scipy import misc, ndimage
STRIPPED_DIR = #Image dir
TMPL_DIR = #Template dir
MATCH_THRESH = 0.9
MATCH_RES = 1 #specifies degree-interval at which to match
def make_templates():
base = misc.imread(os.path.join(TMPL_DIR,'base.jpg')) # The templ that I rotate to make 360 templates
for deg in range(360):
print('making template: ' + str(deg))
tmpl = ndimage.rotate(base, deg)
misc.imsave(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), tmpl)
def make_masks():
for deg in range(360):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), 0)
ret2, mask = cv2.threshold(tmpl, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imwrite(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.jpg'), mask)
def match(img_name):
img_rgb = cv2.imread(os.path.join(STRIPPED_DIR, img_name))
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
for deg in range(0, 360, MATCH_RES):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), 0)
mask = cv2.imread(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.jpg'), 0)
w, h = tmpl.shape[::-1]
res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCORR_NORMED, mask=mask)
loc = np.where( res >= MATCH_THRESH)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imwrite('res.png',img_rgb)
以下是我认为可能存在问题但不确定如何解决的几个方面:
- 掩码/模板/图像应该具有的通道数。我已经尝试了一个使用彩色4通道png文件的例子stackoverflow eg.,但不确定它如何转换为灰度或3通道jpeg文件。
- 掩码数组的值。例如,掩盖的像素应该是1还是255?
非常感谢任何帮助。
更新 我在代码中修复了一个微不足道的错误;必须在matchTemplate()的参数中使用mask=mask。这与使用mask值为255一起使得结果有所不同。然而,现在我得到了大量的误报,如下所示: http://ibb.co/esfTnk请注意,误报比真正的匹配更强烈。 有什么方法可以改进我的掩码以解决这个问题吗?目前,我只是使用我的模板的黑白转换。
0
和255
强度值的单通道掩码。 - ZdaR