算法与深度学习·

模板匹配介绍、原理与实现-动手学深度学习4

首发于 CSDN原文链接

本篇目录11 节

1. 模板匹配介绍

模板匹配(Template Matching)是计算机视觉和图像处理中一种常用的技术,用于在较大图像中定位与给定模板图像最相似的区域。它是一种基于像素比较的方法,广泛应用于:
  • 目标检测
  • 物体识别
  • 工业检测
  • 医学图像分析
  • 视频监控等领域

2. 模板匹配原理

基本思想

模板匹配的基本思想是:在源图像上滑动模板图像,
计算模板
与源图像对应区域的相似度,找到相似度最高的位置即为匹配结果。

数学表示

对于源图像I(大小为W×H)和模板T(大小为w×h),在源图像上的每个位置(x,y)计算相似度:
互相关公式: ![R(x,y) = sum_{x'=0}^{w-1}sum_{y'=0}^{h-1} [T(x',y') - I(x+x', y+y')]^2](https://hllqkb-blog.pages.dev/images/csdn/150151492-1.svg)
其中x'∈[0,w-1], y'∈[0,h-1]

3. 模板匹配实现

Python实现(使用OpenCV)

# 模版匹配 import cv2 from matplotlib import pyplot as plt import numpy as np # 读取图像和模板 img = cv2.imread('lenna.jpg') templ = cv2.imread('template.png') # 获取模板的高度、宽度和通道数 height, width, c = templ.shape # # 模块匹配 使用归一化平方差匹配方法(TM_SQDIFF_NORMED) # results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED) results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF) # 获取匹配结果中的最小值、最大值、最小值坐标和最大值坐标 minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results) # 计算匹配结果的中心坐标 resultPoint1 = minLoc resultPoint2 = (resultPoint1[0] + width, resultPoint1[1] + height) # 绘制矩形框 cv2.rectangle(img, resultPoint1, resultPoint2, (0, 0, 255), 2) # 显示结果 while True: cv2.imshow('Matching Result', img) key = cv2.waitKey(1) # 每1ms检测一次按键 if key == ord('q'): # 按 'q' 退出 break cv2.destroyAllWindows()

4. 模板匹配的优缺点

优点

  • 实现简单直观
  • 计算效率相对较高
  • 对小角度旋转和轻微形变有一定鲁棒性

缺点

  • 对光照变化敏感
  • 对旋转和尺度变化适应性差
  • 当目标被遮挡时效果不佳
  • 背景复杂时容易产生误匹配
最后匹配失败因为
光
照变化
notion image

5. 改进方法

为了提高模板匹配的鲁棒性,可以采用以下改进方法:
使用归一化平方差匹配方法(TM_SQDIFF_NORMED)
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED)
结果:
notion image

6.多目标模板匹配

待匹配图片image.png:
notion image
template2.png文件
notion image
特别要注意图片大小,不能过大过小,最好是在imshow的待匹配图片里面截图才是最合适的大小
相关代码:
import cv2 import numpy as np # 读取图像和模板 img = cv2.imread('image.png') templ = cv2.imread('template2.png') # 检查图像是否成功加载 if img is None or templ is None: print("Error: Could not load one or both images") exit() # 打印图像尺寸 print("Image size:", img.shape) print("Template size:", templ.shape) if img.shape[0] < templ.shape[0] or img.shape[1] < templ.shape[1]: print("Error: Template is larger than image") exit() # 获取模板的高度和宽度 height, width = templ.shape[:2] # 使用归一化平方差匹配方法 result = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 设置匹配阈值 threshold = 0.7 # 获取所有大于阈值的匹配位置 locations = np.where(result >= threshold) locations = list(zip(*locations[::-1])) # 转换为(x,y)坐标列表 # 使用非极大值抑制(NMS)来避免重叠的矩形框 def non_max_suppression(boxes, overlap_thresh=0.5): if len(boxes) == 0: return [] # 将边界框坐标转换为float类型 boxes = np.array(boxes, dtype="float") # 初始化选择的索引列表 pick = [] # 获取边界框的坐标 x1 = boxes[:, 0] y1 = boxes[:, 1] x2 = boxes[:, 2] y2 = boxes[:, 3] # 计算边界框的面积并排序 area = (x2 - x1 ) * (y2 - y1) idxs = np.argsort(y2) # 循环遍历排序后的索引 while len(idxs) > 0: # 获取最后一个索引并将其添加到选择列表中 last = len(idxs) - 1 i = idxs[last] pick.append(i) # 找到当前框与其他框的最大(x,y)坐标 xx1 = np.maximum(x1[i], x1[idxs[:last]]) yy1 = np.maximum(y1[i], y1[idxs[:last]]) xx2 = np.minimum(x2[i], x2[idxs[:last]]) yy2 = np.minimum(y2[i], y2[idxs[:last]]) # 计算重叠区域的宽度和高度 w = np.maximum(0, xx2 - xx1) h = np.maximum(0, yy2 - yy1 ) # 计算重叠比例 overlap = (w * h) / area[idxs[:last]] # 删除重叠比例大于阈值的所有索引 idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlap_thresh)[0]))) # 返回选择的边界框 return boxes[pick].astype("int") # 创建边界框列表 rectangles = [] for loc in locations: rect = [loc[0], loc[1], loc[0] + width, loc[1] + height] rectangles.append(rect) # 应用非极大值抑制 rectangles = non_max_suppression(rectangles) # 绘制所有匹配的矩形框 for (x1, y1, x2, y2) in rectangles: cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) while True: cv2.imshow('Multi-Template Matching', img) k = cv2.waitKey(1) & 0xFF if k == 27: break # 显示结果 cv2.destroyAllWindows()
运行效果
notion image
模板匹配虽然简单,但在特定条件下(如工业检测中的固定场景)仍然非常有效且实用。
这种基于滑动窗口的相识度匹配是很多计算机视觉的基础,从中我们也能慢慢的步入目标检测的大门

评论加载中…