图像处理讲义——模板匹配
1|0什么是模板匹配(Template Matching)
模板匹配是指在当前图像 A 内寻找与图像 B 最相似的部分,一般将图像 A 称为输入图像, 将图像 B 称为模板图像。模板匹配的操作方法是将模板图像 B 在图像 A 上滑动,遍历所有像素以完成匹配。
举个例子:我们现在有模板图像,以及输入图像(都是灰度图像且模板图像更小),设模板图像高为\(h_t\),宽为\(w_t\),输入图像高为\(h\),宽为\(w\),则模板匹配的过程为:
- 将模板图像放在输入图像内,设模板图像左上角顶点在输入图像的位置为\(P = (x,y)\),将模板图像放到\((0,0)\)的位置,进行第一次匹配,计算匹配度(匹配度计算后面再说)
- 然后将模板图像放到\((1,0)\)的位置,即向右移动一个像素,再次计算匹配度;然后再移动一个像素······一直移动到第一行末尾,每次都计算匹配度,可以发现一共计算了\(w-w_t+1\)次匹配度
- 第一行匹配结束,将模板图像放到\((0,1)\)的位置,开始第二行的匹配······和第一行一样,一共计算了\(w-w_t+1\)次匹配度
- 以此类推,直到最后一行匹配结束,可以发现整个模板匹配的过程中,我们一共计算了\((w-w_t+1)*(h-h_t+1)\)次匹配度
- 最后将匹配度以矩阵的形式返回(匹配度的位置与匹配时模板图像所在的位置一样),且该矩阵行数为\(h-h_t+1\),列数为\(w-w_t+1\)(在python中就是二维数组)



2|0模板匹配的代码实现
2|1单模板匹配
所谓单模板匹配,就是一个模板只能匹配输入图像中的一个位置,即一个一对一的映射。
我们先来看看opencv中与模板匹配相关的api函数吧
result = cv2.matchTemplate(image, templ, method[, mask ] )
- image 为原始图像,必须是 8 位或者 32 位的浮点型图像。
- templ 为模板图像。它的尺寸必须小于或等于原始图像,并且与原始图像具有同样的类型。
- method 为匹配方法。该参数通过 TemplateMatchModes 实现,有 6 种可能的值,如下图所示。
具体计算公式如下图所示
-
mask 为模板图像掩模。它必须和模板图像 templ 具有相同的类型和大小。通常情况下 该值使用默认值即可。当前,该参数仅支持 TM_SQDIFF 和 TM_CCORR_NORMED 两 个值。
-
result 为返回值,是一个行数为\(h-h_t+1\),列数为\(w-w_t+1\)的二维数组,每个元素代表由method对应公式计算出来的匹配度
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc( src [, mask] )
- src为单通道数组
- minVal 为返回的最小值,如果没有最小值,则可以是 NULL(空值)。
- maxVal 为返回的最大值,如果没有最小值,则可以是 NULL。
- minLoc 为最大值的位置,如果没有最大值,则可以是 NULL。
- maxLoc 为最大值的位置,如果没有最大值,则可以是 NULL。
- mask 为用来选取掩模的子集,可选项。
用途:该函数可以对 cv2.matchTemplate 函数的返回值 result 进行处理,找到 result 所代表的二维数组中最大值/最小值,及其所在的行列坐标位置(用opencv的坐标系表示,即 Loc[0] 为列数, Loc[1] 为行数)
模板匹配完成后,我们可以用opencv中的 cv2.rectangle 函数标记出我们所匹配到的位置
Img = cv.rectangle( img, pt1, pt2, color[, thickness])
- img 表示要标记的目标图像。
- pt1 是矩形的顶点。
- pt2是pt1的对角顶点
- color是颜色(灰度图像中就是明暗强度)
- thickness是矩形边线宽度(可选)
2|2单模板匹配的代码实现
2|3多模板匹配
在日常的代码编写中,我们大都会遇到这种情况:你有模板1、2、3···n,每个模板在输入图像里都有多处匹配的位置。这时,你就不能使用 cv2.minMaxLoc 函数来获取最佳匹配位置,因为你所需要的是一个一对多的映射,而非一对一的映射,所以你需要另一种方法对 cv2.matchTemplate 函数的返回值 result 数组进行处理,来获取所有能匹配的位置,这也就是多模板匹配与单模板匹配的区别。
那么,我们如何处理 result 数组呢?
熟悉 numpy 的同学知道,numpy中有一个 np.where 函数,能够返回numpy数组中满足输入条件的所有元素的行列位置信息,该函数原型为:
loc = np.where( res >= threshold)
例如:
则改代码返回结果为:
上述结果说明,存在二维数组 am,其中,位置[0, 1]、[0, 2]、[0, 3]、[0, 4]、[1, 2]、[1, 4]、[2, 0]、[2, 2]上的元素值大于 5。
但是,我们一般所需要的位置信息是例如 [column, row] 这样行列索引的集合,而非上面那样第一行是行数索引,第二行是列数索引的矩阵,所以我们还需要对上面的返回结果进行处理,也就是线性代数中对矩阵进行转置。
熟悉python的同学知道,python里有一个 zip 函数,其用可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由 这些元组组成的列表。
举个例子,对于前面提到的数组 am,使用函数 zip()循环,就可以得到其中大于 5 的元素索引的集合
输出结果为:
可以看到,我们能够获得形如 (column, row) 的位置信息了。但是在opencv坐标系中,我们的坐标是形如 (x, y) 的,其中x为列数,y为行数,所以我们需要将 (column, row) 变成 (row, column) ,即对数组元素进行倒置。这里我们使用python内置的 loc 函数。
举个例子:
输出为:
这样,我们就可以进行我们的多模板匹配了。
2|4多模板匹配的代码实现
如果对python语言不是很熟悉的同学可能一开始看不太懂,可以多让chatGPT解释一下各段代码并自行理解消化😊
__EOF__

本文链接:https://www.cnblogs.com/Asaka-QianXiang/p/18024680.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-02-21 【线性代数复习笔记】矩阵特征值,特征向量,相似对角化与实对称矩阵