- 测试
- 质量保障
- 计算机视觉
【免费下载链接】Airtest
UI Automation Framework for Games and Apps
本文导读:Airtest 是面向游戏与应用的 UI 自动化测试框架,图像识别是其核心能力之一,而airtest/aircv/template.py正是整套图像识别链路的入口模块。本文将围绕该模块的两个公开函数find_template/find_all_template,结合aircv包内的工具函数、置信度算法、上层Template类与测试用例,完整讲解模板匹配的参数语义、执行流程、返回结果格式与调参实践。读完本文,你将掌握如何在 Airtest 中直接调用底层模板匹配 API,理解threshold与rgb两个参数的真实作用,并能根据源码判断不同场景下的参数选择。
模块定位:aircv.template 在 Airtest 中的作用
docs/all_module/airtest.aircv.template.rst是 Airtest 文档体系中针对airtest/aircv/template.py模块的 API 说明页(Sphinxautomodule自动生成),其内容主体即该模块的完整源码。模块位于 airtest/aircv/template.py,并在 airtest/aircv/init.py 中被显式导出:
from .template import find_template, find_all_template # noqa因此,aircv.template是 Airtest 图像识别体系中"模板匹配"(Template Matching)这一基础算法的公开入口。模块 docstring 直接定义了用户可调节的两个核心参数:
对用户提供的调节参数:
- threshold: 筛选阈值,默认为 0.8
- rgb: 彩色三通道,进行彩色权识别
模板匹配的原理是:在屏幕截图(im_source)中滑动搜索预先准备好的小图(im_search),找出相似度最高(或所有超过阈值)的区域。它是 Airtest 中touch、swipe、wait、exists等 API 的识别底座——上层 airtest/core/cv.py 中MATCHING_METHODS字典的"tpl"项即指向模板匹配实现类,且ST.CVSTRATEGY默认策略一般将tpl放在首位。
核心 API 一:find_template —— 找到最优匹配区域
函数签名与文档一致(airtest/aircv/template.py):
def find_template(im_source, im_search, threshold=0.8, rgb=False):参数说明
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
im_source | numpy 数组(cv2 图像) | 无 | 屏幕截图,即"大图",作为搜索空间 |
im_search | numpy 数组(cv2 图像) | 无 | 待查找的目标小图,即"模板" |
threshold | float | 0.8 | 筛选阈值,识别结果的置信度(confidence)低于该值则判定为未找到,返回None |
rgb | bool | False | 是否启用彩色三通道校验;为True时对候选区域做 BGR 三通道加权识别,为False时直接采用灰度匹配的相关系数 |
需要注意im_source/im_search必须是 numpy 矩阵格式的图像,通常通过airtest.aircv.imread(filename)读取(airtest/aircv/aircv.py)。该函数支持中文路径,因为 Python 3 下使用cv2.imdecode(np.fromfile(...))而非直接cv2.imread。
内部执行流程(四步)
find_template的源码把整个匹配过程拆成了清晰的四步,每步都有独立私有函数支撑:
校验图像输入:调用
check_source_larger_than_search(im_source, im_search)(airtest/aircv/utils.py),检查模板图是否比截图更大;若im_search的高或宽超过im_source,会抛出TemplateInputError("error: in template match, found im_search bigger than im_source.")(异常类定义见 airtest/aircv/error.py)。这保证了匹配的物理可行性。计算匹配结果矩阵:调用
_get_template_result_matrix()(airtest/aircv/template.py)。由于cv2.matchTemplate只能处理灰度图,这里先把两张图通过img_mat_rgb_2_gray(airtest/aircv/utils.py,内部即cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))转为灰度,然后执行:res = cv2.matchTemplate(i_gray, s_gray, cv2.TM_CCOEFF_NORMED)即使用归一化相关系数法(TM_CCOEFF_NORMED)在截图矩阵上滑动模板,生成一张"相似度热度图"
res,其取值范围理论上落在 [-1, 1] 之间。取出最优位置并计算置信度:通过
cv2.minMaxLoc(res)拿到结果矩阵中的最大值max_val及其位置max_loc(即模板左上角在截图中的坐标)。随后由_get_confidence_from_matrix(airtest/aircv/template.py)计算最终置信度:rgb=False时:confidence = max_val,直接使用灰度匹配的相关系数;rgb=True时:从截图中裁出候选区域img_crop = im_source[max_loc[1]:max_loc[1]+h, max_loc[0]:max_loc[0]+w],调用cal_rgb_confidence(img_crop, im_search)做三通道彩色校验(详见下文)。
计算目标矩形与中心点,生成标准结果:
_get_target_rectangle(max_loc, w, h)(airtest/aircv/template.py)以匹配到的左上角为基准,加上模板宽高w, h,得到中心点middle_point与四角点序列rectangle(顺序为左上→左下→右下→右上),再交给generate_result封装。
最后执行return best_match if confidence >= threshold else None,即低于阈值一律视为"未找到"。
返回结果格式
generate_result(airtest/aircv/utils.py)统一了所有 aircv 识别结果的字典格式:
ret = dict(result=middle_point, # 中心点坐标 (x, y),供点击使用 rectangle=pypts, # 四个角点,顺序为 左上->左下->右下->右上 confidence=confi) # 置信度 float上层 airtest/core/cv.py 的match_in正是利用result字段通过TargetPos换算实际点击焦点;而rectangle可用于画框、断言或日志展示。
核心 API 二:find_all_template —— 找出所有匹配区域
当同一张截图里出现多个相同目标(例如一屏多个"领取"按钮)时,使用find_all_template(airtest/aircv/template.py):
def find_all_template(im_source, im_search, threshold=0.8, rgb=False, max_count=10):相比find_template多了max_count参数,默认10,用于限制最多返回的匹配数量。其流程如下:
- 同样先做输入校验与结果矩阵计算;
- 进入
while True循环,每轮用cv2.minMaxLoc(res)取出当前矩阵中的最优值; - 计算置信度,若
confidence < threshold或len(result) > max_count则终止循环; - 记录本轮结果后,用
cv2.rectangle(res, ..., (0,0,0), -1)把已匹配区域在结果矩阵中涂黑屏蔽,进入下一轮继续寻找次优匹配(源码中注释掉的cv2.floodFill是另一种候选屏蔽方案,最终选用矩形屏蔽,矩形范围即模板在截图中的覆盖区域); - 返回结果列表;若没有任何匹配(结果列表为空)则返回
None。
result = [] # 每个元素都是 {"result": 中心点, "rectangle": 四角点, "confidence": 置信度}注意循环中有一个细节:len(result) > max_count是在confidence < threshold之后才判断,实际最多可能返回max_count + 1个结果,编写上层逻辑时如对数量有严格要求应自行裁剪。
置信度计算的两个分支:灰度相关系数与 RGB 三通道校验
_get_confidence_from_matrix揭示了rgb参数的本质——它决定置信度的计算口径:
灰度模式(rgb=False):直接信任
cv2.matchTemplate的TM_CCOEFF_NORMED结果。速度快,但只比较亮度结构,颜色相同的不同物体可能互相误判。彩色模式(rgb=True):对候选区域逐通道校验。其实现位于 airtest/aircv/cal_confidence.py 的
cal_rgb_confidence:np.clip(img, 10, 245)将像素值裁剪到 [10, 245],减少极限值(纯黑/纯白)对后续角度计算的影响;cv2.cvtColor(..., COLOR_BGR2HSV)将两图转到 HSV 色彩空间,强化颜色的区分度;cv2.copyMakeBorder(..., 10, 10, 10, 10, BORDER_REPLICATE)扩展置信度计算区域,并故意把边界两像素置为 0 和 255,加入取值范围干扰,防止算法过于放大微小差异;cv2.split拆分三个通道,对每个通道单独跑cv2.matchTemplate(..., TM_CCOEFF_NORMED)得到三个相关系数;- 最终
return min(bgr_confidence)—— 取三通道中最小的那个作为整体置信度。
"取三通道最小值"意味着:只要任何一个颜色通道匹配度不达标,整体置信度就会被拉低,因此rgb=True时对颜色变化的敏感度显著更高,适合背景复杂、同类形状不同颜色的场景(例如区分红色和绿色的相同按钮)。代价是额外的裁图、HSV 转换和三轮匹配计算。
工程封装对照:函数式 API 与 TemplateMatching 类
airtest/aircv/template.py提供的是函数式 API;而框架内部实际运行的是 airtest/aircv/template_matching.py 中的TemplateMatching类,两者算法流程完全同构:
| 函数式(template.py) | 类封装(template_matching.py) |
|---|---|
find_template(im_source, im_search, threshold, rgb) | TemplateMatching(im_search, im_source, threshold, rgb).find_best_result() |
find_all_template(im_source, im_search, threshold, rgb, max_count) | TemplateMatching(...).find_all_results() |
_get_template_result_matrix | 同名方法_get_template_result_matrix |
_get_confidence_from_matrix | 同名方法_get_confidence_from_matrix |
两类实现共享同样的工具函数(generate_result、check_source_larger_than_search、img_mat_rgb_2_gray)与置信度算法(cal_rgb_confidence)。类版本额外增加了print_run_time装饰器(airtest/aircv/utils.py)记录耗时,并把最大结果数固化在类常量MAX_RESULT_COUNT = 10。值得注意的一点差异:函数式版本rgb默认False,而类版本默认rgb=True,直接使用时应留意这个默认值区别。
在上层 API 中的完整调用链:Template 类与 CVSTRATEGY
aircv.template的匹配函数并非孤立存在,它们通过 airtest/core/cv.py 接入 Airtest 的touch/wait/exists等脚本 API:
- 用户在脚本中写
touch(Template("tpl.png")),即创建Template对象(airtest/core/cv.py)。其构造函数暴露了threshold、rgb、scale_max、scale_step、target_pos、record_pos、resolution等参数,其中threshold缺省时取全局ST.THRESHOLD(见 airtest/core/settings.py)。 - 匹配时
Template._cv_match按ST.CVSTRATEGY配置的方法顺序逐个尝试,"tpl"映射到TemplateMatching,调用其find_best_result()(airtest/core/cv.py)。sift/surf/brief等方法若因缺少 opencv-contrib 模块而失败,会被_try_match捕获并降级,不影响后续方法。 loop_find(airtest/core/cv.py)则驱动"截图→匹配→超时重试"的循环:每次循环调用G.DEVICE.snapshot()获取im_source,调用query.match_in(screen);timeout内找不到就抛出TargetNotFoundError。注意loop_find中threshold的传递方式:只有传入非空threshold时才会覆盖query.threshold,否则沿用 Template 对象自身配置。- 另外,
Template对象在record_pos/resolution存在时,可借助Predictor(airtest/core/cv.py)预测目标在屏幕上的大致区域,用于关键点类匹配的剪裁加速。
对于普通脚本用户而言,这意味着aircv.template的两个threshold、rgb参数与Template/ST.CVSTRATEGY完全贯通:Template("x.png", threshold=0.9, rgb=True)最终就会以rgb=True走cal_rgb_confidence彩色校验路径。
测试验证:模板匹配的正确性由单测保障
aircv.template的匹配行为有对应单元测试覆盖,见 tests/test_aircv.py:
def test_func_find_template(self): """Test find_template function in template.py.""" result = find_template(self.template_src, self.template_sch, threshold=self.THRESHOLD, rgb=self.RGB) self.assertIsInstance(result, dict) def test_func_find_all_template(self): """Test find_all_template function in template.py.""" result = find_all_template(self.template_src, self.template_sch, threshold=self.THRESHOLD, rgb=self.RGB) self.assertIsInstance(result, list)测试类TestAircv(tests/test_aircv.py)设置的THRESHOLD = 0.7、RGB = True,并加载 tests/matching_images/template_search.png(模板)与 tests/matching_images/template_screen.png(整屏截图)作为输入。同文件中test_find_template(类封装版本,tests/test_aircv.py)还验证了TemplateMatching类路径。此外测试文件头部注释给出了各匹配算法的工程经验排序("单纯效果,推荐程度:tpl > surf ≈ sift > ..."),从侧面印证模板匹配是 Airtest 中效果与资源占用最均衡的默认首选方案。
如需复现,可在仓库根目录执行python -m pytest tests/test_aircv.py(或参考 runtest.sh),前提是安装requirements.txt中的 opencv 依赖。
调参实践:threshold 与 rgb 的选取建议
结合源码行为,可以给出如下可验证的调参结论:
- threshold(默认 0.8):confidence 低于此值即返回
None/ 停止查找。由于TM_CCOEFF_NORMED是归一化相关系数,0.8 是一个工程上较稳健的起点;目标被遮挡、光照变化或缩放时相关系数会明显下降,此时可适当下调(如 0.6~0.7)。测试中使用的0.7即为低阈值示例。 - rgb(默认 False):截图是彩色图时推荐开启
rgb=True,它能借助三通道最小值校验显著降低"形状相同、颜色不同"的误报;代价是每次匹配多出 HSV 转换与三通道匹配的开销。若目标区域颜色单一、背景干净,或对性能敏感(如高频循环查找),保持rgb=False即可。 - 模板大小:
im_search尺寸必须小于im_source,否则直接抛TemplateInputError;且模板越小,灰度相关性对噪声越敏感,threshold可能需要相应放宽。 - 多目标场景:使用
find_all_template时可通过max_count限制返回数量,并结合rectangle四点坐标做后续去重与排序。
小结
airtest.aircv.template是 Airtest 图像识别体系中最基础、最常用的匹配算法模块:find_template与find_all_template两个函数以threshold(默认 0.8)与rgb(默认 False)两个参数,完整覆盖了"单目标最优匹配"与"多目标遍历匹配"两类需求。其灰度TM_CCOEFF_NORMED匹配 + 可选 RGB/HSV 三通道校验 + 标准result/rectangle/confidence返回格式的设计,也被上层TemplateMatching类、Template对象与CVSTRATEGY策略链完整复用。理解本模块,就相当于掌握了 Airtest 中所有基于图片定位 API 的底层运作机制。
- 测试
- 质量保障
- 计算机视觉
【免费下载链接】Airtest
UI Automation Framework for Games and Apps
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考