macOS下基于图像识别的自动化程序
2017-04-08杨雨昕吕伟龙向豪
杨雨昕 吕伟龙 向豪
摘要:随着macOS系统用户的逐渐增多,各类应用需求不断增加,而自动化程序的出现可以解决可以解决许多日常应用中的痛点难点,比如重复性操作、游戏外挂、自动抢票等。文章给出一种在macOS系统下自动化程序的实现框架,不同于一般的自动化程序,其特点是可以从屏幕截图自动识别信息,利用多种不同的程序语言完成不同的功能模块,最终实现一个可以自动进行扫雷游戏的程序。其中,利用python语言实现程序主框架并完成人机交互,利用C++语言高效实现核心算法策略,利用octave语言实现图像的读取与识别。
关键词:图像识别;自动化程序;程序设计;macOS,python;C++;octave;深度优先搜索(DFS)
中图法分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)05-0155-05
随着macOS系统用户的逐渐增多,各类应用需求不断增加,而自动化程序的出现可以解决可以解决许多日常应用中的痛点难点,比如重复性操作、游戏外挂、自动抢票等。
Python是一种强大的解释型程序设计语言,在各种库的帮助下可以便捷的实现各种强大的功能。Octave是一个类似于MATLAB的开源的科学计算及数值分析工具,擅长处理图片等矩阵型数据。C++是一种广泛使用的程序设计语言,相比于python它有更高的执行速度,许多核心算法在python上实现会遇到速度瓶颈,C++的实现则可以让速度提升一至两个数量级。
笔者在macOS系统下使用python、c++、octave三种语言实现了一个扫雷游戏的自动化程序(下简称扫雷自动机),能够读取并识别屏幕图像,模拟用户的思维与操作,从而自动进行游戏。该文希望通过对这个自动化程序的分析,给其他程序初学者提供一个可行的自动化程序解决方案。
1主框架流程
2重难点分析
扫雷自动机需要完成信息获取、局面决策、人机交互三个大任务。信息获取中,需要完成屏幕截图、图像读取、图像识别等子任务;局面决策需要在保证正确性的情况下尽可能多的判断出一定是或一定不是地雷的位置,提高每一次主循环的效率;人机交互方面需要在保证速度的同时考虑到游戏本身的性能,太快会让游戏本身来不及反应,甚至出现一些严重的错误。
2.1信息获取
自动化程序获取信息的方式可以大致分为三种,一种是环境已提供好便于读取的信息,通过调用接口或读取文件就可以解决;一种是通过一些反编译手段从内存中获取到环境不希望我们获得的信息;还有一种从用户屏幕、音响等输出设备间接获取。这里我们通过屏幕图像间接获取信息。
2.1.1屏幕截图
在macOS下,屏幕截图可以由macOS系统自带的命令‘screencapture完成,此命令可以将图片保存至指定路径或剪贴板。另外,还可以使用PIL库中的ImageGrab.grab()函数将当前屏幕图像保存至内存中,并转换成可供python使用的格式。
2.1.2图像读取
根据图像数据保存的位置,可通过imread()等常规手段读取硬盘中的图像,也可以利用python的PIL库函数截屏至内存,还可以通过AppKit的NSPasteboard读取剪贴板中的图像。
将图像保存至硬盘再通过常规手段读取,整体速度取决于硬盘的速度;使用PIL截屏至内存,简洁方便,但這样便不能通过octave工具分析图像,且其速度与手动保存至硬盘再读取相似,可以合理推断其实现采用了相同的方法。通过AppKit的NSPasteboard读取剪贴板中的图像性能最佳,不过需要swift或Objective-C的支持,以及转换到python所支持的格式。
2.1.3图像识别
在扫雷自动机中,图像识别的任务是获取扫雷地图上每一个方格的状态。而在其他应用中,可以是识别验证码、锁定人物位置等功能。
识别每一个方格的状态,首先需要确定每一个方格在图像中的相对位置。笔者的方法是先找到游戏界面的左上角,再根据每一个方块与游戏界面的左上角的相对位置计算每一个方块在整个图像中的绝对位置。寻找游戏界面左上角的方法可以很灵活,笔者直接枚举一个小区域中的所有像素点,当与标准左上角区域吻合时,就是左上角的位置。
整个决策算法包含两种方法,优先循环使用第一种方法,无法更新地图后使用第二种方法,循环这个过程,直到地图经过两种方法都无法更新。
2.3 人机交互
人机交互部分可以由python的第三方库完成,笔者选择使用PyUserInput库,可以实现模拟用户鼠标点击事件。点击位置由之前确定的各个方格的位置以及局面决策结果确定,由于本次采用H5扫雷进行测试,性能不足,两次点击之间需要有一定的时间间隔,否则游戏本身无法正常响应。
3 程序实现
整个扫雷自动机由三部分组成,首先是python的主框架部分,负责架构整个项目、调用各个模块、储存信息、人机交互等;其次是C++的局面决策部分,负责分析扫雷游戏的一个局面,给出当前最优解;最后是数据输入部分,也就是屏幕图像的获取、读取和识别,由octave完成。
下面选取一些主要的函数或细节进行分析。
3.1 主框架
主框架由python编写
3.1.1 截图
3.3.3 地图识别
地图识别的过程和数据收集以及模型训练中的预测过程类似,得到图像数据后,输入模型即可。
4 效率分析
扫雷自动机是由三种语言共同完成,这中间有一系列的程序调用、文件读写。下面给出扫雷自动机在游戏循环内的访问关系。
其中,C++程序内独立计时后发现,包括文件读写在内,其真实平均运行时间为0.289ms,远远低于python中调用它的总耗时,可见在python中使用os库调用其他可执行文件或脚本是需要可观的成本的,大约为5ms。
而octave/图像识别模块是扫雷自动机游戏循环中最耗时的部分,成为性能瓶颈。经过分析,其中的两个子步骤占用了大部分时间,分别是读取图像文件和读取模型参数矩阵,平均耗时分别为0.446s以及0.394s。
若要优化扫雷自动机的性能,可以放弃octave模块,使用python在初始化时读取模型参数矩阵,避免其在循环体内重复读取,并用python语言实现octave图像识别模块的功能;使用不压缩的图片格式(例如.tiff .bmp等)保存截图,可以提高读取图片的速度,在python中使用scipy.misc的imread()读取.tiff格式的截图,耗时在80ms左右。这样一个循环的总耗时可以控制在0.25s左右,整体提速4~5倍。
若需要进一步提高性能,需要利用AppKit的NSPasteboard直接读取剪贴板(内存)中的图像,在这里不做过多的讨论。
5 扫雷自动机效果图
6 结束语
计算机技术不断发展,合理利用程序设计语言等工具可以给予我们许多帮助。在操作系统的支持下,使用不同的手段,合理组合不同的工具,可以充分发挥其各自的能力,组合出花样繁多的功能。希望这个自动化程序的设计过程能够给大家带来启发。由于本人水平限制,文中难免存在各种问题,欢迎读者批评指正。
参考文献:
[1] 周志华.机器学习[M].北京:清华大学出版社,2016:53-65.
[2] 刘颖超,张纪元.梯度下降法[J].南京理工大学学报(自然科学版),1993(02):12-16,22.
[3] Anany Levitin.算法设计与分析基础(第3版)[M].北京:清华大学出版社,2015:94-96.