为什么OCR截图,有些内容无法识别?是否有更好的截图OCR识别代码?
第 1 条补充
· 1 个月前
循环OCR识别元素点击,但是切换页面后,第一次还是会识别上一页的元素进行点击对应坐标,有什么办法避免,怎么解决??
第 2 条补充
· 1 个月前
循环及途中,能否能增加截图对比?如果截图一样就继续截图,直到不一样再往下执行,代码怎么写?
回答
OCR识别不成功通常有以下几个原因:
- 图像质量问题:截图模糊、分辨率低或有噪点会影响识别准确率
- 文字对比度不足:文字与背景颜色相近,缺乏足够对比度
- 字体特殊或太小:非常规字体或过小的文字难以被准确识别
- 屏幕刷新问题:截图时界面未完全渲染完成
- OCR引擎限制:OCR技术本身对某些语言、字体或排版支持有限
要提高OCR识别效果,你可以尝试以下改进方案:
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
if (!requestScreenCapture()) {
toastLog('请先授予 Hamibot 屏幕截图权限');
hamibot.exit();
}
// 增加等待时间确保界面稳定
sleep(2000);
// 截取屏幕
var img = captureScreen();
// 如果需要,可以先对特定区域截图提高识别率
// 例如只截取屏幕中央区域 [x, y, width, height]
// var regionImg = images.clip(img, 0, 200, device.width, device.height-400);
// 尝试使用不同的OCR方法
var result = "";
var maxAttempts = 3;
var attempt = 0;
while(attempt < maxAttempts && !result) {
attempt++;
// 优先尝试recognizeText获取纯文本
result = ocr.recognizeText(img);
// 如果结果为空,尝试完整的recognize方法
if(!result) {
var fullResult = ocr.recognize(img);
if(fullResult && fullResult.text) {
result = fullResult.text;
}
}
// 如果仍然没有结果,稍等后重试
if(!result && attempt < maxAttempts) {
sleep(1000);
img = captureScreen();
}
}
if(result) {
toastLog('识别成功,内容: ' + result.substring(0, 30) + (result.length > 30 ? '...' : ''));
log('完整识别结果: ' + result);
} else {
toastLog('多次尝试后仍无法识别文字内容');
// 可以保存问题截图用于分析
var fileName = '/sdcard/hamibot_failed_ocr_' + new Date().getTime() + '.png';
images.save(img, fileName);
log('问题截图已保存至: ' + fileName);
}
img.recycle(); // 释放图片资源
hamibot.exit();
额外建议:
- 对于固定界面的文字识别,可以先截图保存模板,然后使用
findImage定位文字区域再进行OCR - 如果识别率仍然不高,考虑对截图进行预处理(使用images模块调整对比度、二值化等)
- 对于重要信息,可以结合图像识别和OCR,先用
findColor或findImage定位关键区域再进行文字识别 - 复杂场景建议使用Hamibot的付费OCR服务,通常比基础OCR有更高的准确率
OCR技术本身有一定局限性,对于特别重要的场景,建议设计多重验证机制确保自动化流程的可靠性。
补充回答 1
要解决循环OCR识别时切换页面后仍识别上一页元素的问题,关键在于确保每次OCR识别都基于最新的屏幕内容。以下是具体解决方案:
- 强制刷新屏幕截图
在每次循环开始时重新获取屏幕截图,避免使用缓存图像:
// 文档地址 https://docs.hamibot.com/
while(true) {
// 必须每次循环都重新截图
const img = captureScreen();
// 添加页面确认步骤(关键!)
if (!isTargetPage(img)) {
// 等待页面完全切换完成
sleep(800);
continue;
}
// 执行OCR识别
const res = ocr.recognizeText(img);
// ...后续处理
}
// 页面确认函数示例
function isTargetPage(img) {
// 查找新页面特有的文字特征
const pageIndicator = images.findColor(img, "#FF0000", {
threshold: 4,
region: [500, 100, 200, 100]
});
return pageIndicator != null;
}
- 添加双重确认机制
在页面切换操作后添加明确的等待条件:
// 执行页面切换操作后
click(1000, 200);
// 等待切换动画完成
sleep(500);
// 双重确认页面是否已切换
let pageLoaded = false;
for(let i = 0; i < 5; i++) {
const img = captureScreen();
if(images.findColor(img, "#新页面特征色")) {
pageLoaded = true;
break;
}
sleep(300);
}
if(!pageLoaded) {
toastLog("页面切换超时");
hamibot.exit();
}
- 优化循环结构
使用更可靠的循环控制逻辑:
// 文档地址 https://docs.hamibot.com/
function safeOcrLoop() {
while(true) {
// 1. 请求最新截图权限
if(!requestScreenCapture(true)) {
toastLog("截图权限异常");
return;
}
// 2. 获取全新截图(关键:不使用缓存)
const freshImg = captureScreen();
// 3. 验证是否为目标页面
if(!verifyCurrentPage(freshImg)) {
sleep(600); // 给页面切换留出时间
continue;
}
// 4. 执行识别和点击
const res = ocr.recognizeText(freshImg);
// ...处理识别结果
// 5. 点击后强制等待
sleep(300);
}
}
// 页面验证函数(根据你的实际页面特征修改)
function verifyCurrentPage(img) {
// 查找页面特有的标题文字
const title = images.findColor(img, "#333333", {
region: [0, 50, 1080, 100]
});
return title != null;
}
关键要点:
- 每次循环必须调用
captureScreen()获取新截图,不要复用之前的图像对象 - 在OCR识别前添加页面确认步骤,确保当前页面是目标页面
- 页面切换操作后添加
sleep(500)以上等待时间,让界面动画完成 - 使用
requestScreenCapture(true)强制刷新截图权限 - 对于快速切换的页面,建议添加多次确认机制
这样处理后,系统会确保每次OCR识别都是基于最新页面内容,避免误识别上一页元素的问题。
补充回答 2
要实现截图对比功能,在Hamibot中可以通过关键点颜色检测来判断页面是否已切换。以下是完整可靠的解决方案:
// 文档地址 https://docs.hamibot.com/
function waitForPageChange(maxWaitTime = 5000) {
// 获取当前屏幕作为基准
const baseScreen = captureScreen();
// 提取5个具有代表性的关键点(根据你的应用界面调整坐标)
const keyPoints = [
{x: 200, y: 300, color: images.pixel(baseScreen, 200, 300)},
{x: 500, y: 400, color: images.pixel(baseScreen, 500, 400)},
{x: 800, y: 500, color: images.pixel(baseScreen, 800, 500)},
{x: 300, y: 600, color: images.pixel(baseScreen, 300, 600)},
{x: 700, y: 200, color: images.pixel(baseScreen, 700, 200)}
];
const startTime = Date.now();
while (Date.now() - startTime < maxWaitTime) {
const currentScreen = captureScreen();
let screenChanged = false;
// 检查所有关键点是否发生变化
for (const point of keyPoints) {
const currentColor = images.pixel(currentScreen, point.x, point.y);
// 颜色不一致说明页面已变化
if (currentColor !== point.color) {
screenChanged = true;
break;
}
}
if (screenChanged) {
return true; // 页面已切换
}
// 短暂等待后再次检查
sleep(150);
}
return false; // 超时未检测到变化
}
// 使用示例(结合OCR循环)
auto.waitFor();
if (!requestScreenCapture()) {
toastLog('请授予屏幕截图权限');
hamibot.exit();
}
// 执行页面切换操作
click(1000, 500);
sleep(300);
// 等待页面完全切换
if (waitForPageChange(4000)) {
toastLog("页面切换完成,开始OCR识别");
// 执行OCR识别逻辑
const img = captureScreen();
const res = ocr.recognizeText(img);
// ...后续处理
} else {
toastLog("等待页面切换超时");
}
优化建议:
-
关键点选择技巧:
- 选择页面上变化最明显的区域(如标题栏、状态栏)
- 避免选择可能动态变化的区域(如广告、计时器)
- 每个关键点间隔至少200px,确保覆盖不同区域
-
增强版等待函数(适用于复杂场景):
function waitForPageChangeAdvanced(maxWaitTime = 5000, changeThreshold = 3) {
const baseScreen = captureScreen();
const keyPoints = generateKeyPoints(); // 生成20个均匀分布的关键点
const startTime = Date.now();
let unchangedCount = 0;
while (Date.now() - startTime < maxWaitTime) {
const currentScreen = captureScreen();
let changedPoints = 0;
for (const point of keyPoints) {
const baseColor = images.pixel(baseScreen, point.x, point.y);
const currentColor = images.pixel(currentScreen, point.x, point.y);
if (baseColor !== currentColor) {
changedPoints++;
}
}
// 如果超过阈值的关键点变化,认为页面已切换
if (changedPoints > changeThreshold) {
return true;
}
// 连续3次未检测到变化则增加等待时间
unchangedCount = (baseScreen === currentScreen) ? unchangedCount + 1 : 0;
sleep(unchangedCount > 2 ? 300 : 150);
}
return false;
}
// 生成均匀分布的关键点
function generateKeyPoints() {
const points = [];
const width = 1080; // 根据你的设备分辨率调整
const height = 1920;
for (let x = 100; x < width; x += 200) {
for (let y = 100; y < height; y += 200) {
points.push({x, y});
}
}
// 随机打乱顺序
return points.sort(() => Math.random() - 0.5).slice(0, 20);
}
使用注意事项:
- 在页面切换操作后立即调用此函数,不要添加过长的固定sleep
- 关键点坐标需要根据你的具体应用界面调整
- 对于动画过渡较长的页面,适当增加maxWaitTime(建议2000-5000ms)
- 如果页面变化较小(如只更新部分区域),减少changeThreshold值
这种实现方式比单纯使用固定sleep更可靠,能准确检测到页面是否真正完成切换,有效避免识别上一页元素的问题。
ℹ️ 本回答由 AI 生成,内容仅供参考