0

我有一张图像,我需要尽可能快地检测到一个物体。我也知道我只需要检测离中心最近的物体。

AFAIK Opencv 的 MatchTemplate 有点像这样(伪代码):

for(x in width):
    for(y in height):
        value = calcSimilarity(inputImage, searchedImage, x, y)
        matched[x][y] = value

之后,我必须遍历生成的图像并找到离中心最近的点,这都是相当浪费的。

所以我想知道我是否可以做类似的事情:

coordsGen = new CoordsGen() // a class that generates specific coords for me
while(!coordsGen.stop):
    x, y = coordsGen.next()
    value = calcSimilarity(inputImage, searchedImage, x, y)
    if(value > treshold)
        return x, y

基本上我在这里需要的是 calcSimilarity 函数。这将使我能够大大优化流程。

4

1 回答 1

1

模板匹配的相似度评分方法有多种选择。 *

OpenCV 有 3 种可用的模板匹配模式:

  • 平方差之和(欧几里得距离)
  • 互相关
  • 皮尔逊相关系数

在 OpenCV 中,这三个中的每一个都具有规范/缩放版本:

  • 归一化平方差和
  • 归一化互相关
  • 归一化皮尔逊相关系数

您可以在 TemplateMatchModes 下查看 OpenCV 文档中使用的实际公式,尽管这些公式与上述方法随处可见的通用公式一致。


您可以编写与自己匹配的模板,而不是使用 OpenCV。但是,请注意,OpenCV 已针对这些操作进行了优化,并且通常在模板匹配方面速度极快。OpenCV 使用 DFT 来执行其中一些计算以减少计算负载。例如,请参阅:

您还可以使用 OpenCVminMaxLoc()来查找最小/最大值,而不是自己循环。此外,您没有指定如何访问您的值,但并非所有查找方法都与其他方法一样快。请参阅如何扫描图像以查看最快的Mat访问操作。剧透:原始指针。


您的优化希望给您带来的主要加速是提前终止该功能。但是,我认为您通常不会通过自己编码来获得更快的时间,除非模板通常包含的原始图像的子集要小得多。

如果图像非常大,减少搜索时间的更好方法是使用金字塔分辨率方法。基本上,制作模板和搜索图像 1/2 你的图像,1/2,1/2,等等。然后你在一个小的 1/16 或任何大小的图像上开始模板匹配,并找到模板的大致位置。然后你对下一个图像尺寸做同样的事情,但你只搜索你的模板在前一个比例的位置的一个小子集。然后,每次您将图像尺寸增大到更接近原始尺寸时,您只需要寻找几个像素的微小差异来更准确地确定位置。首先使用最小缩放图像找到大致位置,与原始图像大小相比,它只需要一小部分时间即可找到,然后您只需通过放大来对其进行细化。


* 请注意,OpenCV 不包括您可能在其他地方看到的其他模板匹配方法。特别是,OpenCV 有平方差之和但没有绝对距离之和的方法。相位差也用作相似性度量,但在 OpenCV 中不存在。无论哪种方式,互相关和平方差之和在图像处理中都非常常见,除非您有特殊的图像域,否则应该可以正常工作。

于 2018-05-08T06:06:32.433 回答