• OpenCV-Python:模板匹配


    啥叫模板匹配

    模板匹配就是在大图中找小图,也就说在一幅图像中寻找另一幅模板图像的位置:

    OpenCV使用 cv2.matchTemplate() 实现模板匹配。

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    img = cv2.imread('lena.jpg', 0)
    template = cv2.imread('face.jpg', 0)
    h, w = template.shape[:2]    # rows->h, cols->w

    匹配函数返回的是一幅灰度图,最白的地方表示最大的匹配。使用 cv2.minMaxLoc() 函数可以得到最大匹配值的坐标,以这个点为左上角角点,模板的宽和高画矩形就是匹配的位置了:

    # 相关系数匹配方法: cv2.TM_CCOEFF
    res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
    left_top = max_loc   # 左上角
    right_bottom = (left_top[0] + w, left_top[1] + h)   # 右下角
    cv2.rectangle(img, left_top, right_bottom, 255, 2)  # 画出矩形位置
    
    plt.subplot(121), plt.imshow(res, cmap='gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    
    plt.subplot(122), plt.imshow(img, cmap='gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.show()

    模板匹配的原理 

    模板匹配的原理其实很简单,就是不断地在原图中移动模板图像去比较,有6种不同的比较方法,详细请参考:TemplateMatchModes

    • 平方差匹配 CV_TM_SQDIFF:用两者的平方差来匹配
    • 归一化平方差匹配 CV_TM_SQDIFF_NORMED
    • 相关匹配 CV_TM_CCORR:用两者的乘积匹配,数值越大表明匹配程度越好
    • 归一化相关匹配 CV_TM_CCORR_NORMED
    • 相关系数匹配 CV_TM_CCOEFF:用两者的相关系数匹配,1表示完美匹配,-1表示最差匹配
    • 归一化相关系数匹配 CV_TM_CCOEFF_NORMED

    归一化的意思就是将值统一到0~1,这六种方法的对比详情请见 Template Matching. 模板匹配也是应用卷积来实现的:假设原图大小为 WxH,模板图大小为 w×h,那么生成图大小是(W-w+1)x(H-h+1),生成图中的每个像素值表示原图与模板的匹配程度

    匹配多个物体

    前面我们是找最大匹配的点,所以只能匹配一次。我们可以设定一个匹配阈值来匹配多次:

    # 1. 读入原图和模板
    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
    
    # 这段代码后面会有解释
    loc = np.where(res >= threshold)  # 匹配程度大于80%的坐标y,x
    for pt in zip(*loc[::-1]): # *号表示可选参数
        right_bottom = (pt[0] + w, pt[1] + h)
        cv2.rectangle(img_rgb, pt, right_bottom, (0, 0, 255), 2)
        
    cv2.imwrite('res.png', img_rgb)

    这里解释一下第三段的代码:

    1. np.where() 在这里返回res中值大于0.8的所有坐标,如:

    x = np.arange(9.).reshape(3, 3)
    print(np.where(x > 5))
    (array([2, 2, 2], dtype=int64), array([0, 1, 2], dtype=int64))
    结果的含义是(先y坐标,在x坐标)

    2. zip() 函数

    x = [1, 2, 3]
    y = [4, 5, 6]
    print(list(zip(x, y)))
    [(1, 4), (2, 5), (3, 6)]

    这样的解释的话,第三段代码就好理解了:因为loc是先y坐标再x坐标,所以用loc[::-1]翻转一下,然后再用zip函数拼接一下。

    思考一下:

    图片旋转或缩放的话,模板匹配还有作用吗?

    答案是没有作用,因为只有平移的动作,并没有考虑到其他图像特征。这也是模板匹配的局限性所在,但可以使用改进的模板匹配算法。

    参考百科链接:https://baike.baidu.com/item/模板匹配



  • 相关阅读:
    GPG实践
    keepass口令管理实践
    2019-2020 20191204《信息安全导论》第十一周学习总结
    2019-2020 20191204第十周学习总结
    2019-2020 20191211第八周学习总结
    熟悉编程语言
    斐波那契数列
    辗转相除法
    20191210_获奖感言及学习总结
    2019-2020-1 20191210第11周学习总结
  • 原文地址:https://www.cnblogs.com/gezhuangzhuang/p/10724769.html
Copyright © 2020-2023  润新知