批量图像识别的快速遍历技巧
一、前言
二、方法详解
Multiple_exists()
函数。该函数通过循环执行截图操作,每0.2秒进行一次,以最小化循环识别时间。接着将设备屏幕截图和目标图像传递给 match_in_predict_area()
函数,进行裁剪和搜索。一旦找到匹配的图像,立即将坐标信息反馈给 Multiple_exists()
函数,并最终将图像编号和位置信息返回至主函数,供进一步使用。 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("确认已进入到游戏的开始界面")
四、总结
本文分享自微信公众号 - AirtestProject(AirtestProject)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Monorepo:让你的项目脱胎换骨,既能代码复用,又能独立部署!
本文由体验技术团队Kagol原创。 你的项目是不是正在不断膨胀,构建速度越来越慢,包体积越来越大,性能越来越慢了? 想拆分到不同的仓库中分开维护,又担心代码不方便复用? 你可能需要将项目改造成 Monorepo 啦! 我将带大家把一个现有项目改造成 Monorepo 方式,便于扩展和多项目复用。 如果你也有类似的需求,可以点赞、收藏下本文,关键时刻也许能帮上忙。 1 为什么需要做 Monorepo 改造 使用 monorepo 方式组织代码的前提是: 你有多个项目,并且需要在多个项目中复用组件和逻辑。 如果每个项目都是完全独立的,没有什么共用的代码(几乎不太可能),那也许你就不需要用 monorepo 啦。 1.1 Monorepo 的好处 使用 Monorepo 方式组织项目代码,至少有以下好处: 便于代码复用:多个仓库都会用到的组件、工具函数、类型声明、样式等,可以放到 common 子包中,需要的仓库直接 npm install 这个子包就行,就跟 npm install 一个 npm 包一样容易。 独立构建和部署:每个子包都是一个独立的项目,有自己的 package.json ...
- 下一篇
试用 Kubernetes Gateway API 的五大理由
原文作者:Michael Pleshakov - F5平台集成工程师 原文链接:试用 Kubernetes Gateway API 的五大理由 转载来源:NGINX 中文官网 NGINX 唯一中文官方社区 ,尽在nginx.org.cn Kubernetes从早期阶段就包含一个 API — 内置Ingress 资源,用于配置外部 HTTP 流量到Service的请求路由。虽然已被用户广泛采用并得到许多实现(如 Ingress controller)的支持,但 Ingress 资源在以下三大方面限制了其用户: 功能不足– 减少了支持的用例数量。 可扩展性模型不佳– 限制了对 NGINX 等许多数据平面中已有的高级功能的访问。 缺少不同的用户角色– 阻碍了集群内多个团队之间安全共享数据平面基础设施。 为了应对这些限制,Kubernetes 社区设计了Gateway API,这个新项目可更有效地替代 Ingress 资源。本文阐释了试用 Gateway API 的五大理由,并将其与 Ingress 资源进行了比较,另外还介绍了我们的开源项目NGINX Gateway Fabric。该项目支持...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程