了解和评估模板匹配方法
Understanding and evaluating template matching methods
OpenCV 有matchTemplate()
函数,它通过在输出上滑动模板输入,并生成与匹配对应的数组输出来操作。
我在哪里可以详细了解如何解读这六个 TemplateMatchModes?
我已经通读并实现了基于 tutorial 的代码,但除了了解人们寻找 TM_SQDIFF
的最小结果来匹配和寻找最大值之外,我不不知道如何解释不同的方法,以及人们会选择一种而不是另一种的情况。
例如(取自教程)
res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
和
R(x,y)= ∑x′,y′ (T′(x′,y′) ⋅ I′(x+x′,y+y′))
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−-------------
sqrt(∑x′,y′ T′(x′,y′)^2 ⋅ ∑x′,y′ I′(x+x′,y+y′)^2)
(取自文档页面;不确定如何进行公式格式化)
我会推断 TM_CCOEFF_NORMED
会 return 介于 0 和 1 之间的值,并且 0.8 阈值是任意的,但这只是假设。
是否有更深入的在线方程式、针对标准数据集的性能测量或关于不同模式以及何时以及为何使用一种模式的学术论文?
所有模板匹配模式都可以粗略地分类为密集(意味着像素方向)相似性度量,或者等效但相反,距离度量 图片之间。
通常,您会有两张图片,您希望以某种方式比较它们。马上,模板匹配不会直接帮助您匹配缩放、旋转或扭曲的东西。模板匹配严格关注测量两个图像的相似性,就像它们出现时一样。然而,这里使用的实际指标在计算机视觉中无处不在,包括寻找图像之间的转换......通常还有更复杂的步骤(比如梯度下降来找到最佳转换参数)。
距离度量有很多选择,根据应用的不同,它们通常各有利弊。
绝对差之和 (SAD)
首先,最基本的距离度量只是两个值之间的绝对差值,即 d(x, y) = abs(x - y)
。对于图像,从单个值扩展它的一种简单方法就是将所有这些距离按像素相加,从而得出绝对差值之和 (SAD) 度量;它也被称为 Manhattan 或 taxicab 距离,并定义了 L1 范数。令人讨厌的是,这并没有作为 OpenCV 的模板匹配模式之一实现,但在本次讨论中作为与 SSD 的比较仍然很重要。
在模板匹配场景中,您将模板沿多个位置滑动,然后简单地找到差异最小的位置。相当于询问数组[1, 4, 9]中最接近5的值的索引是多少。您将数组中每个值的绝对差值与 5 相差,索引 1 的差值最小,因此这是最接近匹配的位置。当然在模板匹配中这个值不是5而是一个数组,图片是一个更大的数组
差平方和 (SSD):TM_SQDIFF
SAD 指标的一个有趣特性是它不会对非常大的差异进行惩罚,而不会对一堆非常小的差异进行惩罚。假设我们要使用以下向量计算 d(a, b)
和 d(a, c)
:
a = [1, 2, 3]
b = [4, 5, 6]
c = [1, 2, 12]
逐元素求绝对差之和,我们看到
SAD(a, b) = 3 + 3 + 3 = 9 = 0 + 0 + 9 = SAD(a, c)
在某些应用程序中,这可能无关紧要。但在其他应用程序中,您可能希望这两个距离实际上完全不同。对差值求平方,而不是取它们的绝对值,而是惩罚与您期望值相差较远的值——随着值差的增加,它使图像 更远 更远。它更多地映射到某人如何将估计值解释为 way,即使在价值上它实际上并不 that 遥远。差平方和 (SSD) 等价于 欧氏距离 的平方,L2 范数 的距离函数。使用 SSD,我们看到我们的两个距离现在完全不同:
SSD(a, b) = 3^2 + 3^2 + 3^2 = 27 != 81 = 0^2 + 0^2 + 9^2 = SSD(a, c)
您可能会看到 L1 规范 有时被称为 稳健规范。这是因为单点错误不会比错误本身增加更多的距离。但当然对于 SSD,离群值会使距离变大。因此,如果您的数据在某种程度上倾向于一些非常遥远的值,请注意 SSD 对您来说可能不是一个好的相似性度量。一个很好的例子可能是比较可能曝光过度的图像。在图像的某些部分,您可能只有白色的天空,而另一个根本不是白色的,因此图像之间的距离会很大。
当比较的两个图像相同时,SAD 和 SSD 的最小距离均为 0。它们总是非负的,因为绝对差或平方差总是非负的。
互相关(CC):TM_CCORR
SAD 和 SSD 通常都是离散指标——因此它们是采样信号(如图像)的自然考虑因素。然而,互相关也适用于连续信号,因此也适用于模拟信号,这是其在信号处理中普遍存在的一部分。对于广义的信号,尝试检测信号内模板的存在被称为 匹配过滤器 ,您基本上可以将其视为模板匹配的连续模拟。
互相关只是将两个图像相乘。您可以想象,如果两个信号完全对齐,将它们相乘将简单地使模板平方。如果它们没有按原样排列,那么产品就会变小。所以,产品最大化的位置就是他们排列最好的地方。但是,当您将互相关用作您不确定是否相关的信号的相似性度量时,互相关会出现问题,这通常在以下示例中显示。假设你有三个数组:
a = [2, 600, 12]
b = [v, v, v]
c = [2v, 2v, 2v]
从广义上讲,a
和 b
以及 a
和 c
之间没有明显的相关性。通常,a
与 b
的关联不应比与 c
的关联更多。但是,它是一种产品,因此 ccorr(a, c) = 2*ccorr(a, b)
。因此,这对于尝试在较大图像中查找模板并不理想。因为我们处理的是具有定义最大值(图像)的离散数字信号,这意味着图像的亮白色块基本上总是具有最大相关性。由于这个问题,TM_CCORR
作为模板匹配方法并不是特别有用。
均值偏移互相关(皮尔逊相关系数):TM_CCOEFF
解决与亮斑相关问题的一种简单方法是在比较信号之前简单地减去均值。这样,简单移位的信号与未移位的信号具有相同的相关性。这符合我们的直觉——一起变化的信号是相关的。
规范化:TM_SQDIFF_NORMED
、TM_CCORR_NORMED
、TM_CCOEFF_NORMED
OpenCV 中的所有方法都经过相同的归一化处理。规范化的要点是 而不是 以提供 confidence/probability,而是提供可以与不同大小的模板或不同比例的值进行比较的指标。例如,假设我们想要查找某个对象是否在图像中,并且我们有该对象的两个不同模板。两个不同的模板大小不同。我们可以只按像素数进行归一化,这可以用来比较不同大小的模板。然而,假设我的模板实际上在强度上有很大不同,比如一个模板的像素值方差比另一个模板高得多。通常,在这种情况下,您要做的是除以标准差(均值平方差之和的平方根)。 OpenCV 确实使用 TM_CCOEFF_NORMED
方法执行此操作,因为均值差的平方和 是 方差,但其他方法不是均值偏移,因此缩放只是图像值总和的度量。无论哪种方式,结果都是相似的,您希望通过与所用图像块强度相关的东西进行缩放。
其他指标
OpenCV 没有提供其他有用的指标。 Matlab提供了SAD,以及最大绝对差度量(MaxAD),也称为uniform distance metric,给出了L∞范数.基本上,您采用最大绝对差而不是它们的总和。使用的其他指标通常出现在优化设置中,例如 enhanced correlation coefficient which was first proposed for stereo matching, and then later expanded for alignment in general. That method is used in OpenCV, but not for template matching; you'll find the ECC metric in computeECC()
and findTransformECC()
.
使用哪种方法?
大多数情况下,您会看到使用规范化和非规范化 SSD(TM_SQDIFF_NORMED
、TM_SQDIFF
)和零规范化互相关/ZNCC (TM_CCOEFF_NORMED
)。有时您可能会看到 TM_CCORR_NORMED
,但不常见。根据我在网上找到的一些 lecture notes(关于这个主题的一些很好的例子和直觉!),Trucco 和 Verri 的 CV 书指出,通常 SSD 比相关性更好,但我没有 T&V 的书来了解为什么他们建议;大概是在真实世界的照片上进行比较。但尽管如此,SAD 和 SSD 绝对有用,尤其是在数字图像上。
我不知道有任何明确的例子可以证明其中一个或另一个在大多数情况下本质上更好或其他什么---我认为这真的取决于您的图像和模板。一般来说,我会说:如果您正在寻找精确匹配或非常接近精确匹配,请使用 SSD。它速度很快,而且它肯定会映射到您想要最小化的内容(模板和图像补丁之间的差异)。在这种情况下不需要规范化,它只是增加了开销。如果你有类似的需求,但需要多个模板进行比较,那就归一化SSD。如果您正在寻找匹配项,但您正在处理可能存在曝光或对比度差异的真实照片,则 ZNCC 的均值偏移和方差均衡可能是最好的。
至于选择正确的阈值,ZNCC 或 SSD 的值根本不是置信度或概率数。如果您想选择正确的阈值,您可以通过多种典型方式测量参数。您可以计算不同阈值的 ROC 曲线或 PR 曲线。您可以使用回归来找到最佳参数。您需要标记一些数据,但至少您可以衡量您在某些测试集上的表现,这样您的选择就不是随意的。与数据填充字段一样,您需要确保您的数据尽可能接近真实世界的示例,并且您的测试数据涵盖您的边缘情况以及您的典型图像。
OpenCV 有matchTemplate()
函数,它通过在输出上滑动模板输入,并生成与匹配对应的数组输出来操作。
我在哪里可以详细了解如何解读这六个 TemplateMatchModes?
我已经通读并实现了基于 tutorial 的代码,但除了了解人们寻找 TM_SQDIFF
的最小结果来匹配和寻找最大值之外,我不不知道如何解释不同的方法,以及人们会选择一种而不是另一种的情况。
例如(取自教程)
res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
和
R(x,y)= ∑x′,y′ (T′(x′,y′) ⋅ I′(x+x′,y+y′))
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−-------------
sqrt(∑x′,y′ T′(x′,y′)^2 ⋅ ∑x′,y′ I′(x+x′,y+y′)^2)
(取自文档页面;不确定如何进行公式格式化)
我会推断 TM_CCOEFF_NORMED
会 return 介于 0 和 1 之间的值,并且 0.8 阈值是任意的,但这只是假设。
是否有更深入的在线方程式、针对标准数据集的性能测量或关于不同模式以及何时以及为何使用一种模式的学术论文?
所有模板匹配模式都可以粗略地分类为密集(意味着像素方向)相似性度量,或者等效但相反,距离度量 图片之间。
通常,您会有两张图片,您希望以某种方式比较它们。马上,模板匹配不会直接帮助您匹配缩放、旋转或扭曲的东西。模板匹配严格关注测量两个图像的相似性,就像它们出现时一样。然而,这里使用的实际指标在计算机视觉中无处不在,包括寻找图像之间的转换......通常还有更复杂的步骤(比如梯度下降来找到最佳转换参数)。
距离度量有很多选择,根据应用的不同,它们通常各有利弊。
绝对差之和 (SAD)
首先,最基本的距离度量只是两个值之间的绝对差值,即 d(x, y) = abs(x - y)
。对于图像,从单个值扩展它的一种简单方法就是将所有这些距离按像素相加,从而得出绝对差值之和 (SAD) 度量;它也被称为 Manhattan 或 taxicab 距离,并定义了 L1 范数。令人讨厌的是,这并没有作为 OpenCV 的模板匹配模式之一实现,但在本次讨论中作为与 SSD 的比较仍然很重要。
在模板匹配场景中,您将模板沿多个位置滑动,然后简单地找到差异最小的位置。相当于询问数组[1, 4, 9]中最接近5的值的索引是多少。您将数组中每个值的绝对差值与 5 相差,索引 1 的差值最小,因此这是最接近匹配的位置。当然在模板匹配中这个值不是5而是一个数组,图片是一个更大的数组
差平方和 (SSD):TM_SQDIFF
SAD 指标的一个有趣特性是它不会对非常大的差异进行惩罚,而不会对一堆非常小的差异进行惩罚。假设我们要使用以下向量计算 d(a, b)
和 d(a, c)
:
a = [1, 2, 3]
b = [4, 5, 6]
c = [1, 2, 12]
逐元素求绝对差之和,我们看到
SAD(a, b) = 3 + 3 + 3 = 9 = 0 + 0 + 9 = SAD(a, c)
在某些应用程序中,这可能无关紧要。但在其他应用程序中,您可能希望这两个距离实际上完全不同。对差值求平方,而不是取它们的绝对值,而是惩罚与您期望值相差较远的值——随着值差的增加,它使图像 更远 更远。它更多地映射到某人如何将估计值解释为 way,即使在价值上它实际上并不 that 遥远。差平方和 (SSD) 等价于 欧氏距离 的平方,L2 范数 的距离函数。使用 SSD,我们看到我们的两个距离现在完全不同:
SSD(a, b) = 3^2 + 3^2 + 3^2 = 27 != 81 = 0^2 + 0^2 + 9^2 = SSD(a, c)
您可能会看到 L1 规范 有时被称为 稳健规范。这是因为单点错误不会比错误本身增加更多的距离。但当然对于 SSD,离群值会使距离变大。因此,如果您的数据在某种程度上倾向于一些非常遥远的值,请注意 SSD 对您来说可能不是一个好的相似性度量。一个很好的例子可能是比较可能曝光过度的图像。在图像的某些部分,您可能只有白色的天空,而另一个根本不是白色的,因此图像之间的距离会很大。
当比较的两个图像相同时,SAD 和 SSD 的最小距离均为 0。它们总是非负的,因为绝对差或平方差总是非负的。
互相关(CC):TM_CCORR
SAD 和 SSD 通常都是离散指标——因此它们是采样信号(如图像)的自然考虑因素。然而,互相关也适用于连续信号,因此也适用于模拟信号,这是其在信号处理中普遍存在的一部分。对于广义的信号,尝试检测信号内模板的存在被称为 匹配过滤器 ,您基本上可以将其视为模板匹配的连续模拟。
互相关只是将两个图像相乘。您可以想象,如果两个信号完全对齐,将它们相乘将简单地使模板平方。如果它们没有按原样排列,那么产品就会变小。所以,产品最大化的位置就是他们排列最好的地方。但是,当您将互相关用作您不确定是否相关的信号的相似性度量时,互相关会出现问题,这通常在以下示例中显示。假设你有三个数组:
a = [2, 600, 12]
b = [v, v, v]
c = [2v, 2v, 2v]
从广义上讲,a
和 b
以及 a
和 c
之间没有明显的相关性。通常,a
与 b
的关联不应比与 c
的关联更多。但是,它是一种产品,因此 ccorr(a, c) = 2*ccorr(a, b)
。因此,这对于尝试在较大图像中查找模板并不理想。因为我们处理的是具有定义最大值(图像)的离散数字信号,这意味着图像的亮白色块基本上总是具有最大相关性。由于这个问题,TM_CCORR
作为模板匹配方法并不是特别有用。
均值偏移互相关(皮尔逊相关系数):TM_CCOEFF
解决与亮斑相关问题的一种简单方法是在比较信号之前简单地减去均值。这样,简单移位的信号与未移位的信号具有相同的相关性。这符合我们的直觉——一起变化的信号是相关的。
规范化:TM_SQDIFF_NORMED
、TM_CCORR_NORMED
、TM_CCOEFF_NORMED
OpenCV 中的所有方法都经过相同的归一化处理。规范化的要点是 而不是 以提供 confidence/probability,而是提供可以与不同大小的模板或不同比例的值进行比较的指标。例如,假设我们想要查找某个对象是否在图像中,并且我们有该对象的两个不同模板。两个不同的模板大小不同。我们可以只按像素数进行归一化,这可以用来比较不同大小的模板。然而,假设我的模板实际上在强度上有很大不同,比如一个模板的像素值方差比另一个模板高得多。通常,在这种情况下,您要做的是除以标准差(均值平方差之和的平方根)。 OpenCV 确实使用 TM_CCOEFF_NORMED
方法执行此操作,因为均值差的平方和 是 方差,但其他方法不是均值偏移,因此缩放只是图像值总和的度量。无论哪种方式,结果都是相似的,您希望通过与所用图像块强度相关的东西进行缩放。
其他指标
OpenCV 没有提供其他有用的指标。 Matlab提供了SAD,以及最大绝对差度量(MaxAD),也称为uniform distance metric,给出了L∞范数.基本上,您采用最大绝对差而不是它们的总和。使用的其他指标通常出现在优化设置中,例如 enhanced correlation coefficient which was first proposed for stereo matching, and then later expanded for alignment in general. That method is used in OpenCV, but not for template matching; you'll find the ECC metric in computeECC()
and findTransformECC()
.
使用哪种方法?
大多数情况下,您会看到使用规范化和非规范化 SSD(TM_SQDIFF_NORMED
、TM_SQDIFF
)和零规范化互相关/ZNCC (TM_CCOEFF_NORMED
)。有时您可能会看到 TM_CCORR_NORMED
,但不常见。根据我在网上找到的一些 lecture notes(关于这个主题的一些很好的例子和直觉!),Trucco 和 Verri 的 CV 书指出,通常 SSD 比相关性更好,但我没有 T&V 的书来了解为什么他们建议;大概是在真实世界的照片上进行比较。但尽管如此,SAD 和 SSD 绝对有用,尤其是在数字图像上。
我不知道有任何明确的例子可以证明其中一个或另一个在大多数情况下本质上更好或其他什么---我认为这真的取决于您的图像和模板。一般来说,我会说:如果您正在寻找精确匹配或非常接近精确匹配,请使用 SSD。它速度很快,而且它肯定会映射到您想要最小化的内容(模板和图像补丁之间的差异)。在这种情况下不需要规范化,它只是增加了开销。如果你有类似的需求,但需要多个模板进行比较,那就归一化SSD。如果您正在寻找匹配项,但您正在处理可能存在曝光或对比度差异的真实照片,则 ZNCC 的均值偏移和方差均衡可能是最好的。
至于选择正确的阈值,ZNCC 或 SSD 的值根本不是置信度或概率数。如果您想选择正确的阈值,您可以通过多种典型方式测量参数。您可以计算不同阈值的 ROC 曲线或 PR 曲线。您可以使用回归来找到最佳参数。您需要标记一些数据,但至少您可以衡量您在某些测试集上的表现,这样您的选择就不是随意的。与数据填充字段一样,您需要确保您的数据尽可能接近真实世界的示例,并且您的测试数据涵盖您的边缘情况以及您的典型图像。