OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
模板匹配

上一个教程: 反向投影
下一个教程: 在图像中查找轮廓

原始作者Ana Huamán
兼容性OpenCV >= 3.0

目标

在本教程中,您将学习如何

  • 使用OpenCV函数 matchTemplate() 搜索图像块与输入图像之间的匹配项
  • 使用OpenCV函数 minMaxLoc() 查找给定数组中的最大值和最小值(及其位置)。

理论

什么是模板匹配?

模板匹配是一种在图像中查找与模板图像(块)匹配(相似)区域的技术。

虽然图像块必须是矩形,但可能并非所有矩形都相关。在这种情况下,可以使用掩膜来隔离图像块中应用于查找匹配的部分。

它是如何工作的?

  • 我们需要两个主要组成部分

    1. 源图像 (I): 我们期望在其中找到模板图像匹配项的图像
    2. 模板图像 (T): 将与源图像进行比较的图像块

    我们的目标是检测最高的匹配区域

  • 为了识别匹配区域,我们必须通过滑动来将模板图像与源图像进行比较
  • 通过滑动,我们指的是一次移动图像块一个像素(从左到右,从上到下)。在每个位置,都会计算一个度量,以表示该位置的匹配程度是“好”还是“坏”(或图像块与源图像特定区域的相似程度)。
  • 对于 TI 上方的每个位置,您将度量存储结果矩阵 R 中。R 中的每个位置 \((x,y)\) 都包含匹配度量

上图是使用度量 TM_CCORR_NORMED 滑动图像块的结果 R。最亮的位置表示最高的匹配。如您所见,红色圆圈标记的位置可能是值最高的位置,因此该位置(由该点作为角点以及宽度和高度等于图像块图像形成的矩形)被视为匹配。

  • 实际上,我们使用函数 minMaxLoc()R 矩阵中定位最高值(或最低值,取决于匹配方法的类型)

掩膜如何工作?

  • 如果匹配需要掩膜,则需要三个组件
    1. 源图像 (I): 我们期望在其中找到模板图像匹配项的图像
    2. 模板图像 (T): 将与源图像进行比较的图像块
    3. 掩膜图像 (M): 掩膜,一个掩盖模板的灰度图像
  • 目前只有两种匹配方法接受掩膜:TM_SQDIFF 和 TM_CCORR_NORMED(有关OpenCV中所有可用匹配方法的解释,请参见下文)。
  • 掩膜必须与模板具有相同的尺寸
  • 掩膜应具有CV_8U或CV_32F深度,并且与模板图像具有相同的通道数。在CV_8U情况下,掩膜值被视为二进制,即零和非零。在CV_32F情况下,值应在[0..1]范围内,模板像素将乘以相应的掩膜像素值。由于样本中的输入图像为CV_8UC3类型,因此掩膜也以彩色图像读取。

OpenCV中有哪些可用的匹配方法?

好问题。OpenCV在函数 matchTemplate() 中实现了模板匹配。可用的方法有6种

  1. 方法=TM_SQDIFF

    \[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\]

  2. 方法=TM_SQDIFF_NORMED

    \[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\]

  3. 方法=TM_CCORR

    \[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\]

  4. 方法=TM_CCORR_NORMED

    \[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\]

  5. 方法=TM_CCOEFF

    \[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\]

    其中

    \[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\]

  6. 方法=TM_CCOEFF_NORMED

    \[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\]

代码

  • 此程序的作用是什么?
    • 加载输入图像、图像块(模板)以及可选的掩膜
    • 使用OpenCV函数 matchTemplate() 执行模板匹配过程,使用前面描述的6种匹配方法中的任何一种。用户可以通过在轨迹条中选择来选择方法。如果提供了掩膜,它将仅用于支持掩膜的方法
    • 标准化匹配过程的输出
    • 定位匹配概率较高的位置
    • 在最高匹配区域周围绘制一个矩形

解释

  • 声明一些全局变量,例如图像、模板和结果矩阵,以及匹配方法和窗口名称

  • 加载源图像、模板,以及可选地,如果匹配方法支持,则加载掩膜

  • 创建轨迹条以输入要使用的匹配方法。检测到更改时,将调用回调函数。

  • 让我们看看回调函数。首先,它复制了源图像

  • 执行模板匹配操作。参数自然是输入图像 I、模板 T、结果 R 和匹配方法(由轨迹条给出),以及可选的掩膜图像 M

  • 我们标准化结果

  • 我们使用 minMaxLoc() 定位结果矩阵 R 中的最小值和最大值。

  • 对于前两种方法(TM_SQDIFF 和 MT_SQDIFF_NORMED),最佳匹配是最低值。对于所有其他方法,值越高表示匹配越好。因此,我们将相应的值保存在 matchLoc 变量中

  • 显示源图像和结果矩阵。在可能出现最高匹配的区域周围绘制一个矩形

结果

  1. 使用如下输入图像测试我们的程序

和模板图像

  1. 生成以下结果矩阵(第一行是标准方法SQDIFF、CCORR和CCOEFF,第二行是其归一化版本)。在第一列中,越暗表示匹配越好,对于其他两列,位置越亮表示匹配越高。

  1. 右侧的匹配项如下所示(右侧男子的脸部周围有黑色矩形)。请注意,CCORR和CCDEFF给出了错误的最佳匹配,但其归一化版本是正确的,这可能是由于我们只考虑“最高匹配”而不是其他可能的较高匹配。