一、学习目标
- 了解图片内容定位方法matchTemplate使用
- 了解minMaxLoc方法使用
上一篇《[python opencv 计算机视觉零基础到实战] 十、图片效果毛玻璃》
如有错误欢迎指出~
二、了解从一张图片中找到指定内容的方法
2.1 使用matchTemplate函数对图片中的指定内容进行查找
有小伙伴可能用过一些辅助软件,帮助我们从一些游戏中找到固定像素,并且去对该像素位置进行点击,随后解放双手。今天这一节所讲解的就是与这个功能相关的内容,对图像中的指定图形元素进行查找,并且选中该元素。
我们所使用的方法是matchTemplate。matchTemplate主要是一种匹配方法,通过判断物体在一张图片中的什么位置,从而进行定位,如下图所示:
matchTemplate将会在对像素点进行匹配,匹配相似度越大,则确定该位置为目标。这个方法有一定局限性,在原图中若目标图片发生了旋转等变化,那么将会查找失败。
matchTemplate有几种匹配算法,分别是TM_SQDIFF平方差匹配、TM_CCORR相关性匹配以及TM_CCOEFF相关性系数匹配。TM_SQDIFF平方差匹配是平方差匹配,最佳匹配值为0,若不佳则匹配值会越大;TM_CCORR是由原图和目标图像做乘法,值越高匹配越佳,反之越差,0为最差;TM_CCOEFF是将模版对其均值相对值与图像对其均值相关值进行匹配,最佳匹配为1,0表示完全匹配不到,-1则表示有匹配,但是精确度不高。以上内容了解即可,对于初学者来说就知道就行,不理解也不妨碍我们现阶段使用该API进行开发。
matchTemplate函数原型为:
matchTemplate(img, tpl, method[, result[, mask]])
matchTemplate中参数img为目标图像,tpl为原图,method是所使用的匹配算法,result是匹配结果图像。
我们首先引入所需库:
import cv2
import numpy as nptarget = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
tpl = cv2.imread(r'C:\Users\mx\Desktop\1target.png')
以上代码中引入了目标图片target与原图tpl。随后我们使用TM_SQDIFF_NORMED匹配方法对图像进行匹配。
接下来获取目标图片的宽高:
th, tw = tpl.shape[:2]
目标图片如下:
随后传入参数至matchTemplate方法中:
result = cv2.matchTemplate(target, tpl, cv2.TM_SQDIFF_NORMED)
接下来我们需要使用一个方法minMaxLoc。minMaxLoc方法是在一个矩阵中寻找最大值和最小值,并且得到最大值最小值的索引。若有一个矩阵为[[1,2,3,4],[5,11,7,8]],名为a,传入到 方法后,代码如下:
min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(a)
print(min_val,max_val,min_loc,max_loc)
最终结果将是:
1.0 11.0 (0, 0) (1, 1)
我们接下来使用minMaxLoc获取matchTemplate算出来的计算结果,由于我们使用的方法是TM_SQDIFF_NORMED,那么将获取最低值进行目标获取。代码如下:
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
tl = min_loc
接下来我们使用rectangle对所需要的部分进行绘图。rectangle接收五个参数,分别是image图片、start_point起始坐标、end_point结束坐标、color颜色、thickness线条粗细。我们就常规使用前4个参数就ok了。
接下来我们使用最小的坐标加上目标图片的宽高就可以知道绘制区域了:
br = (tl[0] + tw, tl[1] + th)
最终完整的代码如下:
import cv2
import numpy as nptarget = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
tpl = cv2.imread(r'C:\Users\mx\Desktop\1target.png')
th, tw = tpl.shape[:2]result = cv2.matchTemplate(target, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
tl = min_loc
br = (tl[0] + tw, tl[1] + th)
cv2.rectangle(target, tl, br, [0, 255, 0])
cv2.imshow("target", target)cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下:
2.2 深入了解matchTemplate函数
matchTemplate函数的查找方式我们可以通过matchTemplate函数所返回的结果进行查看,修改代码如下:
import cv2
import numpy as nptarget = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
tpl = cv2.imread(r'C:\Users\mx\Desktop\1target.png')
methods = [cv2.TM_SQDIFF_NORMED, cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF_NORMED]
th, tw = tpl.shape[:2]result = cv2.matchTemplate(target, tpl, cv2.TM_SQDIFF_NORMED)cv2.imshow("result", result)cv2.waitKey(0)
cv2.destroyAllWindows()
我们以上代码直接显示了result结果,由于为了演示效果,最理想状态是扣选出来的图片,所以我使用了原图进行目标图像的选取。
tpl=target[200:400,280:450]
并且使用了methods列表存储了匹配方法TM_SQDIFF_NORMED、TM_CCORR_NORMED、TM_CCOEFF_NORMED。之后使用了遍历依次使用这些方法对目标图片进行匹配。但是由于不同的方法高地值表示不懂的匹配效果,在此使用了if语句判断不同的方法取不同的高低值:
if md == cv2.TM_SQDIFF_NORMED:tl = min_locelse:tl = max_loc
修改了目标图,为了有更好的对比,目标图如下:
结果如下:
以上我展示了一种方法的结果图,其它方法由于我选择的目标图有太多相似的区域,所以这张图是一种较为理想的想过。可以看到在黄色箭头选择的区域有明显的高亮位置,该位置则是我们进行目标匹配后的结果位置。其实在进行匹配时,这个过程就类似于是卷积。
该系列文章首发于ebaina
三、总结
- 目标匹配方法matchTemplate的使用方法
- 了解了matchTemplate方法有3中匹配方式,依次是TM_SQDIFF_NORMED、TM_CCORR_NORMED、TM_CCOEFF_NORMED
- 了解了不同匹配方法之间高低值有不同的依据结果