模板匹配
本教程中你将学到如何:
- 使用 OpenCV 函数 matchTemplate() 在一个图像块与一幅输入图像之间搜索匹配
- 使用 OpenCV 函数 minMaxLoc() 在给定数组中寻找最大值与最小值(及其位置)。
什么是模板匹配?
Section titled “什么是模板匹配?”模板匹配(template matching)是一种在一幅图像中寻找与模板图像(图像块 patch)匹配(相似)区域的技术。
虽然图像块必须是矩形,但矩形的某些部分可能并不相关。在这种情况下,可以使用一个掩膜来隔离图像块中应当用于匹配的那一部分。
它是如何工作的?
Section titled “它是如何工作的?”-
我们需要两个主要组件:
- 源图像(I): 我们期望在其中找到与模板图像匹配的图像
- 模板图像(T): 将与源图像进行比较的图像块
我们的目标是检测匹配度最高的区域:
-
为识别匹配区域,我们需要通过滑动的方式将模板图像与源图像进行比较:
-
所谓滑动,是指每次将图像块移动一个像素(从左到右、从上到下)。在每个位置都计算一个度量,用以表示该位置处匹配“好”还是“坏”(或者说图像块与源图像该特定区域的相似程度)。
-
对于 T 在 I 上的每个位置,你将该度量存储在结果矩阵 R 中。R 中的每个位置 都包含匹配度量:
上图是用度量 TM_CCORR_NORMED 滑动图像块所得的结果 R。最亮的位置表示最高匹配。可以看到,红圈标记的位置很可能是取值最高的位置,因此该位置(以该点为一个角、宽高等于图像块的矩形)被视为匹配。
-
实际中,我们使用函数 minMaxLoc() 在 R 矩阵中定位最高值(或根据匹配方法类型,定位最低值)
掩膜是如何工作的?
Section titled “掩膜是如何工作的?”

-
如果匹配需要使用掩膜,则需要三个组件:
- 源图像(I): 我们期望在其中找到与模板图像匹配的图像
- 模板图像(T): 将与源图像进行比较的图像块
- 掩膜图像(M): 掩膜,一幅对模板进行遮罩的灰度图像
-
目前只有两种匹配方法接受掩膜:TM_SQDIFF 与 TM_CCORR_NORMED(关于 opencv 中可用的所有匹配方法,见下文说明)。
-
掩膜必须与模板具有相同的尺寸
-
掩膜的深度应为 CV_8U 或 CV_32F,且通道数与模板图像相同。在 CV_8U 情况下,掩膜的值被视为二值(即零与非零)。在 CV_32F 情况下,值应落在 [0..1] 范围内,模板像素将与对应的掩膜像素值相乘。由于示例中的输入图像类型为 CV_8UC3,掩膜也作为彩色图像读入。
OpenCV 中有哪些可用的匹配方法?
Section titled “OpenCV 中有哪些可用的匹配方法?”好问题。OpenCV 在函数 matchTemplate() 中实现了模板匹配。可用方法共 6 种:
-
method=TM_SQDIFF
-
method=TM_SQDIFF_NORMED
-
method=TM_CCORR
-
method=TM_CCORR_NORMED
-
method=TM_CCOEFF
其中
-
method=TM_CCOEFF_NORMED
-
这个程序做什么?
- 载入一幅输入图像、一个图像块(模板),以及可选的一个掩膜
- 使用 OpenCV 函数 matchTemplate() 配合前述 6 种匹配方法中的任意一种执行模板匹配。用户可通过在 Trackbar 中输入选择来选用方法。若提供了掩膜,则它只会用于支持掩膜的方法
- 对匹配过程的输出进行归一化
- 定位匹配概率最高的位置
- 在最高匹配对应的区域周围绘制一个矩形
-
可下载代码:点击 这里
-
代码一览: 代码见下方示例
-
可下载代码:点击 这里
-
代码一览: 代码见下方示例
-
可下载代码:点击 这里
-
代码一览: 代码见下方示例
- 声明一些全局变量,例如图像、模板与结果矩阵,以及匹配方法和窗口名称:
- 载入源图像、模板,并在匹配方法支持的情况下,可选地载入一个掩膜:
- 创建 Trackbar 以输入要使用的匹配方法种类。检测到变化时即调用回调函数。

- 我们来看回调函数。首先,它拷贝源图像:
- 执行模板匹配操作。参数自然是输入图像 I、模板 T、结果 R 以及匹配方法(由 Trackbar 给出),以及可选的掩膜图像 M。
- 我们对结果进行归一化:
- 我们使用 minMaxLoc() 定位结果矩阵 R 中的最小值与最大值。
- 对于前两种方法(TM_SQDIFF 与 TM_SQDIFF_NORMED),最佳匹配是最低值。对于其余所有方法,值越高表示匹配越好。因此,我们将对应的值保存到 matchLoc 变量中:
- 显示源图像与结果矩阵。在最高可能匹配区域周围绘制一个矩形:

-
用如下输入图像测试我们的程序:
以及一个模板图像:
-
生成如下结果矩阵(第一行是标准方法 SQDIFF、CCORR 与 CCOEFF,第二行是同样方法的归一化版本)。在第一列中,越暗表示匹配越好;对于另外两列,位置越亮则匹配度越高。
-
正确匹配如下图所示(右侧那个人脸部周围的黑色矩形)。注意 CCORR 与 CCOEFF 给出了错误的最佳匹配,然而它们的归一化版本却匹配正确。这可能是因为我们只考虑了“最高匹配”,而没有考虑其他可能的高匹配。