OpenCV 4.11.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. method=TM_SQDIFF

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

  2. method=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. method=TM_CCORR

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

  4. method=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. method=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. method=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 给出了错误的最佳匹配,但是它们的归一化版本做对了,这可能是因为我们只考虑了“最高匹配”,而不是其他可能的较高匹配。