YYPOST群发软件 发表于 2026-8-20 07:34:37

AIWROK软件本地搭建OCR找字服务器

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 可选 百分比0~100
* @return {String} base64字符串
*/
function ocrScreenshot(region) {
    var img;
    if (region && region.length >= 4) {
      // region是百分比0~100,cutImagePercent用0~1
      var x1 = region / 100;
      var y1 = region / 100;
      var x2 = region / 100;
      var y2 = region / 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(" 返回空响应");
            return null;
      }
      return JSON.parse(resp);
    } catch (e) {
      printl(" 请求失败: " + e);
      return null;
    }
}

/**
* 全量OCR识别
* @param {Array} region 可选 百分比
* @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(" 识别失败: " + (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(" 查找失败: " + (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;
      var sw = screen.getScreenWidth();
      var sh = screen.getScreenHeight();
      var absX, absY;

      if (region && region.length >= 4) {
            var rx1 = Math.round(region * sw / 100);
            var ry1 = Math.round(region * 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(" 找到'" + 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(" 等待'" + 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(" 服务连接正常!");
            printl(" 引擎: " + data.engine);
            printl(" 已加载: " + data.loaded);
            return true;
      }
    } catch (e) {
      printl(" 连接失败: " + e);
      printl(" 请检查: 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.text + " (score=" + words.score + ")");
    }

    // 获取全部文字
    printl("\n--- 全部文字 ---");
    var allText = ocrGetAllText();
    printl(allText);

    // 查找文字
    printl("\n--- 查找文字 ---");
    var found = ocrFindText("设置");
    if (found.length > 0) {
      printl("找到'设置': " + found.x + "," + found.y);
    } else {
      printl("未找到'设置'");
    }

    printl("\n===== 测试完成 =====");
}

// 自动执行测试
main();


页: [1]
查看完整版本: AIWROK软件本地搭建OCR找字服务器