原文链接

—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.模板算法简绍

官网教程 tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_template_matching/py_template_matching.html#>

网络教程 : https://www.jianshu.com/p/5f4bb5c78184

具体用途 : 从一张大的背景图中,找到一张你想要的小图;

例子1:例如从足球比赛场(背景大图)中找到梅西(待找小图):

提高pyautogui识图率的优化方案 - 图1
提高pyautogui识图率的优化方案 - 图2
例子2:从一个电路版(背景大图)中找到主控芯片(待找小图)

提高pyautogui识图率的优化方案 - 图3

2.算法性能测试

结论 : 尽量选择干扰小的背景,匹配的图尽量的丰富,优先考虑使用cv2.TM_CCOEFF_NORMED算法。
注意:这个测试并非专业测试,结果仅仅对于桌面图标的识别的简单测试,只能参考
提高pyautogui识图率的优化方案 - 图4

3.测试代码

  1. # 导入模块 cv2匹配算法 plt 显示图片
  2. import cv2
  3. from matplotlib import pyplot as plt
  4. # 读入图片 big1.png是背景大图; small.png是需要寻找的小图(格式.jpg .png都行)
  5. img = cv2.imread("big1.png",0) # 0 读入灰度图
  6. img3 = cv2.imread("big1.png",1) # 1 读入彩色图
  7. img2 = img.copy()
  8. template = cv2.imread("small.png",0)
  9. w, h = template.shape[::-1]
  10. # 6种算法的列表
  11. methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
  12. 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
  13. # 依次使用算法匹配
  14. for meth in methods:
  15. img = img2.copy()
  16. method = eval(meth)
  17. # 应用模板算法,返回一系列指标
  18. res = cv2.matchTemplate(img,template,method)
  19. min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 从res中挑选最优指标
  20. # 注意 TM_SQDIFF 或者 TM_SQDIFF_NORMED 算法使用最小值为最优
  21. if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
  22. top_left = min_loc
  23. else:
  24. top_left = max_loc
  25. bottom_right = (top_left[0] + w, top_left[1] + h)
  26. # 显示图片
  27. cv2.rectangle(img3,top_left, bottom_right, (0,0,255), 2) # 画出矩形框
  28. plt.axis('off') # 关闭坐标
  29. img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB) # 颜色转换
  30. plt.subplot(121),plt.imshow(res,cmap = 'gray')
  31. plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
  32. plt.subplot(122),plt.imshow(img3)
  33. plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
  34. plt.suptitle(meth)
  35. plt.show()

(四)图片识别的自动化办公

(1)环境安装

python版本:python3.6

第三方库:

  1. pip install opencv-python==4.5.1.48
  2. pip install pillow==8.2.0
  3. pip install pyautogui==0.9.52
  4. pip install win32gui==221.6
  5. pip install pywin32==300

注意:pip 安装库慢,可以设置安装源,在命令行输入(永久设置)

  1. 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(),其他的都是调用这个函数操作。

  1. # 导入所需要的库 cv2:匹配图片 pyautogui:控制鼠标 os 操作文件 win32gui win32con 窗体操作
  2. import cv2
  3. import pyautogui
  4. import win32gui, win32con
  5. import os
  6. def imgAutoCick(tempFile, whatDo, debug=False):
  7. '''
  8. temFile :需要匹配的小图
  9. whatDo :需要的操作
  10. pyautogui.moveTo(w/2, h/2)# 基本移动
  11. pyautogui.click() # 左键单击
  12. pyautogui.doubleClick() # 左键双击
  13. pyautogui.rightClick() # 右键单击
  14. pyautogui.middleClick() # 中键单击
  15. pyautogui.tripleClick() # 鼠标当前位置3击
  16. pyautogui.scroll(10) # 滚轮往上滚10, 注意方向, 负值往下滑
  17. 更多详情:https://blog.csdn.net/weixin_43430036/article/details/84650938
  18. debug :是否开启显示调试窗口
  19. '''
  20. # 读取屏幕,并保存到本地
  21. pyautogui.screenshot('big.png')
  22. # 读入背景图片
  23. gray = cv2.imread("big.png",0)
  24. # 读入需要查找的图片
  25. img_template = cv2.imread(tempFile,0)
  26. # 得到图片的高和宽
  27. w, h = img_template.shape[::-1]
  28. # 模板匹配操作
  29. res = cv2.matchTemplate(gray,img_template,cv2.TM_SQDIFF)
  30. # 得到最大和最小值得位置
  31. min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
  32. top = min_loc[0]
  33. left = min_loc[1]
  34. x = [top, left, w, h]
  35. top_left = min_loc #左上角的位置
  36. bottom_right = (top_left[0] + w, top_left[1] + h) #右下角的位
  37. # 先移动再操作, 进行点击动作,可以修改为其他动作
  38. pyautogui.moveTo(top+h/2, left+w/2)
  39. whatDo(x)
  40. if debug:
  41. # 读取原图
  42. img = cv2.imread("big.png",1)
  43. # 在原图上画矩形
  44. cv2.rectangle(img,top_left, bottom_right, (0,0,255), 2)
  45. # 调试显示
  46. img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST)
  47. cv2.imshow("processed",img)
  48. cv2.waitKey(0)
  49. # 销毁所有窗口
  50. cv2.destroyAllWindows()
  51. os.remove("big.png")
  52. def simple_example_baidu():
  53. '''这是一个例子---百度搜索图片 需要先准备好图片,截图就可以'''
  54. # 调用函数-- 打开浏览器
  55. time.sleep(1)
  56. imgAutoCick("baidu_tu/test2.png", pyautogui.click)
  57. # 点击搜索框 百度搜图片
  58. time.sleep(2)
  59. imgAutoCick("baidu_tu/test3.png", pyautogui.click)
  60. # 输入内容
  61. time.sleep(1)
  62. pyautogui.typewrite("meinv1") #键盘输入
  63. # 点击搜索按钮
  64. time.sleep(1)
  65. imgAutoCick("baidu_tu/test4.png", pyautogui.click)
  66. # 点击图片按钮
  67. time.sleep(1)
  68. imgAutoCick("baidu_tu/test5.png", pyautogui.click)
  69. # 将鼠标移动到中间
  70. m, n = pyautogui.size()
  71. pyautogui.moveTo(x=m/2, y=n/2)
  72. # 将鼠标滚动
  73. for i in range(100):
  74. time.sleep(0.5)
  75. pyautogui.scroll(-120) # 滚轮往上滚10
  76. if __name__=="__main__":
  77. # 将代码窗口最小化
  78. Minimize = win32gui.GetForegroundWindow()
  79. win32gui.ShowWindow(Minimize, win32con.SW_MINIMIZE)
  80. #simple_example_baidu()
  81. #pyautogui.alert(text='下面即将打开开始菜单', title='提示')
  82. pyautogui.PAUSE = 1
  83. pyautogui.press('winleft')
  84. pyautogui.PAUSE = 1
  85. imgAutoCick("baidu_tu/step1.png", pyautogui.click,True)

(五)不足之处:

1.存在一个大问题,就是背景图改变之后,背景里的小图和需要匹配的小图,两者的尺寸不一致,导致框出来的位置不准确。但是取了中间点也就问题不是很多,再出问题的画,下次再解决。
2.pyautogui中文输入问题