安卓找图:findImage 与多点找色坐标换算

function main() {
let req = image.requestScreenCapture(10000, 0);
if (!req) {
req = image.requestScreenCapture(10000, 0);
}
if (!req) {
loge("申请截图权限失败");
return;
}
sleep(1000);
let tpl = readResAutoImage("btn.png");
let img = image.captureFullScreen();
if (img != null) {
let result = image.findImage(img, tpl, 0, 0, 0, 0, 0.7, 0.9, 1, 5);
if (result && result.length > 0) {
let r = result[0];
let x = parseInt((r.left + r.right) / 2);
let y = parseInt((r.top + r.bottom) / 2);
logd("相似度 " + r.similarity + " 坐标 " + x + "," + y);
clickPoint(x, y);
} else {
loge("没找到");
}
image.recycle(img);
}
image.recycle(tpl);
}
main();

安卓找图从截图开始,坐标按截图分辨率换算。上面这段是能直接跑的完整流程:申请截图权限、读模板、截全屏、找图、点中心、回收图片。每一步为什么这么写,坐标又是什么时候偏的,分开说清楚。

这段代码在做什么

image.requestScreenCapture(10000, 0) 申请截图权限,第一个参数是超时毫秒。失败再申请一次,两次都失败就别往下走了,多半是后台弹出或悬浮窗权限没给。

申请成功不能马上截图。文档里写得很清楚:权限通过后需要一点时间截图才可用,立刻截可能拿到空图,所以中间 sleep(1000)。机器越差,这个等待越要给足。

readResAutoImage("btn.png") 从工程的 res 目录读模板图。模板要按原图截,别在电脑上二次缩放。

image.captureFullScreen() 截全屏,返回一个图片对象。这个对象用完要 image.recycle(img) 回收,不回收跑久了内存会涨。

image.findImage(...) 在大图里找小图,返回的是 Rect 数组,每个元素带 similarity、left、right、top、bottom。注意它不是点坐标,是一个矩形框,图标的左上角和右下角。点击取中心:

let x = parseInt((r.left + r.right) / 2);
let y = parseInt((r.top + r.bottom) / 2);

findImage 的参数怎么填

签名长这样:

image.findImage(image, template, x, y, ex, ey, weakThreshold, threshold, limit, method)
参数默认值怎么填
weakThreshold0.7每轮匹配的继续门槛,比 threshold 低一点,0.6–0.7
threshold0.9相似度,固定界面用 0.9,有压缩或缩放时 0.8–0.85
limit1只找一个填 1,要找多个填数量
method55 是归一化系数匹配,一般不用改
x/y/ex/ey0全屏找就全填 0;限区域就填起点和终点

返回的 similarity 是实际相似度,日志里打出来看一眼,就知道模板质量怎么样。0.95 以上算稳,0.85 勉强能用,0.8 以下就该换模板了。

找不到的时候,先把返回值和相似度打出来,别急着调 threshold。

多点找色:什么时候比找图省事

按钮是纯色、图标很小、或者界面上有动态文字(标题里带数字、带时间),截模板很麻烦,这时候用找色。找色不认形状,认颜色。

颜色写法是 0x主色-0x偏移,偏移那一半是给颜色波动留的容差:

let img = image.captureFullScreen();
if (img != null) {
let points = image.findMultiColor(
img,
"0xDD7A5F-0x101010",
"29|25|0xBB454B-0x101010,58|44|0xA6363A-0x101010",
0.9, 0, 0, 0, 0, 10, 1
);
if (points && points.length > 0) {
for (let i = 0; i < points.length; i++) {
logd(points[i].x + "," + points[i].y);
clickPoint(points[i].x, points[i].y);
}
}
image.recycle(img);
}

第二个参数是第一个点的颜色,第三个参数是其余点相对第一个点的偏移和颜色,格式 x偏移|y偏移|颜色。点取得越多越准,但每多一个点就多一份计算。

找色返回的是 Point 数组,直接带 x、y,不用自己算中心。阈值 threshold 是 0.0–1.0,纯色按钮 0.9 就够;半透明、渐变的按钮调到 0.8 左右,再低容易点到别的按钮。

还有一组带 Ex 的函数:findImageEx、findColorEx、findMultiColorEx,不用自己截图,传模板或颜色进去,它自动截当前屏幕再找。少写两行代码,也省掉忘记回收的问题。

坐标对不上,查这三处

第一处,区域截图没有加偏移。image.captureScreen(3, x, y, ex, ey) 截的是一块区域,在里面找图,返回的坐标是相对这块区域的。点击前要把起点加回去:

let img = image.captureScreen(3, 100, 200, 400, 500);
if (img != null) {
let result = image.findImage(img, tpl, 0, 0, 0, 0, 0.7, 0.9, 1, 5);
if (result && result.length > 0) {
let x = parseInt((result[0].left + result[0].right) / 2) + 100;
let y = parseInt((result[0].top + result[0].bottom) / 2) + 200;
clickPoint(x, y);
}
image.recycle(img);
}

第二处,分辨率不一致。模板是一台机器截的,换一台屏幕尺寸不同,findImage 的相似度会掉。EC 9.41.0 之后有 image.findImage2,带缩放匹配,比 findImage 稳,多机型混跑的用这个。

第三处,拿到的坐标和点击屏幕不是同一套。查一下 device.getScreenSize() 和截图尺寸对不对得上,对不上说明中间有过缩放。日志里把 left/top/right/bottom 和最终点击坐标一起打出来,偏多少一眼能看出来:

logd("rect " + r.left + "," + r.top + "," + r.right + "," + r.bottom);
logd("click " + x + "," + y + " screen " + device.getScreenSize());

关于我们:EasyClick 做手机自动化脚本开发和群控,覆盖安卓免 ROOT、iOS 免越狱、鸿蒙。图色函数的完整参数见 image-api 文档;找控件的方式见 安卓节点找控件:选择器写法与失效排查。

© 2026 EasyClick · 手机自动化脚本与群控,覆盖安卓免 ROOT、iOS 免越狱、鸿蒙三端。

内容面向合法用途:自动化测试、跨境电商运营与设备管理。