var ocrResult = ocr.recognize(img)和 var ocrResult = images.ocr(img)功能是一样的吗,不一样的话帮我使用 ocr.recognize(img)写一段功能相同的方法
使用ocr.recognize 实现指定区域寻找文字并且点击相应坐标
java.lang.IllegalArgumentException 异常,具体提示为“ x + width must be <= bitmap.width() ”运行代码后出现这个错误
回答
ocr.recognize(img) 和 images.ocr(img) 在功能上都是对图像进行文字识别(OCR),但它们属于不同的模块,调用方式和底层实现略有不同:
images.ocr(img)是images模块提供的快捷 OCR 方法,封装了默认参数,使用简单。ocr.recognize(img)是ocr模块的正式接口,支持更多配置选项,例如指定语言、区域、超时等,更灵活。
如果你希望用 ocr.recognize(img) 实现与 images.ocr(img) 相同的功能,可以按以下方式编写代码。下面是一段兼容 Rhino 1.7.15 的 JavaScript 代码,不使用箭头函数或默认参数:
// 文档地址 https://docs.hamibot.com/
/**
* 使用 ocr.recognize 模拟 images.ocr 的行为
* @param {Image} img - 要识别的图像对象
* @returns {Array} 识别结果数组,每个元素包含 text, x, y, width, height
*/
function ocrImage(img) {
// 设置默认参数以匹配 images.ocr 的行为
var options = {
lang: 'chi_sim+eng', // 默认使用简体中文和英文混合识别(与 images.ocr 保持一致)
timeout: 10000, // 超时时间 10 秒
region: [0, 0, img.width(), img.height()] // 全图识别
};
try {
var result = ocr.recognize(img, options);
if (!result || !result.results) {
return [];
}
// 格式化输出为与 images.ocr 类似的结构
var formatted = [];
result.results.forEach(function(item) {
formatted.push({
text: item.text,
x: item.bounds.left,
y: item.bounds.top,
width: item.bounds.right - item.bounds.left,
height: item.bounds.bottom - item.bounds.top
});
});
return formatted;
} catch (e) {
console.error('OCR 识别失败:', e.message);
return [];
}
}
// 使用示例
var img = captureScreen(); // 获取当前屏幕截图
var ocrResult = ocrImage(img);
ocrResult.forEach(function(block) {
console.log("识别文本: " + block.text);
});
说明:
lang: 'chi_sim+eng':这是images.ocr()内部使用的默认语言模型组合,因此这里显式指定以保证行为一致。region设置为整张图片范围。- 返回结果格式化为包含
text,x,y,width,height的对象数组,与images.ocr(img)输出结构基本一致。 - 添加了异常处理,确保脚本健壮性。
⚠️ 注意:首次使用 OCR 功能需要下载对应的语言包,请确保设备联网且已启用相关权限。
补充回答 1
// 文档地址 https://docs.hamibot.com/
/**
* 在指定区域内查找文本并点击
* @param {string} targetText - 要查找的目标文本
* @param {Array} region - 查找区域 [x, y, width, height]
* @param {number} timeout - 最大等待时间(毫秒)
* @returns {boolean} 是否找到并点击成功
*/
function clickTextInRegion(targetText, region, timeout) {
var startX = region[0] || 0;
var startY = region[1] || 0;
var width = region[2];
var height = region[3];
// 确保屏幕截图
if (!requestScreenCapture()) {
console.error("请求截图失败");
return false;
}
var startTime = new Date().getTime();
while (new Date().getTime() - startTime < timeout) {
var img = captureScreen();
if (!img) {
console.warn("截图获取失败,跳过本次识别");
sleep(1000);
continue;
}
// 裁剪指定区域
var regionImg = images.clip(img, startX, startY, width, height);
// 执行 OCR 识别
try {
var result = ocr.recognize(regionImg, {
lang: 'chi_sim+eng',
timeout: 5000
});
if (result && result.results) {
for (var i = 0; i < result.results.length; i++) {
var item = result.results[i];
var text = item.text.trim();
if (text === targetText) {
// 计算相对于全局屏幕的坐标
var globalX = startX + (item.bounds.left + item.bounds.right) / 2;
var globalY = startY + (item.bounds.top + item.bounds.bottom) / 2;
// 执行点击
click(globalX, globalY);
console.log("已点击文本: " + targetText + " 坐标: (" + globalX + ", " + globalY + ")");
return true;
}
}
}
} catch (e) {
console.error("OCR 识别出错: ", e.message);
}
// 未找到,稍等后重试
sleep(2000);
}
console.log("在超时时间内未找到文本: " + targetText);
return false;
}
// 使用示例:在屏幕中间区域查找“确认”并点击
var region = [500, 1000, 600, 200]; // [x, y, 宽度, 高度]
var found = clickTextInRegion("确认", region, 10000); // 最多等待10秒
if (found) {
console.log("成功点击目标文本");
} else {
console.log("未能找到目标文本");
}
功能说明:
- 该脚本会持续截图并在指定区域内进行 OCR 识别。
- 找到匹配的完整文本后,计算其中心点坐标,并执行点击。
- 支持自定义区域和超时时间,适用于各种自动化场景(如弹窗点击、按钮识别等)。
- 使用
images.clip()裁剪区域以提高识别效率和准确性。
✅ 提示:首次使用需下载语言包,请保持网络畅通。确保已开启无障碍服务和截图权限。
补充回答 2
// 文档地址 https://docs.hamibot.com/
/**
* 安全裁剪图像区域,避免 x + width > bitmap.width() 等越界问题
* @param {Image} img - 原始图像
* @param {number} x - 起始 X 坐标
* @param {number} y - 起始 Y 坐标
* @param {number} w - 宽度
* @param {number} h - 高度
* @returns {Image|null} 裁剪后的图像,如果参数无效则返回 null
*/
function safeClip(img, x, y, w, h) {
var bitmapWidth = img.width();
var bitmapHeight = img.height();
// 修正 x 和 y
if (x < 0) {
w += x; // x 为负时,宽度减少对应部分
x = 0;
}
if (y < 0) {
h += y;
y = 0;
}
// 限制宽度和高度不超过图像边界
if (x >= bitmapWidth || y >= bitmapHeight) {
return null; // 起始点已超出图像范围
}
if (x + w > bitmapWidth) {
w = bitmapWidth - x; // 截断宽度
}
if (y + h > bitmapHeight) {
h = bitmapHeight - y; // 截断高度
}
// 检查裁剪区域是否有效
if (w <= 0 || h <= 0) {
return null;
}
return images.clip(img, x, y, w, h);
}
错误原因说明:
你遇到的 java.lang.IllegalArgumentException: x + width must be <= bitmap.width() 是因为传给 images.clip() 的裁剪区域超出了截图的实际尺寸。例如:
- 屏幕宽度是 1080,但你要从 x=1000 开始裁剪宽度为 200 的区域(1000+200 > 1080),就会触发此异常。
解决方法:
在调用 images.clip 前进行边界检查和修正,使用上面提供的 safeClip 函数替代原生 images.clip。
修改后的 OCR 区域查找示例(集成安全裁剪):
function clickTextInRegionSafe(targetText, region, timeout) {
var startX = region[0];
var startY = region[1];
var width = region[2];
var height = region[3];
if (!requestScreenCapture()) {
console.error("请求截图失败");
return false;
}
var startTime = new Date().getTime();
while (new Date().getTime() - startTime < timeout) {
var img = captureScreen();
if (!img) {
sleep(1000);
continue;
}
// 使用安全裁剪
var regionImg = safeClip(img, startX, startY, width, height);
if (!regionImg) {
console.error("裁剪区域无效,请检查坐标和尺寸是否超出屏幕范围");
return false;
}
try {
var result = ocr.recognize(regionImg, {
lang: 'chi_sim+eng',
timeout: 5000
});
if (result && result.results) {
for (var i = 0; i < result.results.length; i++) {
var item = result.results[i];
if (item.text.trim() === targetText) {
var globalX = startX + (item.bounds.left + item.bounds.right) / 2;
var globalY = startY + (item.bounds.top + item.bounds.bottom) / 2;
click(globalX, globalY);
console.log("点击成功: " + targetText + " at (" + globalX + ", " + globalY + ")");
return true;
}
}
}
} catch (e) {
console.error("OCR识别错误:", e.message);
}
sleep(2000);
}
console.log("未找到文本: " + targetText);
return false;
}
使用建议:
确保你的 region 参数满足:
x >= 0
y >= 0
x + width <= screen_width
y + height <= screen_height
推荐先打印屏幕尺寸做调试:
var s = captureScreen();
console.log("屏幕尺寸: " + s.width() + "x" + s.height());
这样可以避免越界错误。