Autox.js OpenCV 高级图像识别 findMulti 模板匹配相似度计算
从"找到没"到"找到几个、分别在哪"
上一页的 images.findImage() 解决的是"屏幕上有没有这个图"的问题。但实际场景往往更复杂:
- 屏幕上有多个相同的图标,我要全部点一遍
- 我只关心某个区域(比如下半屏幕)里有没有目标
- 我想知道匹配的精确相似度,用来判断"这到底是不是同一个东西"
Autox.js 基于 OpenCV-mobile 4.13.0 提供了更丰富的 API。
多目标查找:findMulti
// 查找屏幕上所有匹配的目标
let results = images.findMulti(img, "coin.png", { threshold: 0.8 });
// results 是一个数组,每个元素是 { x, y, similarity }
results.forEach((r, i) => {
console.log("匹配 " + (i + 1) + ":(" + r.x + "," + r.y + ") 相似度 " + r.similarity);
});
// 全部点击
results.forEach(r => click(r.x, r.y));
这在游戏场景特别有用——比如屏幕上散落多个金币,你想全部收集。
限定搜索区域
默认 findImage 搜索整张屏幕。但很多时候你只关心某个子区域:
// 只在上半屏幕搜索
let region = [0, 0, device.width, device.height / 2];
let result = images.findImage(img, "header_logo.png", { region: region });
// 或者只在右下区域
let region = [device.width * 0.5, device.height * 0.5,
device.width * 0.5, device.height * 0.5];
let result = images.findImage(img, "bottom_right_btn.png", { region: region });
限定区域有两个好处:
- 更快:搜索范围小了,OpenCV 的模板匹配计算量减少
- 更准:避免在无关区域误匹配到相似图案
相似度计算:到底有多像
Autox.js v7 提供了一系列相似度度量函数(受 AutoJs6 启发,v7 合并了这些 API):
| 函数 | 含义 |
|---|---|
images.getSimilarity(img1, img2) | 返回 0~1 的相似度 |
images.psnr(img1, img2) | 峰值信噪比(dB,越大越相似) |
images.mse(img1, img2) | 均方误差(越小越相似) |
images.hist(img1, img2) | 直方图相似度 |
images.ssim(img1, img2) | 结构相似度(越接近 1 越像) |
// 比较两张图到底有多像
let sim = images.getSimilarity(img1, img2);
console.log("相似度:" + (sim * 100).toFixed(1) + "%");
if (sim > 0.9) {
console.log("这基本上是同一张图");
} else if (sim > 0.7) {
console.log("相似但不完全相同");
} else {
console.log("可能不是同一个东西");
}
这些函数在精确判断场景有用——比如"连续截两帧看画面有没有变化"(判断游戏是否加载完成、判断是否跳转到新页面)。
颜色模板
除了纯颜色查找,Autox.js 还支持带颜色范围的模板匹配:
// 创建一个颜色模板
let tmpl = images.createTemplate("/sdcard/脚本/images/btn.png", {
// 只匹配这个颜色范围的像素
colorRange: [colors.parseColor("#FF0000"), colors.parseColor("#FF6666")],
threshold: 0.8
});
let result = images.findImage(img, tmpl);
实战:游戏里的金币自动收集
console.show();
if (!requestScreenCapture()) {
exit("截屏权限失败");
}
// 主循环
while (true) {
let img = captureScreen();
// 在屏幕中间区域找金币
let region = [0, device.height * 0.3, device.width, device.height * 0.6];
let coins = images.findMulti(img, "gold_coin.png", {
threshold: 0.75,
region: region
});
console.log("本帧找到 " + coins.length + " 个金币");
coins.forEach(coin => {
click(coin.x, coin.y);
sleep(300); // 点击间隔
});
img.recycle();
sleep(500);
}
模板图怎么准备
好的模板图是图像识别成功的关键:
原则
- 尽量只框住你要识别的那个元素——去掉周围的背景、边框
- 从目标 App 里直接截——不要从网上找相似图
- 多准备几张——游戏可能有不同状态(发光/不发光、选中/未选中),各截一张
实战技巧
屏幕上有个 "▶ 开始" 按钮
│
├─ 框住按钮,截出来 → start_btn.png
屏幕上有两个状态的同一个按钮
│
├─ 灰色不可点 → start_btn_disabled.png
└─ 高亮可点 → start_btn_enabled.png
脚本里根据场景选哪个模板
总结
| 需求 | 方案 |
|---|---|
| 找单个目标 | images.findImage() |
| 找多个相同目标 | images.findMulti() |
| 限制搜索范围 | { region: [x, y, w, h] } |
| 精确比较两帧 | images.ssim() / images.psnr() |
| 只识别某种颜色的元素 | images.findColor() 或带 colorRange 的模板 |