赞
踩
在OpenCV中,模板匹配是一种图像处理技术,用于在一个大的图像中查找和定位一个小的目标图像(也称为模板)。
通俗而言,就是通过一张图片找到和另一张图片相似的部分。
从此章开始,opencv系列所有的之后更新的博客都会更注重实际应用,而不是仅仅简单讲解一个小方法是怎么应用的,会涉及到一些其他的方法,对于有些可能出现的代码看不懂的问题,我会放在文章的最后一节。
在模板匹配中,我们首先选定一个小的图像作为目标图像,然后在一个大的输入图像中滑动这个小的目标图像,从而寻找与其最相似的部分。具体实现时,可以使用多种算法来计算相似度,例如平方差和、相关系数、均方误差等等。
核心方法cv2.matchTemplate()是OpenCV中用于实现模板匹配的API函数。该函数可以在一张大图中查找一个小图像,并输出目标区域的位置。以下是cv2.matchTemplate()函数的详细讲解:
retval = cv2.matchTemplate(image, templ, method)
其中,cv2.TM_CCOEFF和cv2.TM_CCOEFF_NORMED表示相关系数匹配;cv2.TM_CCORR和cv2.TM_CCORR_NORMED表示相关性匹配;cv2.TM_SQDIFF和cv2.TM_SQDIFF_NORMED表示平方差匹配。有兴趣可以了解一下原理。
retval是一个矩阵,大小为(N-M+1, M-N+1),其中N和M分别为大图像和小图像的高和宽。矩阵中的每个元素表示原始图像中与模板匹配度的一个指标,匹配越好,则值越大。
此次图像匹配我们用的素材如下:
大图:

小图:

图像模板匹配就是在大图上找出小图的内容来。
- import cv2
-
- def cv_show(title,img):
- cv2.imshow(title,img)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
- return
-
- #读取两个图像
- template = cv2.imread('the_bird.png',0)#读取灰度图
- cv_show('img',template)#展示图象
- img = cv2.imread('bird.jpg',0)
- cv_show('img',img)
-
-
- # 获取小图像的高和宽
- h, w = template.shape[:2]
-
- #不同的方法模板匹配的方式不同
- methodology =[cv2.TM_CCOEFF,cv2.TM_CCOEFF_NORMED,cv2.TM_CCORR,cv2.TM_CCORR_NORMED,cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]
- # cv2.TM_CCOEFF:相关系数匹配。该方法计算输入图像和模板图像之间的相关系数,值越大表示匹配程度越好。
- # cv2.TM_CCOEFF_NORMED:标准归一化相关系数匹配。该方法计算输入图像和模板图像之间的标准归一化相关系数,也就是相关系数除以两个图像各自的标准差的乘积。值越大表示匹配程度越好。
- # cv2.TM_CCORR:相关性匹配。该方法计算输入图像和模板图像之间的相关性,值越大表示匹配程度越好。
- # cv2.TM_CCORR_NORMED:标准归一化相关性匹配。该方法计算输入图像和模板图像之间的标准归一化相关性,也就是相关性除以两个图像各自的标准差的乘积。值越大表示匹配程度越好。
- # cv2.TM_SQDIFF:平方差匹配。该方法计算输入图像和模板图像之间的平方差,值越小表示匹配程度越好。
- # cv2.TM_SQDIFF_NORMED:标准归一化平方差匹配。该方法计算输入图像和模板图像之间的标准归一化平方差,也就是平方差除以两个图像各自的标准差的乘积。值越小表示匹配程度越好。
-
- method = methodology[1]#选了一个cv2.TM_CCOEFF_NORMED方法进行图像匹配,匹配方式为比较模板和图像中各个区域的标准归一化相关系数
- res = cv2.matchTemplate(img, template, method)#比较完成的结果存储在res中,是一个ndarray类型的
-
- # 获取匹配结果中的最大值和最小值
- #通过左上角点的位置,加上之前获取的小图像的宽和高h,w,就可以把图像在原图中的那个位置框出来了
- min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)#最主要的是知道图像位置_loc
-
-
- #不同的匹配算法,计算匹配到的位置的方式不同
- if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
- top_left = min_loc
- else:
- top_left = max_loc
-
- #通过左上角点的坐标和h,w计算右下角点的坐标
- bottom_right = (top_left[0]+w, top_left[1]+h)#[0]为横坐标,[1]为纵坐标,横加宽纵加高就是右下角的点坐标
-
- #绘制矩形
- resoult_img = cv2.rectangle(img.copy(),top_left,bottom_right,255,1)
-
- cv_show('img',resoult_img)

读取两个图像:template表示要匹配的小图片,img表示需要在其中寻找小图片的大图片。
通过shape属性获取小图像的高h和宽w是几个像素点。
选择不同的方法模板匹配的方式,包括cv2.TM_CCOEFF、 cv2.TM_CCOEFF_NORMED、cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_SQDIFF、cv2.TM_SQDIFF_NORMED。不同的方法模板匹配比较的东西也不同。概述我在代码标注中写了。此次实验中,我们选取cv2.TM_CCOEFF_NORMED方法进行图像匹配。
调用cv2.matchTemplate()函数进行图像匹配,比较完成的结果存储在res中,是一个ndarray类型的。具体来说就是原图中每一块区域所有像素点的比较结果,都存储在这个矩阵里。
获取匹配结果中的最大值和最小值以及对应的位置信息。最大值就代表最优匹配
不同的匹配算法,计算匹配到的位置的方式不同。如果是平方差匹配,则选取最小值点作为匹配结果;否则选取最大值点。匹配结果的坐标就是最优匹配的左上角的坐标。通过左上角点的位置,加上之前获取的小图像的宽和高h,w,就可以把图像在原图中的那个位置框出来了。
通过左上角点的坐标和h,w计算右下角点的坐标。
计算完右下角的点坐标之后,我们就有了左上角和右下角点的坐标。通过cv2.rectangle()方法再原图中将匹配的区域画出来。
先用cv_show方法展示了模板图像,此时咱们读取的是灰度图所以是灰色的。

按任意键继续,展示了需要进行样板匹配的图像:

按任意键继续后,展示的图像是用矩形框将匹配的区域框选出来的图像

上面的代码就是一个简单的图像匹配的具体流程。而再实际应用中,我们可能会面临一个情况就是我的图像中有多个区域(或者说对象)和模板匹配。那么此时我们就不是用
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
这行代码去进行找res对象中最佳的匹配了,而是设置一个阈值,找出相似程度超过阈值的区域。
此次我们示例图像如下:我用画图软件画的

样板如下:

- import cv2
- import numpy as np
-
- def cv_show(title,img):
- cv2.imshow(title,img)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
- return
-
- #读取两个图像
- template = cv2.imread('target.png',0)#读取灰度图目标
- img = cv2.imread('targets.png')
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
-
-
- # 获取小图像的高和宽
- h, w = template.shape[:2]
- method = cv2.TM_CCOEFF_NORMED
-
- #进行匹配,匹配结果存放在res中
- res = cv2.matchTemplate(gray, template, method)
-
- #与之前直接读取最大最小值不同,此次我们需要的是res中多个目标的结果,所以在此设置一个阈值
- threshold = 0.8
- loc = np.where(res >= threshold)#阈值为0.8,即取百分之80匹配的
- for loc in zip(*loc[::-1]):
- bottom_right = (loc[0]+w, loc[1]+h)
- cv2.rectangle(img,loc, bottom_right, 255, 2 )
-
- cv_show('resoult',img)
-


有什么问题可以在评论区讨论哈哈哈
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。