← 返回首页
模板匹配
发表时间:2025-02-22 16:38:34
模板匹配

模板匹配(Template Matching)是OpenCV中一种用于在图像中查找与给定模板图像相似区域的方法。

1.模板匹配

模板匹配是一种在图像中查找目标的方法,它的原理是将一个小的模板图像在原始图像中移动,并计算模板图像与原始图像之间的相似度。在相似度达到一定阈值的情况下,我们就可以认为找到了目标。

在 OpenCV 中,可以使用 cv2.matchTemplate() 函数进行模板匹配。

cv2.matchTemplate(image, templ, method[, result[, mask]]) → result

该函数有四个参数:

源图像:即待匹配的图像。 模板图像:即用来匹配的图像。 匹配方法:用来指定匹配算法,常见的有 6 种,包括: - cv2.TM_CCOEFF //系数匹配 - cv2.TM_CCOEFF_NORMED //归一化系数匹配 - cv2.TM_CCORR //相关匹配 - cv2.TM_CCORR_NORMED ////归一化相关匹配 - cv2.TM_SQDIFF //平方差匹配 - cv2.TM_SQDIFF_NORMED //归一化平方差匹配

在这些匹配方法中,cv2.TM_CCOEFF 和 cv2.TM_CCOEFF_NORMED 方法是最常用的。其中 cv2.TM_CCOEFF 方法会计算源图像和模板图像的相关系数,即两个图像的相似度;而 cv2.TM_CCOEFF_NORMED 方法则是将相关系数进行了归一化,即将相关系数除以源图像和模板图像的标准差的乘积,得到的值在 [-1, 1] 之间,越接近 1 表示匹配度越高。

mask:可选参数,用来指定在源图像和模板图像上进行匹配的区域。

2.OpenCV实现模板匹配

下面让我们来写一个使用 OpenCV 进行模板匹配的项目案例。这个项目的目的是在一张大图中匹配一个小图,并标记出匹配到的位置。

import cv2
import numpy as np

# 加载大图和小图
img = cv2.imread('./images/jpg/football_match01.jpg')
template = cv2.imread('./images/jpg/football_match_dest01.jpg')

# 模板匹配
result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)

# 找到最大值和最大值的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

# 如果使用 TM_CCOEFF_NORMED 算法,则最大值即为相似度的值
print('匹配相似度:', max_val)

# 找到匹配位置的左上角和右下角坐标
w, h = template.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)

# 在大图上标记匹配位置
cv2.rectangle(img, top_left, bottom_right, (0, 0, 255), 2)

# 显示结果
cv2.imshow('result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

多模板匹配实例。实现一个车位识别案例。

import cv2

image = cv2.imread('./images/png/car_park01.png')  # 读取原始图像
templs = []  # 模板列表
templs.append(cv2.imread("./images/png/car_template001.png"))  # 添加模板图像1
templs.append(cv2.imread("./images/png/car_template002.png"))  # 添加模板图像1
templs.append(cv2.imread("./images/png/car_template003.png"))  # 添加模板图像1
templs.append(cv2.imread("./images/png/car_template004.png"))  # 添加模板图像1


for car in templs:  # 遍历所有模板图像
    # 按照标准相关系数匹配
    results = cv2.matchTemplate(image, car, cv2.TM_CCOEFF_NORMED)
    for i in range(len(results)):  # 遍历结果数组的行
        for j in range(len(results[i])):  # 遍历结果数组的列
            # print(results[i][j])
            if results[i][j] > 0.99:  # 如果相关系数大于0.99则认为匹配成功
                if 0 < j <= 164:
                    print("车位编号:", 1)
                elif j <= 392:
                    print("车位编号:", 2)
                elif j <= 600:
                    print("车位编号:", 3)
                else:
                    print("车位编号:", 4)
                break

源图片。

模板图片:

识别结果:

车位编号: 4
车位编号: 3
车位编号: 2
车位编号: 1