—opencv-python的模板匹配算法Template Matching
(一)需求分析
如今2021年,祖国发展进入了新征程,科技技术的发展,更是不可同日而语,自动化人工智能越来越普及,钢铁侠的贾维斯仍旧高科技,办公自动化,也是一个进步吧;扯远了,,,,。近日在使用quicker软件的时候,有一个动作叫按键精灵(之前也有一个软件叫这个),目的都一样,可以录制鼠标按键的过程,不足之处在于太依赖快捷键,并且鼠标的位置是绝对位置,也就是说只能录制一些位置固定的重复动作,并达不到灵活的录制效果,于是心生一个想法,利用python的图像识别
- 按键模拟实现这样灵活的动作效果。虽然pyautogui有一个函数也可以匹配图片,但是效果不理想,所以才提出的这个方案。
pyautogui.locateOnScreen(‘folder.png’)
在当前屏幕匹配folder.png文件。
总之 :一句话,python的图像识别 + 按键模拟实现自动化办公
(二)pyautogui的使用
1.pyautogui简介
PyAutoGUI具有以下功能:
- 移动鼠标,然后单击或在其他应用程序的窗口中键入。
- 向应用程序发送击键(例如,填写表格)。
- 截取屏幕截图,并给出图像(例如,按钮或复选框的图像),然后在屏幕上找到它。
- 找到应用程序的窗口,然后移动,调整大小,最大化,最小化或关闭它(当前仅Windows)
- 在GUI自动化脚本运行时,显示消息框供用户交互
- 总结 :就是模拟键盘鼠标的操作
官方教程 : https://pyautogui.readthedocs.io/en/latest/
网络教程 :
https://blog.csdn.net/weixin_43430036/article/details/84650938(推荐,讲得比较详细)
(三)opencv-python的模板匹配算法Template Matching
1.模板算法简绍
官网教程 :
网络教程 : https://www.jianshu.com/p/5f4bb5c78184
具体用途 : 从一张大的背景图中,找到一张你想要的小图;
例子1:例如从足球比赛场(背景大图)中找到梅西(待找小图):
例子2:从一个电路版(背景大图)中找到主控芯片(待找小图)
2.算法性能测试
结论 : 尽量选择干扰小的背景,匹配的图尽量的丰富,优先考虑使用cv2.TM_CCOEFF_NORMED算法。
注意:这个测试并非专业测试,结果仅仅对于桌面图标的识别的简单测试,只能参考
3.测试代码
# 导入模块 cv2匹配算法 plt 显示图片
import cv2
from matplotlib import pyplot as plt
# 读入图片 big1.png是背景大图; small.png是需要寻找的小图(格式.jpg .png都行)
img = cv2.imread("big1.png",0) # 0 读入灰度图
img3 = cv2.imread("big1.png",1) # 1 读入彩色图
img2 = img.copy()
template = cv2.imread("small.png",0)
w, h = template.shape[::-1]
# 6种算法的列表
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
# 依次使用算法匹配
for meth in methods:
img = img2.copy()
method = eval(meth)
# 应用模板算法,返回一系列指标
res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 从res中挑选最优指标
# 注意 TM_SQDIFF 或者 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(img3,top_left, bottom_right, (0,0,255), 2) # 画出矩形框
plt.axis('off') # 关闭坐标
img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB) # 颜色转换
plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img3)
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
(四)图片识别的自动化办公
(1)环境安装
python版本:python3.6
第三方库:
pip install opencv-python==4.5.1.48
pip install pillow==8.2.0
pip install pyautogui==0.9.52
pip install win32gui==221.6
pip install pywin32==300
注意:pip 安装库慢,可以设置安装源,在命令行输入(永久设置)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pyautogui安装失败的,可以参考:http://www.bubuko.com/infodetail-2982758.html
(2)思路:
通过cv2的Template Matching算法,匹配到小图在大图的位置,使用pyautogui模拟按钮操作。
(3)代码
启动顺序:事先把需要操作的图标截好图,最为小图,大图不需要准备,大图利用自动全屏截图。
具体的代码请看注释,注意的功能函数就是imgAutoCick(),其他的都是调用这个函数操作。
# 导入所需要的库 cv2:匹配图片 pyautogui:控制鼠标 os 操作文件 win32gui win32con 窗体操作
import cv2
import pyautogui
import win32gui, win32con
import os
def imgAutoCick(tempFile, whatDo, debug=False):
'''
temFile :需要匹配的小图
whatDo :需要的操作
pyautogui.moveTo(w/2, h/2)# 基本移动
pyautogui.click() # 左键单击
pyautogui.doubleClick() # 左键双击
pyautogui.rightClick() # 右键单击
pyautogui.middleClick() # 中键单击
pyautogui.tripleClick() # 鼠标当前位置3击
pyautogui.scroll(10) # 滚轮往上滚10, 注意方向, 负值往下滑
更多详情:https://blog.csdn.net/weixin_43430036/article/details/84650938
debug :是否开启显示调试窗口
'''
# 读取屏幕,并保存到本地
pyautogui.screenshot('big.png')
# 读入背景图片
gray = cv2.imread("big.png",0)
# 读入需要查找的图片
img_template = cv2.imread(tempFile,0)
# 得到图片的高和宽
w, h = img_template.shape[::-1]
# 模板匹配操作
res = cv2.matchTemplate(gray,img_template,cv2.TM_SQDIFF)
# 得到最大和最小值得位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top = min_loc[0]
left = min_loc[1]
x = [top, left, w, h]
top_left = min_loc #左上角的位置
bottom_right = (top_left[0] + w, top_left[1] + h) #右下角的位
# 先移动再操作, 进行点击动作,可以修改为其他动作
pyautogui.moveTo(top+h/2, left+w/2)
whatDo(x)
if debug:
# 读取原图
img = cv2.imread("big.png",1)
# 在原图上画矩形
cv2.rectangle(img,top_left, bottom_right, (0,0,255), 2)
# 调试显示
img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST)
cv2.imshow("processed",img)
cv2.waitKey(0)
# 销毁所有窗口
cv2.destroyAllWindows()
os.remove("big.png")
def simple_example_baidu():
'''这是一个例子---百度搜索图片 需要先准备好图片,截图就可以'''
# 调用函数-- 打开浏览器
time.sleep(1)
imgAutoCick("baidu_tu/test2.png", pyautogui.click)
# 点击搜索框 百度搜图片
time.sleep(2)
imgAutoCick("baidu_tu/test3.png", pyautogui.click)
# 输入内容
time.sleep(1)
pyautogui.typewrite("meinv1") #键盘输入
# 点击搜索按钮
time.sleep(1)
imgAutoCick("baidu_tu/test4.png", pyautogui.click)
# 点击图片按钮
time.sleep(1)
imgAutoCick("baidu_tu/test5.png", pyautogui.click)
# 将鼠标移动到中间
m, n = pyautogui.size()
pyautogui.moveTo(x=m/2, y=n/2)
# 将鼠标滚动
for i in range(100):
time.sleep(0.5)
pyautogui.scroll(-120) # 滚轮往上滚10
if __name__=="__main__":
# 将代码窗口最小化
Minimize = win32gui.GetForegroundWindow()
win32gui.ShowWindow(Minimize, win32con.SW_MINIMIZE)
#simple_example_baidu()
#pyautogui.alert(text='下面即将打开开始菜单', title='提示')
pyautogui.PAUSE = 1
pyautogui.press('winleft')
pyautogui.PAUSE = 1
imgAutoCick("baidu_tu/step1.png", pyautogui.click,True)
(五)不足之处:
1.存在一个大问题,就是背景图改变之后,背景里的小图和需要匹配的小图,两者的尺寸不一致,导致框出来的位置不准确。但是取了中间点也就问题不是很多,再出问题的画,下次再解决。
2.pyautogui中文输入问题