首页 > 其他分享 >批量图像识别的快速遍历技巧

批量图像识别的快速遍历技巧

时间:2024-08-22 10:04:35浏览次数:13  
标签:None 遍历 图像识别 批量 screen focus pos DEVICE rect

此文章来源于项目官方公众号:“AirtestProject”
版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途

一、前言

最近,不少同学在Q群中频繁提出疑问:在日常UI测试过程中,如何快速准确地识别页面上的多个元素,或在日常测试中,如何高效地遍历目标图片列表,以确认画面中是否包含特定元素?在官方交流Q群2群的lincoln同学给出了不错的方法思路,我们也获得了他的授权,现在我们一起来学习一下这个小技巧吧~

二、方法详解

lincoln同学提供了两个方法函数,其中一个是局部查找,一个是多重查找,我们就来看看他的一个函数逻辑是怎么样的吧。

代码逻辑的核心在于快速地识别目标图像。首先,将目标图像(最好是特征鲜明、尺寸小一些)列表输入Multiple_exists()函数。该函数通过循环执行截图操作,每0.2秒进行一次,以最小化循环识别时间。接着将设备屏幕截图和目标图像传递给match_in_predict_area()函数,进行裁剪和搜索。一旦找到匹配的图像,立即将坐标信息反馈给Multiple_exists()函数,并最终将图像编号和位置信息返回至主函数,供进一步使用。

可以看到当日常在跑游戏ui回归或APP回归的时候可以利用起来,当一个元素有多种ui表现形式或着需要判断多个元素的情况时,我们可以参考lincoln同学提供的方式,修改成自己想要的效果。

下面是lincoln同学的方法函数源码,大家可以参考一下:

def match_in_predict_area(template, screen=None, rect=None):  # 局部查找
    # logger = Gvar.logger
    if screen is None:
        if G.DEVICE is None:
            raise Exception("G.DEVICE is none.")
    screen = G.DEVICE.snapshot()  # 截屏
    if screen is None:
        raise Exception("snapshot is none.")
    if rect is None:
        return template.match_in(screen)  # 如果没有指定区域,在整个屏幕中查找
    if not isinstance(rect, (list, tuple)):
        raise Exception("to crop a image, rect should be a list")
    else:
        # logger.debug("找到目标%s"%template.filename)
        predict_screen = aircv.crop_image(screen, rect)  # 图片裁切,根据指定区域裁剪屏幕
        focus_pos = template.match_in(predict_screen)  # 在裁剪后的图片中查找模板
        if not focus_pos:
            return False  # 如果没有找到匹配,返回False
        else:
            return focus_pos[0]+rect[0], focus_pos[1]+rect[1]  # 返回匹配位置,加上裁剪区域的偏移
    # end if
# end def

def Multiple_exists(targets,area=None,threshold=0.80,rgb=False,inti=5):#多重查找
    
    # 根据设备方向确定宽度和高度
    if (G.DEVICE.display_info['orientation']%2):
        width = G.DEVICE.display_info['height']
        height = G.DEVICE.display_info['width']
    else:
        width = G.DEVICE.display_info['width']
        height = G.DEVICE.display_info['height']
    #end if
    
    # 尝试多次查找目标
    for i in range(inti):
        #Gvar.logger.debug('第%d次查找%s'%(i,targets))
        
        # 获取全屏截图
        fullScreen = G.DEVICE.snapshot()
        
        # 遍历每个目标
        for target in targets:
            #print("查找目标 %s"%target)
            if target :
                # 在预测区域内匹配目标,如果有元素固定出现的位置范围,可以传入,更进一步的减少识别时间
                focus_pos = match_in_predict_area(Template( '%d\%s.png'%(width, target),
                threshold=threshold, rgb=rgb),
                fullScreen, area)
            
            # 如果找到目标
            if focus_pos:
                #Gvar.logger.debug("找到目标 %s"%target)
                ref = targets.index(target)
                return ref,focus_pos
        #endif
    #end for
        
        # 每次查找间隔0.2秒
        sleep(0.2)
#end for
    
    # 如果所有尝试都失败,返回-1和(-1,-1)
    return -1,(-1,-1)
#end def Multiple_exists

三、实际使用案例

通过上述所讲的逻辑以及方式,我们这边给大家提供一个小小的使用案例,通过识别游戏画面内的三个元素是否都存在,从而去判断是否进入到我们需要的游戏画面。

参考代码如下:

# -*- encoding=utf8 -*-
__author__ = "Airtest"

import os
from airtest.core.api import *
from airtest.aircv import *

auto_setup(__file__)

from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

def Multiple_exists(targets, area=None, threshold=0.80, rgb=False, inti=5):
    # 定义一个函数,用于检测多个目标是否存在
    # 参数说明:
    # targets: 目标列表
    # area: 搜索区域,默认为None(全屏)
    # threshold: 匹配阈值,默认为0.80
    # rgb: 是否使用RGB匹配,默认为False
    # inti: 尝试次数,默认为5次

    #新增找到的图片位置信息列表
    matches = []
    
    # 根据设备方向确定屏幕宽高
    if (G.DEVICE.display_info['orientation'] % 2):
        width = G.DEVICE.display_info['height']
        height = G.DEVICE.display_info['width']
    else:
        width = G.DEVICE.display_info['width']
        height = G.DEVICE.display_info['height']

    # 在指定的尝试次数内循环查找目标
    for i in range(inti):
        # 获取当前屏幕截图
        fullScreen = G.DEVICE.snapshot()
        # 遍历所有目标
        for target in targets:
            if target:
                # 构建目标图片的完整路径
                template_path = os.path.join(str(width), f"{target}.png")
                print(f"Trying to load template: {template_path}")
                # 在指定区域内查找目标
                focus_pos = match_in_predict_area(Template(template_path, threshold=threshold, rgb=rgb), fullScreen, area)
            #若找到图片则将当前图片出现的位置传入列表中
                if focus_pos:
                    matches.append((targets.index(target), focus_pos))
        # 如果所有目标都找到,立即返回结果
        if len(matches) == len(targets):
            return matches
               
        # 如果未找到所有目标,等待0.2秒后继续下一次尝试
        sleep(0.2)
    # 返回找到的所有匹配结果
    return matches       

def match_in_predict_area(template, screen=None, rect=None):  # 局部找图
    if screen is None:
        if G.DEVICE is None:
            raise Exception("G.DEVICE is none.")
    screen = G.DEVICE.snapshot()  # 获取设备屏幕截图
    if screen is None:
        raise Exception("snapshot is none.")
    if rect is None:
        return template.match_in(screen)  # 如果没有指定区域,在整个屏幕中查找
    if not isinstance(rect, (list, tuple)):
        raise Exception("to crop a image, rect should be a list")
    else:
        # logger.debug("找到目标%s"%template.filename)
        predict_screen = aircv.crop_image(screen, rect)  # 裁剪指定区域的图片
        focus_pos = template.match_in(predict_screen)  # 在裁剪后的图片中查找模板
        if not focus_pos:
            return False  # 如果没有找到匹配,返回False
        else:
            return focus_pos[0]+rect[0], focus_pos[1]+rect[1]  # 返回匹配位置,加上裁剪区域的偏移

if __name__ == "__main__":   
	#打开游戏,去确认是否游戏开始界面的元素已就位
    start_app("com.netease.dyll")
    sleep(1.0)
    poco(text="确定").click()
    touch([0.5,0.5])
    sleep(0.2)

    # 定义目标图片的路径列表
    targets = [r"D:/demo/pics.air/tpl1724135823600",r"D:/demo/pics.air/tpl1724135830426",r"D:/demo/pics.air/tpl1724135836266"]
    
    # 调用multiple_exists函数,查找游戏开始界面的图片识别情况
    result = Multiple_exists(targets)

#     打印查找结果
    for i in range(len(result)):
        print("图片{}的位置是:{}".format(i+1,result[i]))
        
    # 判断是否已进入游戏开始界面
    if len(result) == len(targets) :
        print("确认已进入到游戏的开始界面")

四、总结

本周推文我们分享了来自官方交流Q群2群的lincoln同学的一个快速遍历找图的方法函数,这里再次感谢lincoln同学的分享,在函数内我们主要的一个减少识别时间的思路是通过截图当前设备画面,并进行裁切判断,从而避免整个设备屏幕范围内寻找元素。

如果大家有更多好用好玩的Airtest使用脚本,也欢迎大家给我们投稿,同时如果大家在使用Airtest过程中有一些其他新的使用方式或者遇到了问题,又或者有任何想要深入了解的知识点,欢迎在官方交流群(526033840)里告诉我们或者提交issue。


AirtestIDE下载:airtest.netease.com/
Airtest 教程官网:airtest.doc.io.netease.com/
搭建企业私有云服务:airlab.163.com/b2b

官方答疑 Q 群:526033840

标签:None,遍历,图像识别,批量,screen,focus,pos,DEVICE,rect
From: https://www.cnblogs.com/AirtestProject/p/18373180

相关文章

  • df.iterrows() 是 Pandas 中的一个方法,用于在遍历 DataFrame 时,逐行返回每一行的索引
    df.iterrows()是Pandas中的一个方法,用于在遍历DataFrame时,逐行返回每一行的索引和数据。它生成一个迭代器,每次迭代时返回一个(index,Series)对,index是行索引,Series是该行的数据。详细解释df.iterrows():这个方法遍历DataFrame的每一行。每次迭代时,返回的是(ind......
  • 【Advanced Renamer】,批量修改文件名,啥都能改的神器!
    最近有朋友问有没有可能批量修改文件、文件夹名字的工具?好多人都吐槽,下载资源的时候都有一堆引流的后缀,想直接下载到本地后批量修改。这里从解决实际问题的角度上,给你大家带来一款知名最高的“批量修改文件名”的小工具:【AdvancedRenamer】资源在文末。在Windows种,通过快......
  • 头歌 第4关:层次遍历二叉树
    任务描述本关任务:给定一棵二叉树,借助队列实现层次遍历二叉树。相关知识为了完成本关任务,你需要掌握:1.队列的类型定义及基本操作,2.二叉树层次遍历。队列的类型定义及基本操作队列的类型定义:#define MAXSIZE100  //最大长度typedefBiTNode*QElemType;//队列中......
  • ffmpeg批量mov转换mp4格式脚本
    vim convertMP4.sh 输入脚本:#!/bin/bash#检查是否提供了输入目录路径if[-z"$1"];thenecho"Usage:$0<input_directory>"exit1fi#获取输入目录路径input_directory="$1"#检查输入目录是否存在if[!-d"$input_directory"];......
  • 【Oracle】存储过程中将动态SQL的多行结果进行循环遍历
    【Oracle】存储过程中将动态SQL的多行结果进行循环遍历需求背景:有一段拼接出来的动态SQL,结果为多行,需要在函数或者存储过程中将其结果作为游标中的数据循环遍历出来以便后续数据操作使用动态SQL和隐式游标隐式游标不支持动态SQL的直接使用,但是可以通过EXECUTEIMMEDIATE来执行......
  • 【实用】【一眼就会】【直接可用】文件上传 附件上传 前后端分离 分布式 多文件上传
    思路:1、先保存主要信息,存到数据库。2、查询这条数据的id、uid3、上传附件功能:根据id、uid、文件。请求:附件API接口。4、后端接口中:先判断登录状态,5、创建对应的文件夹并存入文件,文件夹名以id名命名。6、把附件名重命名,以uuid命名。7、把所有的文件路径放到集合里,传入id......
  • jmeter如何产生批量数据?
    在使用jmeter时,若需要产生批量数据,可以通过连接数据库--执行相关sql进行操作,例如添加20条数据步骤:1.添加jdbc数据库配置信息2.添加循环控制器(循环次数20)3.循环控制器子级添加计数器(从1开始递增),计数器变量设置为n4.循环控制器子级添加jdbcrequest,QueryType选择upd......
  • 批量创建/删除用户
    #!/bin/bashread-p"请输入你想创建用户的前缀:"prefix[-z$prefix]&&echo"必须输入前缀"&&exit #控制前缀不能为空[[!$prefix=~^[a-Z]+$]]&&echo"请输入正确的前缀"&&exit #控制前缀为字母read-p"请输入你想创建用户的个数:"......
  • 10046-1-批量为视频添加文字水印每隔几秒钟显示一次水印-视频首尾不显示水印-UI
    程序功使用环境▶适用的系统环境说明:win7以上64位win系统注意:win32位系统/mac系统需要额外定制▶使用期限:无需注册、不绑电脑、无时间限制▶如何安装:不需要安装程序功能说明▶子文件夹穿透:支持▶支持的文件格式:'.mp4','.avi','.mkv','.webm','.ts','.flv','.mov','.wmv'......
  • C++批量核验身份证真伪、实名认证接口、身份证识别
    实名认证接口是指一个系统或程序,它能够接收用户的个人信息(如姓名、身份证号码等),并与官方记录进行匹配以验证这些信息的真实性。这种接口可以集成到各种应用程序和服务中,以增强安全性并遵守相关法律法规的要求。批量核验身份证真伪以及进行实名认证是许多在线服务平台为了......