• 008 OpenCV matchTemplate 模板匹配


    目录

    一、环境

    二、模板匹配算法原理

    三、代码演示


    一、环境

    本文使用环境为:

    • Windows10
    • Python 3.9.17
    • opencv-python 4.8.0.74

    二、模板匹配算法原理

    cv.matchTemplate是OpenCV库中的一个函数,用于在图像中查找与模板匹配的特征。它的主要应用场景是在图像处理、计算机视觉和模式识别等领域。

    算法原理: cv.matchTemplate函数通过计算输入图像与模板图像之间的相似度来找到最佳匹配位置。它使用滑动窗口的方法在输入图像上移动模板图像,并计算每个窗口内的像素值差异。然后,根据所选的匹配方法(如平方差、归一化平方差、相关系数等),对差异进行加权求和,得到一个匹配得分矩阵。最后,函数返回得分矩阵中的最大值及其位置,作为最佳匹配位置。

    函数API:

    retval, result = cv2.matchTemplate(image, templ, method, mask)
    

    参数说明:

    • image:输入图像,通常是一个灰度图像。
    • templ:模板图像,可以是灰度图像或彩色图像。
    • method:匹配方法,常用的有:
      • cv2.TM_SQDIFF:平方差匹配法,计算结果越小表示匹配程度越高。
      • cv2.TM_SQDIFF_NORMED:归一化平方差匹配法,计算结果越接近0表示匹配程度越高。
      • cv2.TM_CCORR:相关系数匹配法,计算结果越接近1表示匹配程度越高。
      • cv2.TM_CCORR_NORMED:归一化相关系数匹配法,计算结果越接近1表示匹配程度越高。
      • cv2.TM_CCOEFF:相关系数匹配法,计算结果越接近1表示匹配程度越高。
      • cv2.TM_CCOEFF_NORMED:归一化相关系数匹配法,计算结果越接近1表示匹配程度越高。
    • mask:可选参数,mask是一个二值图,作用于参数temp1,有效区域则参与模板匹配计算

    返回值说明:

    • result:匹配结果矩阵,每个元素表示对应位置的匹配程度。
    • minVal, maxVal, minLoc, maxLoc:最佳匹配位置的最小值、最大值、最小值位置和最大值位置。

    下面是对 cv.matchTemplate() 算法的简单解释:

    1. 预处理:首先,将输入图像和模板图像转换为灰度图像。这是因为 cv.matchTemplate() 算法只支持灰度图像。
    2. 滑动模板:然后,算法会在输入图像上滑动模板。对于每个位置(从左到右、从上到下呗),都会计算一个匹配分数。这个分数取决于当前位置的图像和模板的相似性。
    3. 计算匹配分数:根据选择的匹配方法,计算当前位置的匹配分数。例如,如果选择的是归一化相关系数方法,那么算法会计算输入图像和模板在当前位置的相关系数。其他方法,如归一化相关、平方差等,会有不同的计算方式。
    4. 找到最匹配的位置:在所有位置中,算法会找到匹配分数最高的位置。这个位置就是最匹配的位置。
    5. 返回结果:最后,函数会返回一个包含所有匹配区域信息的结构。这个结构包含了每个匹配区域的坐标、匹配分数等信息。

    需要注意的是,由于滑动窗口的限制,如果模板和图像的某些区域不匹配,这些区域将不会被计入匹配分数。这是通过使用掩码(mask)参数实现的。掩码是一个与模板大小相同的二维数组,值可以是0或1。在掩码中为1的位置将被计入匹配分数,为0的位置则不会被计入。

    总的来说,cv.matchTemplate() 是一个强大的工具,可以用于在图像中查找和模板最匹配的区域。它广泛应用于图像处理、计算机视觉和模式识别等领域。

    三、代码演示

    代码中需要的三张图,这里给出来,lena_tmpl.jpg,以下是原图:

    tmpl.png,以下是模板图,意思是:在原图中找到与其相似的区域,用矩形画出来。

    mask.png,必须与tmp1.png尺寸相同,是一个二值图,用于表示:模板计算过程中,模板图中哪些区域用于模板匹配。

    1. from __future__ import print_function
    2. import sys
    3. import cv2 as cv
    4. # 全局变量
    5. use_mask = False
    6. img = None
    7. templ = None
    8. mask = None
    9. image_window = "Source Image"
    10. result_window = "Result window"
    11. match_method = 0
    12. max_Trackbar = 5
    13. def main():
    14. # 读取三张图
    15. global img
    16. global templ
    17. img = cv.imread('data/lena_tmpl.jpg', cv.IMREAD_COLOR) # 图片1
    18. templ = cv.imread('data/tmpl.png', cv.IMREAD_COLOR) # 图片2
    19. global use_mask
    20. use_mask = True
    21. global mask
    22. mask = cv.imread('data/mask.png', cv.IMREAD_COLOR ) # 图片3
    23. if ((img is None) or (templ is None) or (use_mask and (mask is None))):
    24. print('Can\'t read one of the images')
    25. return -1
    26. cv.namedWindow( image_window, cv.WINDOW_AUTOSIZE )
    27. cv.namedWindow( result_window, cv.WINDOW_AUTOSIZE )
    28. # 创建滑条
    29. trackbar_label = 'Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED'
    30. cv.createTrackbar( trackbar_label, image_window, match_method, max_Trackbar, MatchingMethod )
    31. # 执行模板匹配
    32. MatchingMethod(match_method)
    33. cv.waitKey(0)
    34. return 0
    35. def MatchingMethod(param):
    36. global match_method
    37. match_method = param
    38. img_display = img.copy()
    39. # 模板匹配
    40. method_accepts_mask = (cv.TM_SQDIFF == match_method or match_method == cv.TM_CCORR_NORMED)
    41. if (use_mask and method_accepts_mask):
    42. result = cv.matchTemplate(img, templ, match_method, None, mask)
    43. else:
    44. result = cv.matchTemplate(img, templ, match_method)
    45. # 将结果进行归一化到[0, 1]
    46. cv.normalize( result, result, 0, 1, cv.NORM_MINMAX, -1 )
    47. # 找到最佳匹配
    48. _minVal, _maxVal, minLoc, maxLoc = cv.minMaxLoc(result, None)
    49. # 得到的匹配位置,即:一个矩形框
    50. if (match_method == cv.TM_SQDIFF or match_method == cv.TM_SQDIFF_NORMED):
    51. matchLoc = minLoc
    52. else:
    53. matchLoc = maxLoc
    54. # 可视化
    55. cv.rectangle(img_display, matchLoc, (matchLoc[0] + templ.shape[0], matchLoc[1] + templ.shape[1]), (0,255,0), 2, 8, 0 )
    56. cv.rectangle(result, matchLoc, (matchLoc[0] + templ.shape[0], matchLoc[1] + templ.shape[1]), (0,0,255), 2, 8, 0 )
    57. cv.imshow(image_window, img_display)
    58. cv.imshow(result_window, result)
    59. pass
    60. if __name__ == "__main__":
    61. main()

    以下是不同算法运行效果,哪些算法吊,一眼就能看出来,自己可以玩一玩哈。

    \n 0: SQDIFF

    \n 1: SQDIFF

    \n 2: TM CCORR

    \n 3: TM CCORR

    \n 4: TM COEFF

    \n 5: TM COEFF

  • 相关阅读:
    在中国,技术到底有多有用?
    微服务项目:尚融宝(4)(上手复习mybatisplus)
    运动项目记录
    用10元,20元,50元三种币值的纸币凑出1000元,一共有多少种组合(C++实现)三种思路,两种实现
    数据结构与算法(八):排序算法
    辰视冯良炳博士将于ITES机器视觉与机器人创新应用大讲台开讲
    UiPath:一家由生成式AI驱动的流程自动化软件公司
    JavaSSM笔记(二)SpringMvc基础
    家用电器行业商业供应链协同平台解决方案:供应链系统管理精益化,助推企业智造升级
    C语言课程回顾:十、C语言之 指针
  • 原文地址:https://blog.csdn.net/m0_72734364/article/details/134548276