☰
Airtest 图像识别核心:aircv.template 模板匹配模块源码级解析(find_template 与 find_all_template)
2026/9/25 3:19:54 网站建设 项目流程
  • 测试
  • 质量保障
  • 计算机视觉

【免费下载链接】Airtest

UI Automation Framework for Games and Apps

项目地址:https://gitcode.com/gh_mirrors/ai/Airtest
点击查看免费下载

本文导读: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 直接定义了用户可调节的两个核心参数:

对用户提供的调节参数:

  1. threshold: 筛选阈值,默认为 0.8
  2. 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_sourcenumpy 数组(cv2 图像)无屏幕截图,即"大图",作为搜索空间
im_searchnumpy 数组(cv2 图像)无待查找的目标小图,即"模板"
thresholdfloat0.8筛选阈值,识别结果的置信度(confidence)低于该值则判定为未找到,返回None
rgbboolFalse是否启用彩色三通道校验;为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的源码把整个匹配过程拆成了清晰的四步,每步都有独立私有函数支撑:

  1. 校验图像输入:调用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)。这保证了匹配的物理可行性。

  2. 计算匹配结果矩阵:调用_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] 之间。

  3. 取出最优位置并计算置信度:通过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)做三通道彩色校验(详见下文)。
  4. 计算目标矩形与中心点,生成标准结果:_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,用于限制最多返回的匹配数量。其流程如下:

  1. 同样先做输入校验与结果矩阵计算;
  2. 进入while True循环,每轮用cv2.minMaxLoc(res)取出当前矩阵中的最优值;
  3. 计算置信度,若confidence < threshold或len(result) > max_count则终止循环;
  4. 记录本轮结果后,用cv2.rectangle(res, ..., (0,0,0), -1)把已匹配区域在结果矩阵中涂黑屏蔽,进入下一轮继续寻找次优匹配(源码中注释掉的cv2.floodFill是另一种候选屏蔽方案,最终选用矩形屏蔽,矩形范围即模板在截图中的覆盖区域);
  5. 返回结果列表;若没有任何匹配(结果列表为空)则返回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:

    1. np.clip(img, 10, 245)将像素值裁剪到 [10, 245],减少极限值(纯黑/纯白)对后续角度计算的影响;
    2. cv2.cvtColor(..., COLOR_BGR2HSV)将两图转到 HSV 色彩空间,强化颜色的区分度;
    3. cv2.copyMakeBorder(..., 10, 10, 10, 10, BORDER_REPLICATE)扩展置信度计算区域,并故意把边界两像素置为 0 和 255,加入取值范围干扰,防止算法过于放大微小差异;
    4. cv2.split拆分三个通道,对每个通道单独跑cv2.matchTemplate(..., TM_CCOEFF_NORMED)得到三个相关系数;
    5. 最终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:

  1. 用户在脚本中写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)。
  2. 匹配时Template._cv_match按ST.CVSTRATEGY配置的方法顺序逐个尝试,"tpl"映射到TemplateMatching,调用其find_best_result()(airtest/core/cv.py)。sift/surf/brief等方法若因缺少 opencv-contrib 模块而失败,会被_try_match捕获并降级,不影响后续方法。
  3. loop_find(airtest/core/cv.py)则驱动"截图→匹配→超时重试"的循环:每次循环调用G.DEVICE.snapshot()获取im_source,调用query.match_in(screen);timeout内找不到就抛出TargetNotFoundError。注意loop_find中threshold的传递方式:只有传入非空threshold时才会覆盖query.threshold,否则沿用 Template 对象自身配置。
  4. 另外,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

项目地址:https://gitcode.com/gh_mirrors/ai/Airtest
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询