网站菜单

OpenCV学习笔记(11)——模板匹配

单对象匹配

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与图像被模板覆盖区域的差别程度。这个差别程度的计算方法在OpenCV里有6中,然后将每次计算的结果放入一个矩阵中,作为输出结果。假设原图像是A*B大小,模板是a*b大小,则输出结果的矩阵是(A-a+1)*(B-b+1)

这里重点说一下几种匹配方法的区别

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

一般都使用归一化的匹配方法。

#模板匹配
#第一步,读取灰度图
img = cv2.imread('lena,jpg', 0)
template = cv2.imread('face.jpg', 0)

#第二部,获得模板大小与匹配方法
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
            'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
h, w = template.shape[:2]

#第三步,使用每一种方法进行匹配
for meth in methods:
    #备份原图
    img = img1.copy()
    method = eval(meth)
    # 应用模板匹配
    res = cv2.matchTemplate(img,template,method)
    #找到最大值和最小值
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    print(cv2.minMaxLoc(res))
    # 如果匹配方法是 TM_SQDIFF or 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, 2)

    #使用matplotlib绘制原图与添加了长方形的图
    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(

多对象匹配

单个匹配是找最大匹配的点,所以只能匹配一次。

对于多对象匹配,我们需要设定一个匹配阈值来匹配多次。

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

img = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('guy.jpg',0)
h, w = template.shape[:2]

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

#设定一个阈值。根据算法,有的是越大越好,有的是越小越好
threshold = 0.7

loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
    
cv2.imshow('img', img)
cv2.waitKey(0)

#识别图像保存到本地
#cv2.imwrite('res.png',img_rgb)
显示评论 (0)

文章评论

相关推荐

Yolov5_Seg输出解析

通过矩阵乘法(在代码中称为“matmul”)来计算分割掩码的原因,主要与实例分割网络(例如 YOLOv5 Segmentation)的实现方式有关。这种方法实际上是一种高效的特征图与目标分割系数组合的…

Ubuntu交叉编译Python

在 Ubuntu 上交叉编译 Python 的流程通常用于为不同平台生成可执行文件(如 ARM、MIPS 等)。以下是一般的操作步骤: 1. 安装必要的依赖工具 首先,确保已经安装了编译所需的工具和依…