前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实例应用(二):使用Python和OpenCV进行多尺度模板匹配

实例应用(二):使用Python和OpenCV进行多尺度模板匹配

作者头像
Color Space
发布2020-01-13 15:35:08
5.6K0
发布2020-01-13 15:35:08
举报

原文地址:https://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv/

作者:Adrian Rosebrock

使用Python和OpenCV进行多尺度模板匹配

作者: Adrian Rosebrock 于 2015 年1月26日在 图像处理,教程

过去的这个周末,我感到非常不舒服。除了躺在沙发上,从一个咖啡杯里啜一口鸡汤面,和使命召唤马拉松游戏,我还没有做太多的事情。

它确实一直是 几年,因为我已经花了一个周末无情玩使命召唤。上网和玩无尽的团队死亡竞赛和统治带回了我的大学室友和我自己的游戏整个晚上我的大学年的一些伟大的回忆。

认真的说,回到大学我是一个狂热的使命召唤 - 我甚至有挂在墙上的使命召唤海报。我曾经玩过所有的游戏:第二次世界大战期间制作的“使命召唤”游戏; 现代战争系列(我最喜欢的); 甚至是黑色行动游戏。虽然这周末我太生病了,不能把自己从沙发上拖下来,但是我不能在没有问题的情况下通过一个统治游戏。

但在周日下午结束的时候,我的博彩环节开始感觉有点不适应了。显然,现在我只有一次有限的游戏,现在我不再上大学了。

无论如何,我伸手到我的笔记本电脑,开始网上冲浪。在浏览Facebook几分钟后,我遇到了一个我在Machine Learning Mastery 上完成的模板匹配教程。在这篇文章中,我详细地介绍了如何玩 Waldo在哪里?(或者 哪里是沃利?,为国际读者)使用计算机视觉。

尽管本教程非常有趣(虽然非常具有介绍性),但是我意识到有一个简单的扩展可以使模板匹配更健壮,需要进行覆盖。

你会发现,有些时候使用关键点检测器,局部不变描述符(如SIFT,SURF,FREAK等),以及与RANSAC或LMEDs的关键点匹配只是矫枉过正 - 而且最好采用更简单的方法。

在这篇博文中,我将详细介绍如何将模板匹配扩展为 多尺度,并处理模板和输入图像尺寸不一样的图像。

OpenCV和Python版本: 这个例子将在 Python 2.7 / Python 3.4+OpenCV 2.4.X上运行

使用Python和OpenCV进行多尺度模板匹配

要开始本教程,首先要了解为什么使用cv2进行模板匹配的标准方法 。matchTemplate 不是很健壮。

看看下面的示例图片:

图1:模板匹配无法工作时,模板图像的大小(左)不将图像中的区域的大小相匹配(右)

在上面的示例图片中,左侧是“使命召唤”标志 在右侧,我们有我们想要检测使命召唤标志的图像。

注意: 模板和输入图像在边缘图表示上都是匹配的。在尝试使用两个图像的边缘图来查找模板之后,右侧的图像仅仅是操作的输出。

但是,当我们尝试使用cv2来应用模板匹配时 。matchTemplate 功能,我们留下了一个虚假的比赛-这是因为在标志图像的大小 左边小得多 比责任标志上的游戏封面通话

鉴于“使命召唤”模板的尺寸与游戏封面上的“使命召唤”标识的尺寸不符,我们将留下错误的检测结果。

所以我们现在怎么办?

放弃?开始检测关键点?提取局部不变描述符?并应用关键点匹配?

没那么快

在检测关键点时,提取局部不变描述符和匹配关键点 肯定会起作用,这对于这个问题来说 绝对是矫枉过正的。

事实上,我们可以通过更简单的解决方案来获得更多的代码。

cv2.matchTemplate技巧

所以正如我在本文开头所暗示的那样,仅仅是因为你的模板的尺寸与你要匹配的图像中的区域的尺寸匹配, 并不 意味着你不能应用模板匹配。

在这种情况下,你所需要做的就是应用一个小技巧:

  1. 以多种比例循环输入图像(即使输入图像逐渐变小和变小)。
  2. 使用cv2应用模板匹配 。匹配模板 并跟踪最大相关系数的匹配(以及具有最大相关系数的区域的 x,y坐标)。
  3. 遍历所有尺度后,取相关系数最大的区域作为“匹配”区域。

正如我所说的,这个技巧很简单 - 但在某些情况下,这种方法可以避免编写大量额外的代码,并处理更多奇妙的技术来匹配图像中的对象。

注意: 根据定义,模板匹配是平移不变的。我们现在提出的扩展可以帮助扩展(即大小)的变化。但是, 如果您试图匹配旋转的对象或呈现非仿射变换的对象,则 模板匹配并不理想。如果您对这些类型的转换感到担忧,您最好直接跳到关键点匹配。

无论如何,谈话还是够的。让我们跳到一些代码。打开你最喜欢的编辑器,创建一个新的文件,命名它 匹配。py ,让我们开始吧:

Multi-scale Template Matching using Python and OpenCV

Python

12345678910111213141516171819202122

# import the necessary packagesimport numpy as npimport argparseimport imutilsimport globimport cv2 # construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-t", "--template", required=True, help="Path to template image")ap.add_argument("-i", "--images", required=True, help="Path to images where template will be matched")ap.add_argument("-v", "--visualize", help="Flag indicating whether or not to visualize each iteration")args = vars(ap.parse_args()) # load the image image, convert it to grayscale, and detect edgestemplate = cv2.imread(args["template"])template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)template = cv2.Canny(template, 50, 200)(tH, tW) = template.shape[:2]cv2.imshow("Template", template)

我们要做的第一件事就是导入我们需要的包。我们将使用NumPy进行数值处理, argparse 解析命令行参数, 一些图像处理便利函数的imutils(包含在本文的代码的.zip中),glob 用于获取输入图像的路径, cv2 for我们的OpenCV绑定。

然后我们解析8-15行的观点 。我们将需要三个开关: - 模板 ,这是我们想要在图像中匹配的模板的路径(即使命召唤标志), - 图像 ,目录的路径,包括包含呼叫的图像我们要找到值班的标志,以及一个可选的 - 形象化 的说法,它可以让我们直观跨越多尺度模板匹配搜索。

接下来,是时候把我们的模板加载到第18行的磁盘上 。我们也会将它转换成第19行的灰度, 并检测第20行的边缘 。正如您将在本文后面看到的那样,使用 边缘 而不是 原始图像进行模板匹配,可以大大提高模板匹配的准确性。

其原因是因为“使命召唤”的标识是 严格的并且有明确的定义 - 正如我们稍后会在这篇文章中看到的那样,它允许我们放弃标识的颜色和样式,而仅仅关注轮廓。这样做给了我们稍微更强大的方法,否则我们不会有。

无论如何,应用边缘检测后,我们的模板应该是这样的:

图2:从模板图像中提取边缘。

现在,我们来研究一下多尺度的技巧:

Multi-scale Template Matching using Python and OpenCV

Python

24252627282930313233343536373839404142

# loop over the images to find the template infor imagePath in glob.glob(args["images"] + "/*.jpg"): # load the image, convert it to grayscale, and initialize the # bookkeeping variable to keep track of the matched region image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) found = None # loop over the scales of the image for scale in np.linspace(0.2, 1.0, 20)[::-1]: # resize the image according to the scale, and keep track # of the ratio of the resizing resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) r = gray.shape[1] / float(resized.shape[1]) # if the resized image is smaller than the template, then break # from the loop if resized.shape[0] < tH or resized.shape[1] < tW: break

我们开始循环播放第25行的输入图像。然后,我们加载图像关盘,将其转换为灰度,并初始化变量簿记 发现 跟踪图像的区域和规模与最佳匹配。

从那里,我们开始使用 np在第33行上循环显示图像的多个比例。linspace 函数。这个函数接受三个参数,起始值,结束值,以及相等的块片数。在这个例子中,我们将从图像的原始大小的100%开始,并以20个相同大小的百分比块的方式降低到原始大小的20%。

然后,我们根据当前调整图像大小图像 的规模 在36号线和计算旧的宽度比新的宽度-稍后你会看到,但重要的是我们跟踪这个比例的。

第41行,我们进行检查,以确保输入图像大于我们的模板匹配。如果模板较大,那么我们的cv2 。matchTemplate 调用会抛出一个错误,所以如果是这样的话,我们只是从循环中断开。

在这一点上,我们可以将模板匹配应用于调整后的图像:

Multi-scale Template Matching using Python and OpenCV

Python

444546474849505152535455565758596061626364656667686970717273

# detect edges in the resized, grayscale image and apply template # matching to find the template in the image edged = cv2.Canny(resized, 50, 200) result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) # check to see if the iteration should be visualized if args.get("visualize", False): # draw a bounding box around the detected region clone = np.dstack([edged, edged, edged]) cv2.rectangle(clone, (maxLoc[0], maxLoc[1]), (maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2) cv2.imshow("Visualize", clone) cv2.waitKey(0) # if we have found a new maximum correlation value, then ipdate # the bookkeeping variable if found is None or maxVal > found[0]: found = (maxVal, maxLoc, r) # unpack the bookkeeping varaible and compute the (x, y) coordinates # of the bounding box based on the resized ratio (_, maxLoc, r) = found (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) # draw a bounding box around the detected result and display the image cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) cv2.imshow("Image", image) cv2.waitKey(0)在第46行,我们使用与模板图像完全相同的参数计算图像的Canny边缘表示。然后,我们使用cv2应用模板匹配 。matchTemplate 的47号线。该 CV2 。matchTemplate 函数有三个参数:输入图像,我们希望在输入图像中找到的模板以及模板匹配方法。在这种情况下,我们提供 cv2 。TM_CCOEFF 标志,表示我们正在使用相关系数来匹配模板。CV2 。minMaxLoc 上功能48线将我们的相关结果,并返回一个4元组,其包括最小相关值,最大相关值时,(X,Y)的最小值-协调,和 (X,Y) -协调的最大值,分别。我们只关心最大值和 (x,y)坐标,所以我们保持最大值并舍弃最小值。第51-57行处理可视化多尺度模板匹配。这允许我们检查在每次迭代时匹配的图像区域。

从那里,我们更新簿记可变 发现 上 线61和62来跟踪迄今所发现的最大相关值的 (X,Y)的最大值-协调,与原始图像宽度与比沿当前,调整图像宽度。

在这一刻,所有的辛苦工作都完成了。

在我们遍历完所有图像的尺度之后,我们将第66行的簿记变量打开 ,然后计算第67行和第68行的边界框的起始和结束 坐标(x,y)坐标 。需要特别注意的是将边界框的坐标乘以第37行上的比值, 以确保坐标与输入图像的原始尺寸相匹配。

最后,我们绘制边界框并将其显示在71-73行的屏幕上 。

多尺度模板匹配结果

不要拿我的话来说,这种方法的作品!我们来看一些例子。

打开您的终端并执行以下命令:

Multi-scale Template Matching using Python and OpenCV

Shell

1

$ python match.py --template cod_logo.png --images images

你的结果应该是这样的:

图3:成功应用多尺度模板匹配在图像中查找模板。

正如您所看到的,我们的方法成功地找到了“使命召唤”标识,与图1中未能找到标识的基本模板匹配不同。

图4:使用多尺度模板匹配的另一个成功匹配。注意这个图像和图3中的徽标有多不同。

然后,我们将多尺度模板匹配应用于另一个“使命召唤”游戏封面 - 尽管模板比输入图像小得多,我们又找到了“使命召唤”标识。

另外,请仔细检查“使命召唤”徽标的样式和颜色在图3图4中有何不同。如果我们使用RGB或灰度模板,我们将无法在输入图像中找到这些标志。但是通过将模板匹配应用于 边缘图表示而不是原始的RGB或灰度表示,我们能够获得稍微更稳健的结果。

让我们尝试另一个图像:

图5:多尺度模板匹配再一次能够在输入图像(右)中找到徽标(左)

再次,我们的方法能够找到输入图像中的标志!

下面的图6也是如此:

图6:更多的与OpenCV和Python的多尺度模板匹配。请注意,“使命召唤4”中的“4”不包括在比赛中。

现在我最喜欢的使命召唤,现代战争3:

图7:使用cv2.matchTemplate进行多尺度模板匹配

再一次,我们的多尺度方法能够在输入图像中成功找到模板!

更令人印象深刻的是,上面的MW3游戏封面上有很大的噪音 - 封面的艺术家使用白色空间来形成“Y”的右上角,而左下角“C”,因此在那里不会检测到边缘。不过,我们的方法能够在图像中找到标识。

可视化匹配

在上面的部分,我们看了比赛的输出。但是让我们花一点时间来深入了解一下这个算法是如何工作的。

打开您的终端并执行以下命令:

Multi-scale Template Matching using Python and OpenCV

Shell

1

$ python match.py --template cod_logo.png --images images --visualize 1

您将看到类似以下的动画:

在每次迭代中,我们的图像被调整大小,并计算Canny边缘图。

然后我们应用模板匹配,找到 相关系数最大的图像(x,y)坐标。

最后,我们将这些值存储在簿记变量中。

在算法结束时,我们找到所有尺度上相关系数响应最大的区域的 (x,y)坐标,然后画出我们的边界框,如下所示:

图9:我们的多尺度模板匹配的输出。

为了完整起见,下面是使用OpenCV和Python可视化我们的多尺度模板匹配的另一个例子:

图10:可视化多尺度模板匹配的第二个例子。

限制和缺点

当然,应用简单的模板匹配,即使是多尺度模板匹配也有一些明显的局限性和缺陷。

虽然我们可以处理翻译和缩放的变化,但是我们的方法对于旋转或非仿射变换的变化将不够稳健。

如果我们担心在非仿射变换上旋转,我们最好花时间来检测关键点,提取局部不变描述符,并应用关键点匹配。

但是,在我们的模板(1)通过边缘映射具有相当的刚性和良好定义的情况下,以及(2)我们只关心翻译和缩放的情况下,多尺度模板匹配可以给我们提供很好的结果, 。

最后,请记住,模板匹配不能很好地告诉我们一个对象 是否出现在图像中。当然,我们可以设定相关系数的门槛,但实际上这是不可靠的和强大的。如果你正在寻找一个更强大的方法,你将不得不探索关键点匹配。

概要

在这篇博客文章中,我们发现了如何通过扩展它一起工作的标准模板匹配更强大的 多尺度

我们还发现,如果我们的模板图像是刚性和格式良好的,那么在应用模板匹配时,利用边缘图而不是RGB或灰度表示可以产生更好的结果。

如果我们只关心翻译和缩放,那么我们的多尺度模板匹配方法就行得通; 然而,这种方法在旋转和非仿射变换的情况下不会那么健壮。如果我们的模板或输入图像展示了这些类型的转换,我们最好使用关键点检测,局部不变描述符和关键点匹配。

关注【OpenCV学习交流】

长按或者扫描下面二维码即可关注

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Python和OpenCV进行多尺度模板匹配
  • 使用Python和OpenCV进行多尺度模板匹配
  • cv2.matchTemplate技巧
  • 多尺度模板匹配结果
  • 可视化匹配
  • 限制和缺点
  • 概要
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档