Py OpenCV——模板匹配

模板匹配和积卷原理很想。模板在原图像上从原点(从左到右,从上到下)计算模板与图像被模板覆盖的地方(模板这个核在原图上对比的核)的差别程度
这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出
假如原图像是AxB大小 则输出结果的矩阵为(A-a+1)x(B-b+1)

TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
TM_CCORR:计算相关性,计算出来的值越大,越相关
TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关。
TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关。
TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关。

import cv2
import numpy as np
import matplotlib.pyplot as plt


def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyWindow("all")


# 转灰度图 原始图像
img = cv2.imread("Lena.jpg", 0)
# 0是转灰度 模板图像 要在原始图像中对比
template = cv2.imread("Face.jpg", 0)
#template = cv2.imread("1.jpg", 0)
# 获得模板的宽和高
h, w = template.shape[:2]
print("h:",h,"w:",w)

#shape值
print(img.shape)
print(template.shape)

# 进行模板匹配 方式尽量使用归一化的 也就是上面我写的后三个方法 参数(原始图,模板图,方法)返回:res 返回的是每个窗口得到的结果值(矩阵大小)  == 假如原图像是AxB大小 则输出结果的矩阵为(A-a+1)x(B-b+1)
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
print(res.shape)

# 进行定位 返回最小值 最大值 最小值位置(矩阵的左上角) 最大值位置()
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val)
print(max_val)
print(min_loc)
print(max_loc)

"""

展示六种效果

"""
# 创建列表存放六种方法 因为方法不用字符串所以一会要进行取值 再传参
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
           'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

#遍历列表
for meth in methods:
    #图像拷贝
    img2 = img.copy()

    #匹配方法的真值 因为cv2.TM_SQDIFF...等方法可以用值1....来代替 所以用eavl执行之和返回一个值传进去
    method = eval(meth)
    print(method)
    #模板匹配
    res = cv2.matchTemplate(img,template,method)
    #获取最小值最大值已经最小值坐标以及最大值坐标
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    #如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED取最小值 (判断如果是取小值的就取小值如果是取大值的就取大值)
    if method in[cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
        #矩形左上角坐标
        top_left = min_loc
    else:
        #应该是右下角叭
        top_left = max_loc

    #获得位置 wh代表宽高 这里应该获取的结束坐标 top_left[0]top_left[1] 是取出最小值的xy再加上宽和高
    #(这里写的获取位置没有错 如果 我知道了初始 知道了宽高 那么 我得到的就是一个框 也就是位置 得到位置下面再画出矩阵结束)
    bottom_right = (top_left[0]+w,top_left[1]+h)

    #画矩阵 参数(图像,开始坐标,结束坐标,颜色,粗细)
    cv2.rectangle(img2,top_left,bottom_right,255,2)

    #打印当前的结果(矩形(res 每个窗口的结果值 其中亮光的地方 是最接近人脸框的位置))
    plt.subplot(121),plt.imshow(res,cmap="gray")
    #隐藏坐标轴
    plt.xticks([]),plt.yticks([])
    #打印当前结果(框)
    plt.subplot(122),plt.imshow(img2,cmap="gray")
    plt.xticks([]),plt.yticks([])
    plt.suptitle(meth)
    plt.show()


"""

(模板)匹配多个对象

"""

img_rgb = cv2.imread("Mario.jpg")
#转灰度图
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread("Mario_coin.jpg",0)
h,w = template.shape[:2]

#模板匹配
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
#设置阈值
threshold = 0.8
#取匹配程度大于80%的坐标(用于判断每个窗口的结果大于阈值threshold)
loc = np.where(res>=threshold)
#画出所有的loc 也就大于阈值threshold的模板 *号表示可选参数
for pt in zip(*loc[::-1]):
    #获取每个对象的位置
    bottom_righ = (pt[0]+w,pt[1]+h)
    #画矩阵
    cv2.rectangle(img_rgb,pt,bottom_righ,(0,0,255),2)
cv2.imshow("img_rgb",img_rgb)
cv2.waitKey(0)
cv2.destroyWindow("all")

整理下:
1.先获取图片 模板
2.获取模板的宽高
3.进行模板匹配cv2.matchTemplate()
4.获取最小最大值和最小最大坐标用于计算结束位置 初始位置是最小坐标
5.获得位置(bottom_right = (top_left[0]+w,top_left[1]+h)) 最小值[0](最小坐标的x)+宽 最小值[1](最小坐标的y)+高
6.画出矩阵cv2.rectangle(img2,top_left,bottom_right,255,2) 参数:图片,开始坐标,结束坐标,颜色,粗细
7.输出图像


你可能感兴趣的:(python,opencv)