《三英战吕布》- 图像模板匹配【Python_Open_CV系列(八)】
文章目录
ʚʕ̯•͡˔•̯᷅ʔɞ
🍹欢迎各路大佬来到小啾主页指点☀️欢迎大家前来学习《三英战吕布》 - 图像模板匹配Python-Open_CV系列博文第八篇,我是博主侯小啾。
✨我的博客主页:云雀编程小窝 🌹꧔ꦿ
🌹꧔ꦿ博文内容如对您有所帮助,还请给个点赞 + 关注 + 收藏✨
🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ
🌹꧔ꦿ上期传送门:
✨OpenCV图像处理基本操作 【Python-Open_CV系列(一)】
✨OpenCV像素处理基本操作 【Python-Open_CV系列(二)】
✨OpenCV之 BGR、GRAY、HSV色彩空间&色彩通道专题 【Python-Open_CV系列(三)】
✨OpenCV绘制图像与文字(可作为脚手架代码)(python) 【Python-Open_CV系列(四)】
✨OpenCV图像几何变换专题(缩放、翻转、仿射变换及透视)【python-Open_CV系列(五)】
✨基于梵·高《向日葵》的 图像阈值处理专题(二值处理、反二值处理、截断处理、自适应处理及Otsu方法)【Python-Open_CV系列(六)】
✨OpenCV基本功 之 图像的掩模、运算 & 合并专题 -小啾带学【Python-Open_CV系列(七)】
如有疑问欢迎随时在评论区交流。☀️
1.什么是模板匹配? 及 模板匹配方法matchTemplate()
介绍
提供一个模板图像,一个目标图像,且满足模板图像是目标图像的一部分,从目标图像中寻找特定的模板图像的过程,即为模板匹配。OpenCV提供了matchTemplate()方法帮助我们实现模板匹配。
该方法语法如下:
cv2.matchTemplate(image, templ, method, result=None, mask=None)
其中
- image 即目标图像
- templ 即模板图像
- method 是匹配的方式
- mask 即掩模,可选。只有当method为cv2.TM_SQDIFF或cv2.TM_CCORR_NORMED时才支持此参数。
method参数可以是以下值:
参数值描述cv2.TM_SQDIFF差值平方和匹配,也称平方差匹配。可以理解为是基于差异程度的匹配,差异程度越小,匹配程度越高。完全匹配时值差值平方和为0。cv2.TM_SQDIFF_NORMED相关匹配。 可以理解为是基于相似程度的匹配,相似程度越高,计算结果越大,匹配程度就越高。cv2.TM_CCORR标准相关匹配。 规则同上。cv2.TM_CCORR_NORMED相关系数匹配cv2.TM_CCOEFF相关系数匹配。也是基于相似程度的匹配,计算结果是一个-1到1的浮点数,1表示完全匹配,0表示毫无关系,-1表示两张图片亮度刚好相反。cv2.TM_CCOEFF_NORMED标准相关系数匹配,规则同上。
使用matchTemplate()方法,模板会将图像中的每一块区域都覆盖一遍,并每次都使用所选的method方法进行计算,每次的计算结果最后以一个二维数组的形式返回给我们。
素材准备
为方便展示,特准备以下图片素材:
选择世界名画《三英战吕布》(test.png),图像shape为(738, 675, 3):
从中抠出一部分图像元素作为下边要用的模板素材。取材代码如下( 不建议截图,截图抠出来的不一定能保证尺寸):
import cv2
img = cv2.imread("test.png")print(img.shape)# 电灯
img1 = img[20:220,320:480,:]# 虎牢关牌匾
img2 = img[75:150,200:310,:]# 青龙刀
img3 = img[170:530,575:650,:]# 关云长
img4 = img[270:670,160:330,:]
cv2.imshow("img0", img)
cv2.imshow("img1", img1)
cv2.imshow("img2", img2)
cv2.imshow("img3", img3)
cv2.imshow("img4", img4)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('template_pic1.jpg', img1)
cv2.imwrite('template_pic2.jpg', img2)
cv2.imwrite('template_pic3.jpg', img3)
cv2.imwrite('template_pic4.jpg', img4)
取出的模板素材如下:
======================
电 灯
======================
虎牢关牌匾
======================
青龙刀
======================
关云长
======================
2.单模板匹配
单模板匹配,即在匹配时中只使用到一个模板的匹配过程。具体又可以分为单目标匹配和多目标匹配。
2.1 单目标匹配
单目标匹配,即模板在目标图像中只匹配 匹配程度最高的一个匹配结果。
这需要找出这一次匹配结果所在位置的坐标来确定其位置,OpenCV提供了cv2.minMAXLoc()来实现。
该方法参数为matchTemplate()的返回值,会返回一个元组,元组中有四个值,分别是最小值、最大值、最小值时图像左上角顶点坐标,最大值时图像左上角顶点坐标。
接下来,使用 电灯(template_pic1) 图片来匹配原图,并用红色的矩形在原图像中圈出模板图像,使用标准差值平方和的匹配方式,代码如下:
import cv2
img = cv2.imread("test.png")
templ = cv2.imread("template_pic1.jpg")
height, width, c = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED)# 获取匹配结果中的最小值、最大值、最小值坐标和最大值坐标
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results)
resultPoint1 = minLoc
resultPoint2 =(resultPoint1[0]+ width, resultPoint1[1]+ height)
cv2.rectangle(img, resultPoint1, resultPoint2,(0,0,255),2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
如图所示,成功标出了模板图。
如果要从多幅图像中,找出与模板最匹配的结果,
以标准差值平方和的匹配方式为例,
则可以对这些图像进行遍历,并比较每幅图像对应结果中的最小值,找出最小值中的最小值,则为最佳匹配项。以两幅图像为例,将原图翻转一次,生成一张新的图像(翻转后结果与原图较像,但差异巨大)
翻转产生素材(test1.png)
import cv2
img = cv2.imread("test.png")
dst1 = cv2.flip(img,1)
cv2.imshow("dst1", dst1)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('test1.png', dst1)
然后使用模板 关云长 (template_pic4.jpg)对两幅图像进行匹配,输出最佳匹配结果,并画红框展示:
import cv2
image =[]
image.append(cv2.imread("test.png"))
image.append(cv2.imread("test1.png"))
templ = cv2.imread("template_pic4.jpg")
height, width, c = templ.shape
# 循环变量初始化# 这里只是随便设定一个值,该值并无意义,只是为了定义该变量# 使用TM_SQDIFF_NORMED计算方法,计算出的结果通常是小于1的,所以minValue可以设置为1。如果是TM_SQDIFF计算方法,则就不行了,计算出来的值会很大。代码就不再有效,需要把minMax设得更大,或者做其他修改。
index =-1
minValue =1
minLoc1 =(0,0)# 遍历每幅图像for i inrange(0,len(image)):
results = cv2.matchTemplate(image[i], templ, cv2.TM_SQDIFF_NORMED)min= cv2.minMaxLoc(results)[0]ifmin< minValue:
minValue =min
minLoc1 = cv2.minMaxLoc(results)[2]
index = i
minLoc2 =(minLoc1[0]+ width, minLoc1[1]+ height)
cv2.rectangle(image[index], minLoc1, minLoc2,(0,0,255),2)
cv2.imshow("result", image[index])
cv2.waitKey()
cv2.destroyAllWindows()
如图,test.png中的关云长与模板更为匹配。
__
2.2 多目标匹配
多目标匹配,即在目标图像中匹配出所有与模板图像匹配的结果。可以使用相关匹配或相关系数匹配。
素材准备
还以原图像"test.png"为参照,
为了产生方便我们做示例的图像,我们在该图像的基础上多加一盏电灯,生成"test2.png"
import cv2
img = cv2.imread("test.png")
templ = cv2.imread("template_pic1.jpg")
img[20:220,30:190,:]= templ
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('test2.png', img)
多目标匹配
多目标匹配即对matchTemplate()匹配的总的结果,的计算情况数据,使用for循环遍历,并设定一个判断标准。
如使用标准相关系数(cv2.TM_CCOEFF_NORMED)的方法判断,如:如果计算值大于0.99,则我们认为匹配成功了。
使用电灯模板"template_pic1.jpg",匹配图像test2.png。并对匹配的结果用红色的矩形框标记。
代码示例如下:
import cv2
img = cv2.imread("test2.png")
templ = cv2.imread("template_pic1.jpg")
height, width, c = templ.shape
# 按照标准相关系数匹配
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)for y inrange(len(results)):for x inrange(len(results[y])):if results[y][x]>0.99:
cv2.rectangle(img,(x, y),(x + width, y + height),(0,0,255),2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
程序执行结果如下,成功匹配出了两盏灯。
3.多模板匹配
多模板匹配,即进行了n次单模板的匹配过程。
直接上示例:
在test.png中匹配电灯、青龙刀、虎牢关牌匾、关云长四个图像模板:
import cv2
defmyMatchTemplate(img, templ):
height, width, c = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
loc =list()for i inrange(len(results)):for j inrange(len(results[i])):if results[i][j]>0.99:
loc.append((j, i, j + width, i + height))return loc
# 读取原始图像
img = cv2.imread("test.png")# 模板列表
templs =list()
templs.append(cv2.imread("template_pic1.jpg"))
templs.append(cv2.imread("template_pic2.jpg"))
templs.append(cv2.imread("template_pic3.jpg"))
templs.append(cv2.imread("template_pic4.jpg"))
loc =list()for t in templs:
loc += myMatchTemplate(img, t)# 遍历所有红框的坐标for i in loc:
cv2.rectangle(img,(i[0], i[1]),(i[2], i[3]),(0,0,255),2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
匹配效果如下:
本次分享就到这里,更多精彩内容敬请期待!小啾感谢您的支持。
🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ
版权归原作者 侯小啾 所有, 如有侵权,请联系我们删除。