为什么我的代码中,images.findImage()找不到图片?
我十分确认我加载的图片很小,很精准,在截图中具有独特性,唯一性,干扰少。但是无论threshold为多少都find不到image,而且加载的图片都是有效的,我通过images.save()到指定目录也没有问题,图片正确加载,按照预期。我的问题是images.findImage()函数,似乎没有按照我的期望从大图中找到图片,功能失效?每次都是返回null。但是我记得第一次测试的时候是返回过坐标的,成功过,但是现在我不知道哪里有问题
我的代码如下:
if (!requestScreenCapture()) {
toastLog('没有授予 Hamibot 屏幕截图权限');
hamibot.exit();
}
console.show()
toast("start")
let i = images.read(files.cwd() + "/to_pic.png")
console.log("加载图片完成")
// images.save(i, files.cwd() + "/to_pic.png")
console.log(i)
sleep(2000)
// let sc = images.captureScreen()
sleep(500)
console.log("截图完成")
// images.save(sc, files.cwd() + "/sc.png")
// console.log("sc ok")
let ret = images.findImage(images.captureScreen(), i)
sleep(1000)
console.log("找图完成")
console.log(ret)
setTimeout(()=>{
console.log("end")
}, 50000)
回答
文档地址 https://docs.hamibot.com/
你遇到的问题 images.findImage() 返回 null,即使图片有效、截图正常、找图逻辑看似正确,这是一个常见但容易被忽略细节的问题。下面我将从多个角度分析并给出解决方案。
✅ 1. 确认截图权限已正确获取
虽然你调用了 requestScreenCapture(),但它返回 true 并不代表当前帧的截图是有效的。
你需要确保:
- 调用
requestScreenCapture()后,至少等待 1 秒以上再进行captureScreen()。 - 不要在请求权限后立即截图,否则可能返回空或黑屏图像。
你的代码中用了 sleep(500) 是可以接受的,但建议改为 sleep(1000) 更稳妥。
✅ 2. 避免重复使用同一张模板图导致颜色通道问题
一个非常隐蔽的问题是:如果你多次用 images.read() 加载同一张 PNG 图片(尤其是带透明通道的),在某些设备上会因为 ARGB 与 RGB 格式不匹配而导致找图失败。
🔍 原因分析:
captureScreen()返回的是 RGB 565 或 RGBA_8888 的屏幕截图。- 如果你的模板图
to_pic.png是带透明通道的 PNG,在解码时可能是ARGB格式。 - 找图算法对 Alpha 通道敏感,如果模板图有透明像素,而屏幕上实际显示为不透明背景,则无法匹配。
✅ 解决方案:
将模板图强制转换为与屏幕一致的颜色格式(通常是 RGB 565):
// 文档地址 https://docs.hamibot.com/
if (!requestScreenCapture()) {
toastLog('没有授予 Hamibot 屏幕截图权限');
hamibot.exit();
}
console.show();
toast("start");
// 正确加载并标准化模板图
let i = images.read(files.cwd() + "/to_pic.png");
if (!i) {
console.error("模板图读取失败");
exit();
}
// 关键步骤:将模板图转换为 RGB565,去除 alpha 通道干扰
i = images.cvtColor(i, "RGBA", "RGB");
i = images.cvtColor(i, "RGB", "RGB565");
console.log("加载并转换模板图完成");
sleep(1000); // 等待稳定
// 截图
let sc = captureScreen();
if (!sc) {
console.error("截图失败");
exit();
}
console.log("截图完成");
// 执行找图,设置合理的阈值
let ret = images.findImage(sc, i, {
threshold: 0.9,
});
console.log("找图完成");
console.log(ret);
if (ret) {
toastLog("找到目标位置: " + ret);
} else {
toastLog("未找到目标图片");
}
setTimeout(() => {
console.log("end");
}, 50000);
✅ 3. 检查模板图是否真的“完全一致”
即使你觉得图片“很小、精准、独特”,也要注意以下几点:
| 检查项 | 说明 |
|---|---|
| 缩放问题 | 手机系统设置了“显示大小”?比如字体变大/屏幕缩放,会导致 UI 元素尺寸变化,使模板图比例不符。 |
| 分辨率适配 | 模板图是在 A 设备截的,在 B 设备上运行?不同分辨率下图标位置和大小不同。 |
| 动态变化 | 是否是按钮按下状态、高亮、阴影等细微变化?这些都会影响像素匹配。 |
| 抗锯齿/渲染差异 | Android 渲染机制可能导致相同图标每次显示略有像素级差异。 |
✅ 最佳实践:
- 在当前设备上直接截取模板区域作为训练图。
- 使用
images.clip()从截图中裁剪出你要找的小图保存为模板,而不是从别的设备拷贝过来。
例如:
// 临时调试:先手动截图一次,裁剪保存模板
auto.waitFor();
home(); // 回到桌面
sleep(2000);
let img = captureScreen();
images.save(img, files.cwd() + "/debug_screen.png"); // 保存当前屏幕用于调试
// 假设你知道微信图标在 (500, 800),宽高 120x120
let wxIcon = images.clip(img, 500, 800, 120, 120);
images.save(wxIcon, files.cwd() + "/to_pic.png");
toast