如何用 Python 和 OpenCV 实现模板匹配


前言

在本文中,我将使用 Python 和 OpenCV 库来实现一个简单的模板匹配脚本,它可以在屏幕上寻找和点击指定的图像。这个脚本可以用于一些自动化的任务,比如网页刷新、游戏操作等。

准备工作

要运行这个脚本,需要安装以下几个库

cv2:OpenCV 的 Python 接口,用于图像处理和模板匹配。
pyautogui:一个跨平台的 GUI 自动化库,用于模拟鼠标和键盘操作。
time:一个内置的库,用于控制时间和延迟。
keyboard:一个用于监听和模拟键盘事件的库。
numpy:一个用于科学计算的库,用于处理数组和矩阵。

可以使用 pip 命令来安装这些库,例如

pip install opencv-python
pip install pyautogui
pip install keyboard
pip install numpy

另外,还需要准备一个模板图像,即想要在屏幕上寻找和点击的图像。可以使用任何图像编辑软件来制作这个图像,只要它的大小和颜色与屏幕上的目标图像一致即可。可以将这个图像保存为 template.png,并放在与脚本相同的目录下。

计算公式

在这里插入图片描述

其中,T’ 和 I’ 分别是模板图像和目标图像的均值化后的像素值,x 和 y 是模板图像在目标图像上的位置,x’ 和 y’ 是模板图像的像素坐标,R(x,y) 是相似度的值,它的范围是 [-1, 1],1 表示完全匹配,0 表示毫无关系,-1 表示两张图像亮度刚好相反。
使用归一化相关系数匹配法的优点是,它可以抵抗光照变化的影响,因为它只考虑像素值的相对大小,而不是绝对大小。它的缺点是,它可能会误匹配一些具有相同纹理或颜色的区域,因为它没有考虑像素值的分布。

模板匹配的原理

模板匹配的原理很简单,就是用一个小的图像(模板)在一个大的图像(目标)上滑动,并比较每个位置的相似度,当相似度达到一定的阈值时,就认为找到了匹配的位置。OpenCV 提供了 matchTemplate 函数来实现模板匹配,它的语法如下

result = cv2.matchTemplate(image, templ, method)

其中,image 是目标图像,templ 是模板图像,method 是匹配的方式,result 是一个二维数组,存储了每个位置的匹配结果。OpenCV 支持以下六种匹配方式

cv2.TM_SQDIFF:平方差匹配法,计算目标和模板之间的差值的平方和,值越小表示越相似。
cv2.TM_SQDIFF_NORMED:归一化平方差匹配法,对平方差匹配法的结果进行归一化,值在 0 到 1 之间,值越小表示越相似。
cv2.TM_CCORR:相关匹配法,计算目标和模板之间的相关性,值越大表示越相似。
cv2.TM_CCORR_NORMED:归一化相关匹配法,对相关匹配法的结果进行归一化,值在 0 到 1 之间,值越大表示越相似。
cv2.TM_CCOEFF:相关系数匹配法,计算目标和模板之间的相关系数,值在 -1 到 1 之间,值越接近 1 表示越相似,值越接近 -1 表示越相反。
cv2.TM_CCOEFF_NORMED:归一化相关系数匹配法,对相关系数匹配法的结果进行归一化,值在 -1 到 1 之间,值越接近 1 表示越相似,值越接近 -1 表示越相反。
不同的匹配方式适用于不同的场景,一般来说,归一化的匹配方式比非归一化的匹配方式更准确,但也更耗时。相关系数匹配法比相关匹配法更能抵抗光照变化的影响,但也更容易受到噪声的干扰。平方差匹配法比较简单,但对图像的尺寸和旋转比较敏感。具体选择哪种匹配方式,需要根据实际的应用场景和需求进行测试和比较。

模板匹配的示例

为了演示模板匹配的效果,我们准备了一张按钮图标(template.png),如下所示
在这里插入图片描述

我们的目标是在网页截图中找到按钮图标的位置,并用鼠标点击它。

template_image = cv2.imread('template.png', cv2.IMREAD_GRAYSCALE)  # 模板图像路径
template_width, template_height = template_image.shape[::-1]

注意,我们使用了 cv2.IMREAD_GRAYSCALE 参数,将图像转换为灰度图,这样可以减少计算量,提高匹配速度。如果图像中的颜色对匹配结果有影响,可以不使用这个参数,或者使用其他的颜色空间转换函数,如 cv2.cvtColor

然后,我们需要创建一个无限循环,每隔一定的时间,模拟按下 F5 键,刷新网页,然后获取当前屏幕的截图,并将其转换为灰度图

import cv2
import pyautogui
import time
import keyboard  # 请确保已安装 keyboard 模块
import numpy as np  # 导入 NumPy 库

print("按下 Ctrl+C 停止脚本")

while True:
    print("模拟按下 F5")
    keyboard.press_and_release('F5')  # 模拟按下并释放 F5 键
    
    print("开始模板匹配")
    
    # 获取当前屏幕截图
    screen_shot = pyautogui.screenshot()
    screen_image = cv2.cvtColor(np.array(screen_shot), cv2.COLOR_RGB2GRAY)

这里,我们使用了 pyautogui.screenshot 函数来获取屏幕截图,它返回的是一个 PIL.Image 对象,我们需要使用 np.array 函数将其转换为一个 NumPy 数组,然后使用 cv2.cvtColor 函数将其转换为灰度图。

接下来,我们需要在屏幕截图中搜索模板,我们使用 cv2.matchTemplate 函数,并选择 cv2.TM_CCOEFF_NORMED 作为匹配方式,然后使用 cv2.minMaxLoc 函数来获取匹配结果中的最大值和最大值位置

# 在屏幕截图中搜索模板
result = cv2.matchTemplate(screen_image, template_image, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

由于我们使用了归一化相关系数匹配法,匹配结果的值在 -1 到 1 之间,值越接近 1 表示越相似,所以我们需要找到最大值和最大值位置。如果使用其他的匹配方式,可能需要找到最小值和最小值位置。

最后,我们需要判断匹配值是否大于某个阈值,如果是,就认为找到了模板,然后计算模板的中心位置,并用鼠标点击它

# 如果匹配值大于某个阈值,认为找到了模板
threshold = 0.8
if max_val >= threshold:
	# 计算点击位置
    click_x, click_y = max_loc[0] +template_width / 2, max_loc[1] + template_height / 2
    pyautogui.click(click_x, click_y)
    
print("等待5秒")
time.sleep(5)

这里,我们设置了阈值为 0.8,表示只有当匹配值大于等于 0.8 时,才认为是有效的匹配。这个阈值可以根据实际的情况进行调整,一般来说,越接近 1,表示越严格的匹配,越接近 0,表示越宽松的匹配。我们还需要计算模板的中心位置,因为 max_loc 返回的是模板的左上角的位置,所以我们需要加上模板的宽度和高度的一半,才能得到模板的中心位置。然后,我们使用 pyautogui.click 函数来模拟鼠标点击,传入点击的坐标。

最后,我们使用 time.sleep 函数来控制循环的时间间隔,这里我们设置为 5 秒,表示每隔 5 秒执行一次模板匹配和鼠标点击。如果想要停止脚本,可以按下 Ctrl+C 键。

模板匹配的效果

我们将上述代码保存为 template_match.py 文件,并在同一目录下放置 template.png 文件,然后运行脚本

python template_match.py

运行后,我们可以看到脚本的输出信息,如下所示

按下 Ctrl+C 停止脚本
模拟按下 F5
开始模板匹配
等待5秒
模拟按下 F5
开始模板匹配
等待5秒

同时,我们可以看到网页被刷新,并且鼠标自动移动到按钮图标的位置,并点击它。这样,我们就实现了一个简单的模板匹配和鼠标点击的功能。
在这里插入图片描述

模板匹配的局限性

模板匹配是一种简单而有效的图像匹配方法,但它也有一些局限性,例如

模板匹配对图像的尺寸、旋转、形变、遮挡等变化比较敏感,如果目标和模板之间有较大的差异,可能导致匹配失败或误匹配。
模板匹配需要提前准备好模板图像,如果目标的外观不固定或不确定,可能需要多个模板或动态生成模板,这会增加复杂度和计算量。
模板匹配只能找到目标的位置,而不能提取目标的特征或属性,如果需要进一步分析或识别目标,可能需要使用其他的图像处理或机器学习方法。

总结

本文介绍了如何使用 Python 和 OpenCV 库来实现模板匹配,并给出了一个简单的示例代码,演示了如何在网页截图中找到按钮图标的位置,并用鼠标点击它。模板匹配是一种在图像中寻找特定目标的方法,它可以用来实现自动化测试、游戏辅助、图像识别等功能。但模板匹配也有一些局限性,对图像的变化比较敏感,需要提前准备好模板图像,只能找到目标的位置,而不能提取目标的特征或属性。如果想要实现更复杂的图像匹配或识别功能,可能需要使用其他的图像处理或机器学习方法。

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪弯了眉梢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值