这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » OpenVINO生态社区 » 【原创】OpenCV-Python系列之模板匹配(三十九)

共1条 1/1 1 跳转至

【原创】OpenCV-Python系列之模板匹配(三十九)

高工
2020-07-20 22:02:11     打赏

OpenCV-Python系列之模板匹配

我们在之前讨论OpenCV的轮廓以及直方图时已经接触过类似的匹配,事实上,它们原理基本上差不多,都是用一幅模板图像和原图进行匹配,从而找到原图中相应的地方,作为OpenCV中的一种最基本的目标识别的方法,模板匹配有其一定的作用,今天我们来具体的进行讨论。

模板匹配是一种用于在较大图像中搜索和查找模板图像位置的方法。为此,OpenCV带有一个函数cv.matchTemplate()

它只是将模板图像滑动到输入图像上(就像在2D卷积中一样),然后在模板图像下比较模板和输入图像的拼图。

如果输入图像的大小为(WxH),而模板图像的大小为(wxh),则输出图像的大小将为(W-w + 1H-h + 1)。得到结果后,可以使用cv.minMaxLoc()函数查找最大/最小值在哪。将其作为矩形的左上角,并以(wh)作为矩形的宽度和高度,该矩形是模板的区域。

现在我们来进行分析,先来看第一个函数:

result=cv.matchTemplate(image, templ, method[, result[, mask]])

参数image:待搜索的图像(大图)

参数temple:搜索模板,需要和原图一样的数据类型且尺寸不能大于源图像

参数result:比较结果的映射图像,其必须为单通道,32位浮点型图像,如果原图(待搜索图像)尺寸为W*H,temple尺寸为w*h,result尺寸一定是

    (W-w+1)*(H-h+1)

参数method:指定匹配方法,有如下几种:

    CV_TM_SQDIFF:平方差匹配法;

    CV_TM_SQDIFF_NORMED:归一化平方差匹配法;

    CV_TM_CCORR:相关匹配法;

    CV_TM_CCORR_NORMED:归一化相关匹配法;

    CV_TM_CCOEFF:系数匹配法;

    CV_TM_CCOEFF_NORMED:化相关系数匹配法。

T表示模板图像,I表示待匹配图像,切模板图像的宽为w高为h,用R表示匹配结果,匹配过程如下图所示:

image.png

上述6中匹配方法可用以下公式进行描述:

1TM_SQDIFF

该方法名为平方差匹配法,计算的公式如式(6.9)所示,这种方法利用平方差来进行匹配,当模板与滑动窗口完全匹配时计算数值为0,两者匹配度越低计算数值越大。

image.png

其中 image.png 表示模板图像, image.png 表示原图像。

2TM_SQDIFF_NORMED

该方法名为归一化平方差匹配方法,计算公式如式(6.10)所示,这种方法是将平方差方法进行归一化,使得输入结果缩放到了01之间,当模板与滑动窗口完全匹配时计算数值为0,两者匹配度越低计算数值越大。

image.png

3TM_CCORR

该方法名为相关匹配法,计算公式如式(6.11)所示,这类方法采用模板和图像间的乘法操作,所以数值越大表示匹配效果越好,0表示最坏的匹配结果。

image.png

4TM_CCORR_NORMED

该方法名为归一化相关匹配法,计算公式如式(6.12)所示,这种方法是将相关匹配法进行归一化,使得输入结果缩放到了01之间,当模板与滑动窗口完全匹配时计算数值为1,两者完全不匹配时计算结果为0

image.png

5TM_CCOEFF

该方法名为系数匹配法,计算公式如式(6.13)所示,这种方法采用相关匹配方法对模板减去均值的结果和原图像减去均值的结果进行匹配,这种方法可以很好的解决模板图像和原图像之间由于亮度不同而产生的影响。该方法中模板与滑动窗口匹配度越高计算数值越大,匹配度越低计算数值越小,并且该方法计算结果可以为负数。

image.png

其中:

image.png

6TM_CCOEFF_NORMED

该方法名为归一化系数匹配法,计算公式如式(6.15)所示,这种方法将系数匹配方法进行归一化,使得输入结果缩放到了1-1之间,当模板与滑动窗口完全匹配时计算数值为1,当两者完全不匹配时计算结果为-1

image.png

再来看另一个函数:
minVal
maxValminLocmaxLoc=cv.minMaxLocsrc [mask]

函数功能:假设有一个矩阵a,现在需要求这个矩阵的最小值,最大值,并得到最大值,最小值的索引。咋一看感觉很复杂,但使用这个cv2.minMaxLoc()函数就可全部解决。函数返回的四个值就是上述所要得到的。

现在我们使用模板图像:

image.png

原图:

image.png

我们将尝试所有比较方法,以便我们可以看到它们的结果如何(如果使用cv.TM_SQDIFF作为比较方法,则最小值提供最佳匹配,其余的方法使用最大值进行最佳匹配),我们来看代码:

def template():
    img = cv.imread('min.jpg', 0)
    img2 = img.copy()
    template = cv.imread('temp.jpg', 0)
    w, h = template.shape[::-1]
    # 列表中所有的6种比较方法
    methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
               'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
    for meth in methods:
        img = img2.copy()
        method = eval(meth)
        # 应用模板匹配
        res = cv.matchTemplate(img, template, method)
        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
        # 如果方法是TM_SQDIFF或TM_SQDIFF_NORMED,则取最小值
        if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
        bottom_right = (top_left[0] + w, top_left[1] + h)
        cv.rectangle(img, top_left, bottom_right, 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.suptitle(meth)
        plt.show()

来看结果,cv.TM_CCOEFF方法:

image.png

cv.TM_CCOEFF_NORMED:

image.png

cv. TM_CCORR:

image.png

cv.TM_CCORR_NORMED:

image.png

cv.TM_SQDIFF:

image.png

cv.TM_SQDIFF_NORMED:

image.png

由此我们完成了OpenCV的模板匹配,它属于最简单的目标识别,对图像的要求比较高,当原图进行了旋转或者是缩放时,这种匹配方法经常会失效,这个大家可以自行实验,将原图放大或者是缩小,又或者是对图像进行一定角度的旋转,都会导致一定程度的失效,对于这种缺陷,我们在后面会介绍更为强大的特征匹配的方法。

 


对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]