Airtest图像识别

2019-01-14   出处:腾讯移动品质中心TMQ  作/译者:milotian(田蜜)  

Airtest是一款网易出品的基于图像识别面向手游UI测试的工具,也支持原生Android App基于元素识别的UI自动化测试。主要包含了三部分:Airtest IDE、Airtest(用截图写脚本)和 Poco(用界面UI元素来写脚本)。来自Google的评价:Airtest 是安卓游戏开发最强大、最全面的自动测试方案之一。


图示为AirtestIDE中脚本运行范例

本文重点是针对Airtest中的图像识别进行代码走读,加深对图像识别原理的理解(公众号贴出的代码显示不全仅供参考,详细代码可以在github查看)。


一、准备工作

下载好源码:

https://github.com/AirtestProject/Airtest导入IDE,我这里用的是Pycharm。


二、我们从图示中touch方法入手

如图示所示,从touch图片开始,即为点击某个传入的图片,源码在api.py里面:


这个函数执行点击操作的是 G.DEVICE.touch(pos, **kwargs),而pos就是图片匹配返回的坐标位置,重点看loop_find这个函数是怎样识别并返回坐标数据的:


解读下这个loop_find这个方法:

1、首先会获取手机屏幕截图;

2、然后对比脚本传入图片获取匹配上的位置;

3、一直重复上面两步骤直到匹配上或者超时。

跟脚本传入图片进行匹配的代码在这一行 match_pos = query.match_in(screen)

在cv.py 里面找到 Template类的 match_in方法:



解读下 match_in方法:

1、调用自己的_cv_math方法,找到匹配到的坐标结果;

2、根据图片坐标返回点击坐标,默认点击图片中心位置。

接下来看 self._cv_match(screen) 也在cv.py 里面:



解读下_cv_match代码:

1、将用例传入的截图进行缩放(写用例设备与运行用例设备可能不一致);

2、遍历配置项里面的方法,进行匹配,如果是 tpl 则执行_find_template;

如果是sift,先执行_find_sift_in_predict_area 如果还没结果就再执行_find_sift。

这里的可以在settings.py 里面找到默认的定义:

CVSTRATEGY = ["tpl", "sift"]

如果某个方法匹配上了,就返回匹配结果,而_find_sift_in_predict_area 也会调用到 _find_sift,通过方法名可以理解,前者就是在指定区域进行_find_sift。所以我们接下来看cv.py 中的_find_template 和 _find_sift方法:




三、重点分析 aircv.find_template

aircv.find_template 具体实现在 template.py:



概括来说aircv.find_template 主要做了这几件事情:

1、校验图像输入;

2、计算模板匹配的结果矩阵res;

3、依次获取匹配结果;

4、求取可信度;

5、求取识别位置。

confidence 可信度可以简单理解为相似度,这里默认的阈值是threshold=0.8 如果匹配的结果大于这个0.8就把最佳匹配的坐标返回,否则认为没有匹配上返回None,在写脚本的时候可以传入threshold这个参数来提高或降低匹配精度。best_match 就是最佳匹配的坐标,重点看 _get_template_result_matrix是怎样得到匹配结果的:



这里可以看到,Airtest也没有自研一套很牛的图像识别算法,直接用的OpenCV的模板匹配方法。


四、接着看另外一个方法 aircv.find_sift

定义在sift.py里面:


matches = FLANN.knnMatch(des_sch, des_src, k=2) 这就是在对图像的特征点进行匹配,FLANN 是快速最近邻搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)的简称,它是一个对大数据和高维特征进行最近邻搜索算法的集合。至于这个sift是什么对象,就是通过这个对象获取到图像特征点:


可以看到,用到的也是OpenCV的方法,如果是OpenCV3则查找图像特征点集的方法就是:

cv2.xfeatures2d.SIFT_create(edgeThreshold=10).detectAndCompute() 


五、最终用到的就是OpenCV的两个方法:模版匹配和特征匹配

1.模板匹配: 

cv2.matchTemplate(i_gray, s_gray, cv2.TM_CCOEFF_NORMED)

2.特征匹配:

cv2.FlannBasedMatcher(index_params,search_params).knnMatch(des1,des2,k=2)

哪个优先匹配上了,就直接返回结果,可以看到用的都是OpenCV的图像识别算法。


六、总结

1、图像识别,对不能用ui控件定位的地方的,使用图像识别来定位,对一些自定义控件、H5、小程序、游戏,都可以支持;
2、支持多个终端,使用图像识别的话可以一套代码兼容android和ios哦,用ui控件定位的话需要兼容一下;
3、缺点:对于背景透明的按钮控件,或写用例和跑用例设备分辨率相差较大都会造成识别难度加大。


后期我们会根据每个维度陆续写相关的测试文章,如果你有兴趣,请关注我们哦。



欢迎给测试窝投稿或参与内容翻译工作,请邮件至editors@testwo.com。也欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,并与我们的编辑和其他窝友交流。
228°|2281 人阅读|0 条评论

登录 后发表评论