在OpenCV里实现模板匹配

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/caimouse/article/details/102603494

目标:使用模板匹配方法在图片里寻找目标对象,学会使用cv.matchTemplate(), cv.minMaxLoc()函数

 

模板匹配算法是从一个大图像里找到感兴趣的目标对象,OpenCV提供函数cv.matchTemplate()来实现相关的功能。模板匹配的原理其实很简单,就是不断地在原图中移动模板图像去比较,有6种不同的比较方法:

平方差匹配CV_TM_SQDIFF:用两者的平方差来匹配,最好的匹配值为0

归一化平方差匹配CV_TM_SQDIFF_NORMED

相关匹配CV_TM_CCORR:用两者的乘积匹配,数值越大表明匹配程度越好

归一化相关匹配CV_TM_CCORR_NORMED

相关系数匹配CV_TM_CCOEFF:用两者的相关系数匹配,1表示完美的匹配,-1表示最差的匹配

归一化相关系数匹配CV_TM_CCOEFF_NORMED

这些方法的对比代码可到源码处查看。模板匹配也是应用卷积来实现的:假设原图大小为W×H,模板图大小为w×h,那么生成图大小是(W-w+1)×(H-h+1),生成图中的每个像素值表示原图与模板的匹配程度。

 

由于这个模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。所以一般用来相同目标物品在不同图片里寻找,或者同一类型图片的查找。比如下面的例子,就是用来寻找不同人的身份证的有效日期的位置:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('cnid.png',0)
img2 = img.copy()
template = cv2.imread('cnid1.png',0)
w, h = template.shape[::-1]

#6种比较方法
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:
    img = img2.copy()
    method = eval(meth)#这里把字符串表达式求值,返回宏表达的数值

    #匹配比较
    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        
    bottom_right = (top_left[0] + w, top_left[1] + h)
    
    cv2.rectangle(img,top_left, bottom_right, 255, 3)#画白色矩形作为标记

    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.suptitle(meth)

    plt.show()

结果输出如下:

输入搜索的目标

最后输出的结果和在原图上标记为白色

通过这样的方式,就可以定位有效日期所在位置,然后再根据位置进行有效日期的截图,再进入后一阶段进行处理和识别。

 

如果在一个图片里有多个相同的目标,就需要使用下面的代码来解释搜索结果:

res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)

threshold = 0.8

loc = np.where( res >= threshold)

for pt in zip(*loc[::-1]):

cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

这里使用阈值进行分割,然后zip函数遍历所有值。

https://blog.csdn.net/caimouse/article/details/51749579

猜你喜欢

转载自blog.csdn.net/caimouse/article/details/102603494