 | |  |  | AIWROK软件本地搭建OCR找字服务器
- /**
- * 轻量OCR识别 - AIWROK端封装
- * 通过frp隧道连接本地电脑的RapidOCR服务
- * 服务器: http://154.201.80.51:9999 → frp → 本地电脑:9999
- *
- * 方法:
- * ocrRecognize(region) 全量识别,返回words数组
- * ocrFindText(text, region, mode) 查找文字,返回坐标
- * ocrFindAndClick(text) 查找文字并点击
- * ocrGetAllText(region) 返回全部文字拼接
- * ocrTextExists(text) 检查文字是否存在
- * ocrWaitAndClick(text, timeout) 等待文字出现并点击
- * testOcrServer() 测试连接
- *
- * Rhino ES5 注意事项:
- * 1. 字符串拼接产生ConsString,传给Java方法前必须用""+强转
- * 2. 每次请求new okHttp(),不要共享实例(setHeader会累积)
- * 3. sleep用sleep.millisecond()不能用sleep(number)
- * 4. 时间用new Date().getTime()不用Date.now()
- * 5. 截图对象用img.toBase64()不用bitmap.compress()
- * 6. 区域截图用cutImagePercent(0~1百分比)不用screen.screenShot像素
- */
- var OCR_CONFIG = {
- // 局域网直连(手机和电脑同一WiFi时用这个,不走frp隧道,快3-5倍)
- SERVER_LOCAL: "http://192.128.10.103:9999",
- // frp隧道(手机不在同一WiFi时用这个,经服务器中转)
- SERVER_REMOTE: "http://165.201.20.51:9999",
- // 当前使用的服务器,自动检测优先用局域网
- SERVER: "http://192.168.10.103:9999",
- timeout: 30000
- };
- /**
- * 截图转base64
- * @param {Array} region 可选 [x1,y1,x2,y2] 百分比0~100
- * @return {String} base64字符串
- */
- function ocrScreenshot(region) {
- var img;
- if (region && region.length >= 4) {
- // region是百分比0~100,cutImagePercent用0~1
- var x1 = region[0] / 100;
- var y1 = region[1] / 100;
- var x2 = region[2] / 100;
- var y2 = region[3] / 100;
- img = screen.screenShotFull().cutImagePercent(x1, y1, x2, y2);
- } else {
- img = screen.screenShotFull();
- }
- if (!img) {
- throw new Error("截图失败");
- }
- // AIWROK Image对象自带toBase64(),返回Java字符串需用""+强转JS字符串
- var b64 = "" + img.toBase64();
- // 释放截图对象
- try { img.recycle(); } catch(e) {}
- return b64;
- }
- /**
- * 发送OCR请求
- * 用http.json()替代http.post(),直接传对象不手动JSON.stringify
- * 这样不会产生ConsString类型问题(已验证http.json()能跑通)
- * @param {String} apiPath 接口路径
- * @param {Object} params 请求参数
- * @return {Object|null} 解析后的JSON
- */
- function ocrRequest(apiPath, params) {
- var http = new okHttp();
- http.setHeader("Content-Type", "application/json");
- try {
- // http.json(url, object) 直接传对象,okHttp内部序列化
- // 参考已验证能跑通的OCR测试_AIWROK端.js第260行
- var resp = "" + http.json(OCR_CONFIG.SERVER + apiPath, params || {});
- if (!resp || resp.length === 0) {
- printl("[OCR] 返回空响应");
- return null;
- }
- return JSON.parse(resp);
- } catch (e) {
- printl("[OCR] 请求失败: " + e);
- return null;
- }
- }
- /**
- * 全量OCR识别
- * @param {Array} region 可选 [x1,y1,x2,y2] 百分比
- * @return {Array} words数组 [{text,score,box}]
- */
- function ocrRecognize(region) {
- var b64 = ocrScreenshot(region);
- var params = { image: b64 };
- if (region) params.region = region;
- var resp = ocrRequest("/ocr", params);
- if (!resp || resp.code != 0) {
- printl("[OCR] 识别失败: " + (resp ? resp.error : "无响应"));
- return [];
- }
- return resp.words || [];
- }
- /**
- * 查找文字
- * @param {String} text 要查找的文字
- * @param {Array} region 可选区域
- * @param {String} mode exact=精确匹配, include=包含匹配
- * @return {Array} 匹配结果 [{text,x,y,score,box}]
- */
- function ocrFindText(text, region, mode) {
- var b64 = ocrScreenshot(region);
- var params = {
- image: b64,
- text: text,
- mode: mode || "include"
- };
- if (region) params.region = region;
- var resp = ocrRequest("/ocr_find", params);
- if (!resp || resp.code != 0) {
- printl("[OCR] 查找失败: " + (resp ? resp.error : "无响应"));
- return [];
- }
- return resp.found || [];
- }
- /**
- * 查找文字并点击
- * @param {String} text 要查找的文字
- * @param {Array} region 可选区域
- * @return {Boolean} 是否点击成功
- */
- function ocrFindAndClick(text, region) {
- var found = ocrFindText(text, region, "include");
- if (found.length > 0) {
- var item = found[0];
- var sw = screen.getScreenWidth();
- var sh = screen.getScreenHeight();
- var absX, absY;
- if (region && region.length >= 4) {
- var rx1 = Math.round(region[0] * sw / 100);
- var ry1 = Math.round(region[1] * sh / 100);
- absX = rx1 + item.x;
- absY = ry1 + item.y;
- } else {
- absX = item.x;
- absY = item.y;
- }
- // 随机偏移±5px拟人化
- absX += Math.floor(Math.random() * 10) - 5;
- absY += Math.floor(Math.random() * 10) - 5;
- printl("[OCR] 找到'" + text + "' 坐标(" + absX + "," + absY + ") 点击");
- auto.clickPoint(absX, absY);
- return true;
- }
- return false;
- }
- /**
- * 获取全部文字
- * @param {Array} region 可选区域
- * @return {String} 全部文字拼接
- */
- function ocrGetAllText(region) {
- var b64 = ocrScreenshot(region);
- var params = { image: b64 };
- if (region) params.region = region;
- var resp = ocrRequest("/ocr_all", params);
- if (!resp || resp.code != 0) {
- return "";
- }
- return resp.all_text || "";
- }
- /**
- * 检查文字是否存在
- * @param {String} text 要检查的文字
- * @param {Array} region 可选区域
- * @return {Boolean}
- */
- function ocrTextExists(text, region) {
- var found = ocrFindText(text, region, "include");
- return found.length > 0;
- }
- /**
- * 等待文字出现并点击
- * @param {String} text 等待的文字
- * @param {Number} timeout 超时秒数
- * @param {Array} region 可选区域
- * @return {Boolean}
- */
- function ocrWaitAndClick(text, timeout, region) {
- var maxTime = (timeout || 10) * 1000;
- var startTime = new Date().getTime();
- while (new Date().getTime() - startTime < maxTime) {
- if (ocrFindAndClick(text, region)) {
- return true;
- }
- sleep.millisecond(1000);
- }
- printl("[OCR] 等待'" + text + "'超时");
- return false;
- }
- /**
- * 测试OCR服务连接
- * @return {Boolean}
- */
- function testOcrServer() {
- try {
- var http = new okHttp();
- var resp = "" + http.get(OCR_CONFIG.SERVER + "/health");
- var data = JSON.parse(resp);
- if (data.code == 0) {
- printl("[OCR] 服务连接正常!");
- printl("[OCR] 引擎: " + data.engine);
- printl("[OCR] 已加载: " + data.loaded);
- return true;
- }
- } catch (e) {
- printl("[OCR] 连接失败: " + e);
- printl("[OCR] 请检查: 1.本地OCR服务是否启动 2.frp客户端是否启动");
- }
- return false;
- }
- // ===== 使用示例 =====
- function main() {
- printl("===== 轻量OCR测试 =====");
- // 测试连接
- if (!testOcrServer()) {
- return;
- }
- // 全量识别
- printl("\n--- 全量识别 ---");
- var words = ocrRecognize();
- for (var i = 0; i < words.length; i++) {
- printl(" [" + i + "] " + words[i].text + " (score=" + words[i].score + ")");
- }
- // 获取全部文字
- printl("\n--- 全部文字 ---");
- var allText = ocrGetAllText();
- printl(allText);
- // 查找文字
- printl("\n--- 查找文字 ---");
- var found = ocrFindText("设置");
- if (found.length > 0) {
- printl("找到'设置': " + found[0].x + "," + found[0].y);
- } else {
- printl("未找到'设置'");
- }
- printl("\n===== 测试完成 =====");
- }
- // 自动执行测试
- main();
复制代码
| |  | |  |
|