安卓图像识别自动化原理

安卓脚本找图找色原理详解:OpenCV 图像识别与多点找色实战指南

OpenCV 模板匹配如何找图、单点与多点找色、色块查找的适用场景,以及为什么图像识别比坐标点击更稳定(不依赖分辨率与布局)。附函数速览与参数调优建议。

约 20 分钟

安卓自动化的主流做法是免 root,靠无障碍服务和 ADB,让程序去做重复操作。

读不到控件时用找图找色

脚本要操作界面,得先知道界面在哪里。常规做法是读控件树:安卓会给当前界面生成一棵节点树,无障碍服务可以读。每个按钮、输入框、图片都有 id、文本、描述和位置边界,脚本按这些属性找控件。游戏画面里 OpenGL / SurfaceView 渲染的内容没有标准控件节点。自绘控件在节点树里往往只剩一个空壳。图片按钮整张图就是一个按钮。这些界面读不到节点,只能截图找目标,找到再操作。

EasyClick 里,申请截图、抓屏、找图、找色、比色都在图色模块(image 系列 API,对象前缀是 image),走系统官方能力,免 root。

EasyClick 中控设备监控面板展示图像识别与 OCR 结果回传

最早的自动化脚本是坐标脚本,录下屏幕上一个点的 (x, y),到点就点。分辨率一变、布局一调、弹窗一弹,这个坐标就废了。找图记的是目标长什么样,命中后再取出它在屏幕上的位置。按钮挪了位置、换了机型、改了字体,只要样子还在,同一套模板通常还能找到。没有控件节点的界面,只要屏幕上看得到,也能找。目标完全没有颜色和形状特征时,才退回坐标。成熟平台支持在一块坐标区域内随机点击,用来降低操作特征(功能特性文档)。

找图、找色怎么用

找图是目前用得最多的识别手段,做的是模板匹配。准备一张目标小图当模板,在屏幕大图上从上到下、从左到右滑动,每个位置算一次相似度,超过阈值就算命中。命中后返回位置区域(Rect),取中心点当点击坐标。模板从开发工具截下来,放进工程 res 文件夹,脚本里用 readResAutoImage() 读取。相似度由阈值参数控制:

参数 含义 默认值
threshold 图片相似度,0~1 的浮点数,最终命中判定标准 0.9
weakThreshold 弱阈值,用于每一轮匹配中检验是否继续匹配,相似度低于它则提前放弃该轮 0.7

匹配方法(method 参数)有 6 种可选,全部来自 OpenCV 的标准模板匹配方法:

取值 匹配方法 说明
0 TM_SQDIFF 平方差匹配法
1 TM_SQDIFF_NORMED 归一化平方差匹配法
2 TM_CCORR 相关匹配法
3 TM_CCORR_NORMED 归一化相关匹配法
4 TM_CCOEFF 系数匹配法
5 TM_CCOEFF_NORMED 归一化系数匹配法

官方文档写的图像识别率是 95% 以上,指常规、清晰、静态界面(功能特性文档)。实际效果看截图清不清楚、模板和画面是否一致、界面变了多少、阈值设得合不合理。后面是一个能跑的找图示例,函数名和参数顺序以文档为准:

image.initOpenCV();                      // 找图前先初始化 OpenCV 类库(首次较慢,之后很快)
let template = readResAutoImage("sms.png"); // 从工程 res 文件夹读取模板小图
let aimage = image.captureFullScreen();  // 抓取当前屏幕

// 找图:弱阈值 0.7,相似度 0.9,最多找 21 个,method=5 归一化系数匹配法
let points = image.findImage(aimage, template, 0, 0, 0, 0, 0.7, 0.9, 21, 5);
if (points && points.length > 0) {
    // 返回的是 Rect 区域,取中心点作为点击坐标
    let x = parseInt((points[0].left + points[0].right) / 2);
    let y = parseInt((points[0].top + points[0].bottom) / 2);
    clickPoint(x, y);
}
image.recycle(aimage);   // 图片用完要回收,防止内存暴涨
image.recycle(template);

找图还有几个变体。findImageEx 会自己截屏再找。findImage2 带缩放,目标被缩放渲染时比 findImage 更准,EC 9.41.0+。findImageByColor 做透明找图,模板可以带透明,也不用先初始化 OpenCV,EC 7.15.0+。截图本身要花时间。captureScreen 把截图转成 Bitmap,大约 0~20ms。大约 16ms 内连续调用,拿到的是同一张截图(图色函数文档)。模板匹配内部用图像金字塔加速,一般不用自己调。

找色不拿整张图去比,只在指定区域里找指定颜色的点,所以比找图轻。单点找色(findColor)在区域内找和给定值匹配的点,可以带偏色,返回坐标数组。固定色 UI、纯色按钮、状态指示灯常用它。颜色参数格式形如 0xCDD7E9-0x101010,前半是颜色值,后半是偏色容差。threshold 是 01 的颜色相似度,limit 限制返回个数,orz 是 18 的查找方向。单点只核对一个点的颜色,大面积同色背景容易误报。多点找色(findMultiColor)用一个点做锚点,再核对周围若干点的相对位置和颜色,全部符合才算命中:

// 第一个点的颜色作为基准,再校验相对偏移点
// 格式:x 偏移|y 偏移|颜色[-偏色],多个点用逗号分隔
let firstColor = "0xDD7A5F-0x101010";
let points = "29|25|0xBB454B-0x101010,58|44|0xA6363A-0x101010";

// findMultiColorEx 自动截屏多点找色
let result = image.findMultiColorEx(firstColor, points, 0.9, 0, 0, 0, 0, 10, 1);
if (result && result.length > 0) {
    clickPoint(result[0].x, result[0].y);
}

几个点的相对位置和颜色很难在屏幕别处同时对上,所以比单点不容易误报。图标角标、红点、带纹理的按钮常用这种写法。比色(cmpColor / cmpColorEx)检查某个位置上的几个点颜色是否都符合预期,全部符合才返回 true,用来看按钮状态有没有切换。cmpMultiColor / cmpMultiColorEx 可以依次试多组方案,命中返回该组索引,没命中返回 -1。色块查找用的是找色能返回区域内全部匹配点这一点,用来圈出连续色块、找到边界。血条、进度条通常先找两端的颜色边界,再按比例估算,不用准备整张模板图。开发工具可以在截图上取点、取色、生成配置文件。J 系列函数(findColorJ 等)直接从 JSON 读参数。

识别失败怎么调,API 与场景速查

界面会变,一次调好的阈值很难一直管用。找不到就把 threshold 从 0.9 降到 0.85、0.8;找错位置就调高。找色的 threshold 同样处理。阈值只管放多宽,模板本身还得新、还得清楚。全屏查找慢,也容易被别的元素干扰。找图和找色都有 x, y, ex, ey,把范围收在目标可能出现的那一块,同屏相似的元素也不容易认错。同一个目标可以准备几张模板轮流试。多组比色用 cmpMultiColor 一次比完。页面加载有延迟,循环识别,等到目标出现再操作,超时就退出。固定 sleep 经常要么等不够,要么空等。image.setInitParam 可以设置找图找色的最大时间(action_timeout),到点自动返回,免得一直卡住。

找图优先。找不到再找色,还不行就重试。后面是申请截图、找图、找色接在一起的写法:

function main() {
    // 1. 申请截图权限,整个脚本执行一次即可(type 0 自动选择)
    let request = image.requestScreenCapture(10000, 0);
    if (!request) {
        loge("申请截图权限失败");
        exit();
    }
    // 申请完权限至少等 1 秒再截图,否则可能截不到图
    sleep(1000);

    // 2. 找图:在屏幕上找"开始任务"按钮模板(res 文件夹下的 start.png)
    image.initOpenCV();
    let template = readResAutoImage("start.png");
    // findImageEx 自动截屏找图:弱阈值 0.7,相似度 0.9,只找 1 个
    let points = image.findImageEx(template, 0, 0, 0, 0, 0.7, 0.9, 1, 5);
    if (points && points.length > 0) {
        // 返回 Rect 区域,取中心点点击
        let x = parseInt((points[0].left + points[0].right) / 2);
        let y = parseInt((points[0].top + points[0].bottom) / 2);
        clickPoint(x, y);
    } else {
        // 3. 找图失败,退而求其次:找红色角标(颜色带偏色容差)
        let redPoints = image.findColorEx("0xFF3B30-0x101010", 0.9, 0, 0, 0, 0, 10, 1);
        if (redPoints && redPoints.length > 0) {
            clickPoint(redPoints[0].x, redPoints[0].y);
        } else {
            loge("找图、找色都没有命中,等待后重试");
        }
    }
    image.recycle(template);
}

main();

排查速查表:

现象 常见原因 对策
找不到图 目标还没出现 / 模板与画面不一致 / 阈值过高 等目标出现再识别;换新模板;降低 threshold
找错位置 同屏相似元素多 / 阈值过低 提高 threshold;缩小搜索区域;改用多点找色
识别慢 全屏查找 / 频繁手动截图 限定 x,y,ex,ey;用 Ex 系列自动截屏函数
长时间运行内存涨 图片对象没回收 用完立即 image.recycle(img)

无障碍模式下第一次调用 requestScreenCapture 会弹出系统授权,选总是允许。代理模式截图不用这个权限。长时间没人看着跑,用代理模式(图色函数文档)。权限申请之后至少等大约 1 秒再截图。每次都点同一个像素、间隔固定、顺序固定,批量跑的时候容易被当成机器操作。EasyClick 的点击可以落在一块坐标区域里的随机位置(功能特性文档)。找图返回的就是一块区域(Rect),在这块区域里随机取点再点:

// 在目标区域内随机取点再点击,避免每次点击位置完全一致
let x = parseInt(points[0].left + Math.random() * (points[0].right - points[0].left));
let y = parseInt(points[0].top + Math.random() * (points[0].bottom - points[0].top));
clickPoint(x, y);

这篇讲的所有识别与操作都建立在系统官方能力之上,本身合法合规。风险来自使用用途本身。

图像识别 API 速览表,以下函数均出自图色函数文档,名称与参数请以文档为准:

类别 函数 作用
截图权限 image.requestScreenCapture(timeout, type) 申请屏幕截图权限;type:0 自动 / 1 授权 / 2 无需权限(需代理模式)
截图 image.captureScreen / image.captureFullScreen / image.captureFullScreenEx 截取屏幕 / 全屏 / 全屏扩展,返回图片对象
截图 image.captureScreenshot / image.captureScreenSurface 代理模式 SurfaceControl 截图(EC 安卓 12.4.0+)
截图 image.captureToFile 截图保存为 PNG 文件
找图 image.findImage(image, template, …) 模板匹配找图,返回位置区域
找图 image.findImageEx(template, …) 自动截屏找图
找图 image.findImage2(image, template, …) 含缩放的找图,更精准(EC 9.41.0+)
找图 image.findImageByColor(image, template, …) 透明找图,无需初始化 OpenCV
找色 image.findColor(image, color, threshold, …) 单点找色,返回坐标数组
找色 image.findColorEx(color, …) 自动截屏单点找色
找色 image.findMultiColor(image, firstColor, points, …) 多点找色
找色 image.findMultiColorEx(firstColor, points, …) 自动截屏多点找色
比色 image.cmpColor / image.cmpColorEx 单点或多点比色,全部符合返回 true
比色 image.cmpMultiColor / image.cmpMultiColorEx 多组比色,返回命中组索引(-1 为未找到)
找非色 image.findNotColor 查找与指定颜色不相等的点
OpenCV image.initOpenCV() 初始化 OpenCV 类库(找图前调用)
OpenCV image.matchTemplate / image.matchTemplateEx 模板匹配封装(弱/强双阈值)
OpenCV image.useOpencvMat(1) 切换 mat 存储格式,更快更省内存(EC 10.18.0+)
资源管理 image.recycle(img) / image.recycleAllImage() 回收图片,防止内存暴涨

Ex 结尾的函数会自己截屏。J 结尾的函数从 JSON 读参数(findColorJ、findMultiColorJ 等,配置文件由开发工具生成)。

你的场景 推荐手段 理由
游戏画面 / 自绘界面(无控件) 找图 findImageEx + 多点找色 模板匹配定位非标准控件
固定色按钮 / 状态点 单点找色 findColorEx 颜色鲜明,执行最快
图标角标 / 红点 / 复杂图标 多点找色 findMultiColorEx 组合特征抗干扰
判断按钮可点 / 不可点 比色 cmpColorEx 一组点全部符合才命中
血条 / 进度条 找色定位颜色边界,按比例估算 无需完整模板图
目标可能被缩放渲染 findImage2 缩放找图 比 findImage 更精准
需要读取屏幕文字 OCR 识别(PPOCR-V4/V5/V6 全免费、本地离线) 文字类内容用 OCR
需要识别对象(怪物、物品、人物) YOLO 目标检测(ncnn 手机优化,文档) 神经网络定位非文字对象
长时间无人值守运行 代理模式 + 区域内随机点击 代理模式截图无需权限

更完整的识别栈(找图找色 / OCR / YOLO 三级)与运行模式选型看安卓自动化技术栈全景。

FAQ

Q1:找图和找色有什么区别,什么时候用哪个? A:找图基于 OpenCV 模板匹配,识别的是“整张图的样子”,适合特征复杂的目标(图片按钮、图标、游戏画面元素);找色识别的是“颜色特征”,适合颜色鲜明、结构简单的目标(纯色按钮、角标红点、血条端点),执行更快。复杂场景常组合使用。

Q2:OpenCV 图像识别率 95%+ 是什么意思? A:95%+ 是官方宣称的识别率,指常规、清晰、静态界面下的表现。实际效果取决于截图清晰度、模板质量、界面变化程度与阈值设置,识别失败可通过降低阈值、限定区域、多图备选、重试来改善。

Q3:找图的相似度阈值怎么调? A:threshold 是 0~1 的浮点数,默认 0.9。找不到就适当调低(如 0.85、0.8),误识别就调高;weakThreshold(默认 0.7)控制每轮匹配是否继续,一般保持默认即可。

Q4:单点找色和多点找色怎么选? A:单点找色只验证一个点的颜色,遇到大面积同色背景容易误报;多点找色以第一个点颜色为基准,再校验周围若干点的相对位置与颜色,组合特征更唯一、抗干扰更强。图标角标、红点这类场景建议用多点找色。

Q5:图像识别需要 root 吗? A:不需要。截图、识别、点击都基于系统官方能力,在免 root 范围内完成,EasyClick 支持安卓 5.0 及以上的系统。

Q6:找到目标之后怎么点击? A:找图返回位置区域,取中心点或区域内随机点点击;找色返回坐标点数组,取对应 x/y 点击。为降低操作特征,建议点击位置在目标区域内随机化。

Q7:为什么有时候找不到图? A:常见原因:目标还没出现(加载延迟)、模板与实际画面不一致(版本更新、主题变化、缩放)、阈值过高、搜索范围不对。对策:等待目标出现、准备多套模板、降低阈值、限定搜索区域。

Q8:截图需要什么权限? A:无障碍模式下首次调用 requestScreenCapture 会弹出系统授权,选择“总是允许”;代理模式下截图不需要权限,长时间无人值守运行建议用代理模式。申请权限后需等待约 1 秒再截图。

Q9:找图找色慢怎么办? A:把搜索范围限定到目标可能出现的小区域,避免全屏查找;用 Ex 系列自动截屏函数减少重复截图;图片用完及时 recycle;找图前先 initOpenCV;需要极致性能时可用 useOpencvMat 切换 mat 存储格式,速度更快、内存占用更少。

Q10:截图图片为什么要回收? A:截图返回的是内存中的图片对象,不回收会持续占用内存,长时间运行可能内存暴涨。每次用完调用 image.recycle(img) 及时回收即可。


关于 EasyClick:手机自动化脚本开发平台,覆盖安卓免 ROOT、iOS 免越狱、鸿蒙三大手机生态,还提供苹果脚本编写、苹果群控、安卓群控、远程云控、AI 群控手机等。→ 了解全部产品

想要真实跑起来?

本文介绍的方案均可基于 EasyClick 能力在 iEasyClick 落地。官网提供完整文档、开发工具与自动化产品,免费体验。

访问 iEasyClick 官网 →