文字识别后,如何获取坐标,并点击这个按钮
获取到文字位置坐标后转换坐标,如何做
这段代码,为什么点击不了
function ocr_find(txt) {
let res = ocr.recognize(captureScreen());
let index_right = null;
for (var index in res['results']) {
if (res['results'][index]['text'].indexOf(txt) != -1) {
index_right = index;
break;
}
}
if (index_right) {
log(
'"' +
txt +
'"' +
'匹配到文字块:"' +
res['results'][index_right]['text'] +
'"'
);
log(
'该文字块左上角坐标:' +
res['results'][index_right]['bounds']['left'] +
',' +
res['results'][index_right]['bounds']['top']
);
log(
'该文字块右下角坐标:' +
res['results'][index_right]['bounds']['right'] +
',' +
res['results'][index_right]['bounds']['bottom']
);
click(res['results'][index_right]['bounds']['left'],res['results'][index_right]['bounds']['top'],res['results'][index_right]['bounds']['bottom'],res['results'][index_right]['bounds']['right'])
log('原始数据:\n' + JSON.stringify(res['results'][index_right]));
} else log('OCR未找到' + '"' + txt + '"');
}
回答
在 Hamibot 中获取文字识别后的坐标并点击按钮,主要有以下几种方法:
方法一:基于控件识别(推荐)
如果按钮是控件(如 TextView、Button),可以直接通过文本查找并点击:
// 文档地址 https://docs.hamibot.com/
var btn = text("按钮文字").findOne();
btn.click();
方法二:获取控件坐标后点击
如果控件无法直接点击(clickable 为 false),可以获取其中心坐标进行点击:
// 文档地址 https://docs.hamibot.com/
var widget = text("按钮文字").findOne();
var bounds = widget.bounds();
var x = bounds.centerX();
var y = bounds.centerY();
// Android 7.0+ 可用
click(x, y);
// 或有 root 权限时使用
// Tap(x, y);
方法三:纯坐标点击(需注意屏幕适配)
如果需要使用 OCR 文字识别获取坐标,建议:
- 先通过
setScreenMetrics()设置设计分辨率 - 获取到文字位置坐标后转换坐标
- 执行点击操作
// 文档地址 https://docs.hamibot.com/
// 设置设计分辨率(以 1080x1920 为例)
setScreenMetrics(1080, 1920);
// 假设通过 OCR 获取到文字中心坐标为 (500, 800)
var targetX = 500;
var targetY = 800;
// 执行点击
click(targetX, targetY);
sleep(500); // 建议添加适当延迟
注意事项:
- 优先使用控件识别方式,比坐标点击更稳定
- 不同分辨率设备需使用
setScreenMetrics()进行坐标适配 - 点击后建议添加
sleep()等待操作完成 - Android 7.0 以下或需要 root 权限时使用
Tap()函数
如果需要更详细的帮助,可以提供具体的按钮特征和场景信息。
补充回答 1
在Hamibot中,获取文字位置坐标通常通过OCR功能(如ocr.recognizeText())实现,返回的坐标是相对于屏幕左上角的绝对坐标。如果你需要将这些坐标转换为其他坐标系(例如相对于某个控件或窗口),可以通过简单的数学计算来实现。以下是具体步骤和示例:
步骤1: 获取文字位置坐标
使用OCR识别文本,并提取坐标。例如:
// 文档地址 https://docs.hamibot.com/
// 识别屏幕上的文本
let result = ocr.recognizeText(captureScreen(), {
region: [0, 0, device.width, device.height]
});
// 假设result包含文本及其边界框,例如bounds对象
if (result) {
let textX = result.bounds.left; // 文本左上角的X坐标
let textY = result.bounds.top; // 文本左上角的Y坐标
// 其他坐标信息如right、bottom也可用
}
步骤2: 转换坐标
根据你的需求,进行坐标转换。常见场景包括:
- 转换为相对坐标:如果你有一个控件或区域的左上角屏幕坐标(ctrlX, ctrlY),可以将文本坐标转换为相对于该控件的坐标。
- 缩放坐标:如果屏幕分辨率或缩放比例变化,可以应用缩放因子。
示例代码:
// 文档地址 https://docs.hamibot.com/
// 假设控件的屏幕坐标
let ctrlX = 100; // 控件左上角X
let ctrlY = 100; // 控件左上角Y
// 转换文本坐标为相对坐标
let relativeX = textX - ctrlX;
let relativeY = textY - ctrlY;
// 如果需要缩放坐标(例如缩放因子为2)
let scaleFactor = 2;
let scaledX = textX * scaleFactor;
let scaledY = textY * scaleFactor;
// 输出转换后的坐标
console.log("相对坐标:", relativeX, relativeY);
console.log("缩放坐标:", scaledX, scaledY);
注意事项
- 坐标转换基于简单的加减或乘除运算,确保参考点(如控件位置)的坐标准确。
- 如果你在处理图像或画布,可以使用
canvas模块的变换函数(如translate或scale),但这通常用于绘图上下文,而不是直接用于OCR坐标转换。 - 在UI自动化中,坐标通常是屏幕绝对坐标,转换前请确认目标坐标系的原点。
如果你有更具体的转换需求(如旋转或复杂变换),请提供更多细节,我可以进一步协助。
补充回答 2
你的代码中点击不了的原因可能涉及几个方面,包括缺少屏幕截图权限、OCR识别结果的处理问题,以及点击函数的用法不当。下面我将逐一分析并提供改进建议。
主要原因分析:
- 缺少屏幕截图权限:你的代码中使用
captureScreen()进行截图,但在此之前没有请求屏幕截图权限。Hamibot 需要显式请求权限才能捕获屏幕内容。如果没有权限,captureScreen()可能返回空或无效图像,导致 OCR 识别失败。 - OCR识别结果的结构可能不匹配:
ocr.recognize()返回的对象结构可能与你代码中假设的res['results']不一致。Hamibot 的 OCR 模块返回的数据结构可能因版本而异,直接访问results属性可能不正确。 - 点击函数使用不当:你使用了
click(left, top, bottom, right)这个四参数版本,但根据 Hamibot 文档,这个函数通常只用于录制的脚本,在实际代码中可能不可靠。建议使用坐标点击(双参数版本)或计算中心点点击。 - 索引处理问题:你的代码中
index_right初始为null,但循环中如果找到匹配,index_right被设置为索引(字符串类型)。条件if (index_right)可能在某些情况下失败(例如索引为 0 时),因为0在 JavaScript 中被视为 falsy。
改进后的代码:
以下是修改后的代码,添加了权限请求、调整了 OCR 结果处理,并改用中心点点击。同时,我添加了注释以解释关键步骤。
// 文档地址 https://docs.hamibot.com/
// 请求屏幕截图权限和自动化服务
auto.waitFor();
if (!requestScreenCapture()) {
toastLog('没有授予 Hamibot 屏幕截图权限');
hamibot.exit();
}
function ocr_find(txt) {
// 捕获屏幕图像
let img = captureScreen();
if (!img) {
log('截图失败,请检查权限');
return;
}
// 识别文本
let res = ocr.recognize(img);
// 检查识别结果的结构:res 可能是一个对象或数组,具体取决于版本
// 常见结构是 res.results 或直接是数组,建议先打印 res 以确认
// log(JSON.stringify(res)); // 调试时取消注释以查看结构
let foundResult = null;
// 处理识别结果:假设 res 有 results 属性(数组)
if (res && res.results && Array.isArray(res.results)) {
for (let i = 0; i < res.results.length; i++) {
let result = res.results[i];
if (result.text && result.text.indexOf(txt) !== -1) {
foundResult = result;
break;
}
}
} else {
log('OCR识别结果格式异常,请检查OCR模块版本');
return;
}
if (foundResult) {
let bounds = foundResult.bounds;
log('匹配到文字块:"' + foundResult.text + '"');
log('该文字块左上角坐标:' + bounds.left + ',' + bounds.top);
log('该文字块右下角坐标:' + bounds.right + ',' + bounds.bottom);
// 计算文本块的中心点坐标
let centerX = Math.floor((bounds.left + bounds.right) / 2);
let centerY = Math.floor((bounds.top + bounds.bottom) / 2);
// 点击中心点(使用双参数 click)
click(centerX, centerY);
log('点击坐标: ' + centerX + ', ' + centerY);
} else {
log('OCR未找到"' + txt + '"');
}
}
使用示例:
调用 ocr_find("需要点击的文本") 即可。例如:
ocr_find("确定");
注意事项:
- 权限请求:确保在脚本开头请求
auto.waitFor()和requestScreenCapture(),否则截图可能失败。 - OCR结果结构:Hamibot 的
ocr.recognize()返回的结构可能随时间变化。如果上述代码仍不工作,建议先打印res对象(使用log(JSON.stringify(res)))来查看实际结构,并调整代码 accordingly。 - 点击延迟:有时点击需要等待界面稳定。在点击前添加
sleep(500)可能有助于提高可靠性。 - 屏幕旋转:如果屏幕旋转,坐标系统可能变化,确保在正确的屏幕方向下手动处理坐标。
如果问题依旧,请提供更多上下文(如Hamibot版本、OCR识别结果日志),以便进一步排查。