如何解释matchtemplate的输出?(openCV, Python)

10

阅读了文档并在互联网上搜索后,我仍然不理解如何解释来自openCV的matchTemplate函数的输出。

我的理解:

result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)

我理解的是,针对图片中的每个部分,我会得到一个匹配值矩阵。该矩阵中的每个元素决定了它与模板的相似度。

例如,我可以使用 numpy.where(result >= 0.7) 过滤掉所有匹配值低于0.7的位置。

我不理解的是,matchTemplate函数返回的输出如何存储这些信息,并且如何从输出中提取匹配的位置。

基本上,我想做的是将多个模板与一张图片进行匹配,然后确定哪个模板与哪个位置最匹配(对于一个位置来说,所有应用模板的匹配值中哪个最大)。

我的想法是为每个模板提取匹配值并将其放入一个矩阵中,然后将这些矩阵(它们的元素)相互比较,以找到最佳匹配。

感谢您的帮助,请在我错误的地方进行修正。

问候Don

3个回答

2
我不理解的是,如何从matchTemplate函数的输出中提取匹配位置,并且这些信息是如何存储的。该结果将返回图像中每个像素与模板的相似度,例如与模板左上角像素的相似度。
loc =numpy.where(result >= 0.7)

我们将使用上述方法来筛选可能性。我们将获取图像中可能性大于0.7的像素与模板顶角的x坐标和y坐标。
#(array([202, 203, 203, 203, 204]), array([259, 258, 259, 260, 259]))

现在我们获取了与左上角模板相似度可能大于或等于0.7的图像位置。
在我们的示例输出中,可以看到我们可以根据阈值获得许多匹配点。我们需要循环它们以找到每个位置。
由于我们知道loc变量是一个元组,包含两个NumPy数组(Y坐标NumPy数组和X坐标NumPy数组),我们需要解包元组并反转数组的顺序以获取模板的实际位置,如下所示。
“基本上我想做的是将几个模板与一张图像匹配,然后确定哪个模板最符合每个位置(在所有应用的模板中具有最大匹配值)。”
问题是,每个结果的形状不同,因为它取决于模板的高度和宽度。
我们可以轻松地使用cv2.resize方法使所有模板具有相同的形状(可以近似为所有模板)。
'''
my original  template shapes
img (1256, 1300)
tempate (215, 223)
tempate (217, 204)
tempate (207, 203)
width =220
height = 225
temp  =  cv2.resize(temp,(width,height),cv2.INTER_CUBIC)

这个使我们的结果与下面的形状相同。
res = cv2.matchTemplate(gray, temp,cv2.TM_CCOEFF_NORMED)
print(res.shape) #output (1032, 1081)

我的方法

  • 我找到了包含所有结果的最大可能数组。所有的结果都被添加到结果列表中。
  • maximum_values_array = np.maximum(*results)
    

    我找到了该位置具有最大值的res。
    maximum_value_contains_array =np.array(results).argmax(axis=0)     
    

    我遍历每一个大于零的可能值(阈值>0.7),根据具有最大值的数组选择颜色。
    
    for i in range(len(maximum_values_array)):
      for j in range(len(maximum_values_array[i])):
        if maximum_values_array[i][j]>0:
          colour = colours[maximum_value_contains_array[i][j]]
          top_lect = (j,i)
          bottom_right = (j+width, i+height)
          cv2.rectangle(img,top_lect,bottom_right, colour, 2)
    

    完整的 Python 代码
    import cv2
    import numpy as np
    img  = cv2.imread('test.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    templates = [cv2.imread('blue_temp.jpg', 0), cv2.imread('yellow_temp.jpg', 0), cv2.imread('red_temp.jpg', 0)]
    colours =[(255,0,0), (0,255,0),(0,0,255)]
    
    results =[]
    for temp in templates:
      print(temp.shape)
      width =205
      height = 205
      # temp  =  cv2.resize(temp,(width,height),cv2.INTER_CUBIC)
      res = cv2.matchTemplate(gray, temp,cv2.TM_CCOEFF_NORMED)
      res[res<0.9] =0
      results.append(res)
    maximum_values_array = np.maximum(*results)
    maximum_value_contains_array =np.array(results).argmax(axis=0)     
    print(maximum_values_array.shape)
    print(maximum_value_contains_array.shape)
    
    for i in range(len(maximum_values_array)):
      for j in range(len(maximum_values_array[i])):
        if maximum_values_array[i][j]>0:
          print(maximum_values_array[i][j])
          colour = colours[maximum_value_contains_array[i][j]]
          top_lect = (j,i)
          bottom_right = (j+width, i+height)
          cv2.rectangle(img,top_lect,bottom_right, colour, 2)
    cv2_imshow(img)
    cv2.imwrite('output.png', img)
    
    
     
    

    我假设矩形内部没有重叠。 - Sivaram Rasathurai

    0
    你可以使用以下代码:
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    

    当使用cv2.TM_CCOEFF_NORMED时,max_loc将是模板在图像中的位置。而max_val将是匹配的相关性。


    该位置是模板的左上角、右上角、左下角、右下角或中心? - SaintTail
    两个位置都在左上角。 - smerlung
    3
    那并没有真正回答这个问题。 - Flash Thunder

    0

    它简单地将模板图像滑动到输入图像上(就像2D卷积一样),并在模板图像下比较输入图像的补丁和模板。

    如果输入图像的大小为(WxH),模板图像的大小为(wxh),则输出图像的大小将为(W-w+1,H-h+1)。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接