找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 13|回复: 1

机器的眼睛多点找色 + 比色守卫

[复制链接]
发表于 半小时前 | 显示全部楼层 |阅读模式
机器的眼睛多点找色 + 比色守卫

QQ截图20261101154022.png


QQ截图20261101154006.png


QQ截图20261101153947.png

  1. /**
  2. * 案例28:机器的眼睛多点找色 + 比色守卫
  3. *
  4. * "机器的眼睛"第四招——比色,四招横评:
  5. *   案例28 多点找色/比色——**连图都不用**,几个"坐标偏移+颜色值"就能定位/判断画面,
  6. *   代价是只认颜色,画面内容大改色就失效——所以它是**最便宜的页面守卫**。
  7. *
  8. * 教学亮点(零素材闭环自证,不需要任何图片文件、不依赖任何 PC 端服务):
  9. *   每轮截屏 → getPointRGB 从**当前画面实时采 5 个点**的颜色 →
  10. *   拼成"0,0,#色 + 4 个偏移色"的颜色指纹 →
  11. *   ① checkColors 拿刚拼的指纹回同一屏比 → 应 true(比色链路自证);
  12. *   ② findMultiColor 拿指纹找色 → 命中中心应≈基点(找色链路自证,偏差报数字);
  13. *   ③ getcolorNum 数一数基点色全屏有多少像素 → 直观演示"取色要取稀有色";
  14. *   ④ 用**上一轮的旧指纹**再比一次 → 没换页应 true,换页后应 false——
  15. *      "旧指纹失效 = 页面变了",这就是游戏脚本里最常用的**比色守卫**原型。
  16. *
  17. * 新知识点:
  18. * 1. img.getPointRGB(x%, y%) 返回 Java int[](RGB,可能带 alpha 共 4 个)——按百分比取色,跨分辨率;
  19. * 2. opencv.checkColors(mat, ['x,y,#RRGGBB',...], 颜色误差, 坐标误差, 相似度) → boolean,
  20. *    多点比色——**实测锤死:坐标是绝对像素位置**(传相对偏移会拿 (0,0)/负坐标去比,必挂):
  21. *    逐个检查"指定位置的颜色对不对",全对 true,有一个不对 false;
  22. * 3. opencv.findMultiColor(mat, 基点String, ['dx,dy,#RRGGBB',...], 偏色阈值, 偏移阈值, 区域%, 相似度)
  23. *    → detect[]——多点找色:和案例27 找图同款 detect,getRealRect() 拿像素坐标。
  24. *    **SDK 文档没给基点格式示例**(实测传纯色串 "#fafafa" 抛 NumberFormatException),
  25. *    本案例用"格式探测":候选格式逐个试,"不抛异常且命中贴近基点"者为正确,探一次记住;
  26. * 4. opencv.getcolorNum(mat, ['#RRGGBB',...], 相似度, [0,0,1,1]) → int——区域内该颜色的像素数量;
  27. * 5. 颜色指纹 = 一串 JS 字符串,可以跨轮存在全局变量里——比"存模板图文件"轻一万倍。
  28. *
  29. * 踩坑预告:
  30. * - **getPointRGB 返回的是 Java 数组**:长度可能是 3(RGB)也可能是 4(ARGB),
  31. *   取下标前先看 length(本案例已做防御,日志会打出原始值验证);
  32. * - **纯色/重复图案区域是找色的老毛病**(案例27 同款):白底上取到 #FFFFFF,
  33. *   findMultiColor 全屏几万个候选点,命中的不一定是你采的那个——所以采点要**散开在内容区**,
  34. *   自检偏差大时打 ⚠ 讲原理,而不是硬报错;
  35. * - 颜色误差太小:截图有损压缩 + 抗锯齿会让同一屏的颜色都有 ±2~8 的抖动,自检直接挂;
  36. *   太大:不同页面也能对上,守卫形同虚设——16 起步;
  37. * - 比色语义是"**这些固定位置的颜色还对不对**"——点位全撞白底时,换页照样全对,
  38. *   守卫就废了;指纹要散开在内容区,采到"页面专属"的颜色组合才有区分度;
  39. * - Mat 和 img 是两笔内存,closeImg + recycle 都要还(案例27 铁律);
  40. * - **文档没示例的新方法参数格式别赌一次到位**:格式探测+打日志试错+全局记住正确格式,
  41. *   是对 SDK"黑盒参数"最省时间的打法(本案例 findMultiColor 基点就这么收的);
  42. * - **findMultiColor 全屏区域 + 纯色背景 = 不抛不崩的"发呆卡死"**(实测锤死):
  43. *   基点色 #fafafa 全屏 750 万像素全当候选点,几十分钟不返回——找色**必须限定小区域**
  44. *   (本案例改成基点±200像素),且长耗时 native 调用**前先打日志**,卡住才知道卡在哪;
  45. */

  46. // ========== 配置区(改这里) ==========
  47. var 比色间隔秒 = 10;              // 每 10 秒一轮:切页→截屏→采色→自检→旧指纹守卫→入库
  48. var 颜色误差 = 16;                // checkColors 颜色误差范围(太小自检挂,太大门卫废,16 起步)
  49. var 坐标误差 = 2;                 // checkColors 坐标误差范围(绝对坐标 ± 像素)
  50. var 比色相似度 = 0.95;            // checkColors 相似度
  51. var 找色偏色阈值 = 16;            // findMultiColor 颜色容差
  52. var 找色偏移阈值 = 3;             // findMultiColor 坐标容差(像素)
  53. var 找色相似度 = 0.9;             // findMultiColor 相似度
  54. var 找色搜索半径 = 200;           // findMultiColor 只在基点±此半径的小框里找——
  55.                                   // 实测锤死:纯色背景全屏找色(基点色几百万像素)不抛不崩,
  56.                                   // 就是几十分钟不返回,日志"发呆"卡死在这
  57. // 采样的 5 个点(百分比坐标):基点在屏幕正中,其余 4 点散在内容区四角——
  58. // 故意避开状态栏(顶 5%)和导航条(底 7%),页面内容变了指纹才变
  59. var 采样点列表 = [
  60.     { 名称: "中心", x: 0.50, y: 0.50 },
  61.     { 名称: "左上", x: 0.15, y: 0.25 },
  62.     { 名称: "右上", x: 0.85, y: 0.25 },
  63.     { 名称: "左下", x: 0.15, y: 0.75 },
  64.     { 名称: "右下", x: 0.85, y: 0.75 }
  65. ];
  66. // 演示页面(只用 openApp 实测能切的,和案例23/27 同款)
  67. var 演示页面列表 = [
  68.     { 名称: "设置",           包名: "com.android.settings" },
  69.     { 名称: "浏览器(百度首页)", 包名: "com.android.browser" }
  70. ];
  71. var 开页等待秒 = 4;
  72. var SQLite路径 = "/sdcard/比色记录.db";
  73. var 表名 = "color_records";

  74. // ========== 全局变量顶部声明 ==========
  75. var gStop = false;
  76. var 数据库连接 = null;
  77. var 数据库可用 = false;
  78. var 累计入库条数 = 0;
  79. var 累计轮数 = 0;
  80. var 上轮指纹 = null;              // 上一轮拼出的颜色指纹(数组),本轮拿来演"旧指纹守卫"
  81. var 基点格式索引 = -1;            // findMultiColor 基点格式探测结果(-1=还没探出来)

  82. // ========== importClass 只能放最外层 ==========
  83. importClass(android.database.sqlite.SQLiteDatabase);
  84. importClass(java.io.File);

  85. // ========== 工具函数(先定义后调用) ==========

  86. function dbConnect() {
  87.     try {
  88.         数据库连接 = SQLiteDatabase.openOrCreateDatabase(new File(SQLite路径), null);
  89.         数据库可用 = true;
  90.         printl("[DB] ✅ SQLite 已打开: " + SQLite路径);
  91.     } catch (e) {
  92.         数据库可用 = false;
  93.         printl("[DB] ⚠ 打开失败(只打印不入库): " + e);
  94.     }
  95. }

  96. function dbEnsureTable() {
  97.     if (!数据库可用) return;
  98.     try {
  99.         var sql = "CREATE TABLE IF NOT EXISTS " + 表名 + " (" +
  100.             "id INTEGER PRIMARY KEY AUTOINCREMENT," +
  101.             "page TEXT, base_color TEXT, hit_count INTEGER, dev_px INTEGER," +
  102.             "color_num INTEGER, self_check INTEGER, collected_at INTEGER)";
  103.         数据库连接.execSQL(sql);
  104.         printl("[DB] ✅ 表已就绪: " + 表名);
  105.     } catch (e) {
  106.         printl("[DB] ⚠ 建表失败: " + e);
  107.         数据库可用 = false;
  108.     }
  109. }

  110. // 一轮比色结果入库(页面/基点色/找色命中数/自检偏差/该色像素数/自检是否通过)
  111. function dbInsertColor(页面名, 基点色, 命中数, 偏差, 色数, 自检过) {
  112.     if (!数据库可用) return false;
  113.     try {
  114.         var stmt = 数据库连接.compileStatement("INSERT INTO " + 表名 +
  115.             " (page, base_color, hit_count, dev_px, color_num, self_check, collected_at) VALUES (?,?,?,?,?,?,?)");
  116.         stmt.bindString(1, "" + 页面名);
  117.         stmt.bindString(2, "" + 基点色);
  118.         stmt.bindLong(3, 命中数);
  119.         stmt.bindLong(4, 偏差);
  120.         stmt.bindLong(5, 色数);
  121.         stmt.bindLong(6, 自检过 ? 1 : 0);
  122.         stmt.bindLong(7, time.nowStamp());
  123.         stmt.executeInsert();
  124.         stmt.close();
  125.         return true;
  126.     } catch (e) {
  127.         printl("[DB] ❌ 入库失败: " + e);
  128.         return false;
  129.     }
  130. }

  131. function dbClose() {
  132.     if (数据库可用 && 数据库连接 != null) {
  133.         try { 数据库连接.close(); } catch (e) {}
  134.         数据库连接 = null;
  135.     }
  136. }

  137. // Java int[] → "#RRGGBB"(防御:长度 4 按 ARGB 取后三位,长度 3 按 RGB)
  138. // ES5 没有 padStart,用 "0"+hex 再 slice(-2) 补零
  139. function rgb转hex(rgb) {
  140.     if (!rgb || rgb.length < 3) return "#000000";
  141.     var r = 0, g = 0, b = 0;
  142.     if (rgb.length >= 4) { r = rgb[1]; g = rgb[2]; b = rgb[3]; }
  143.     else { r = rgb[0]; g = rgb[1]; b = rgb[2]; }
  144.     var hr = ("0" + r.toString(16)).slice(-2);
  145.     var hg = ("0" + g.toString(16)).slice(-2);
  146.     var hb = ("0" + b.toString(16)).slice(-2);
  147.     return "#" + hr + hg + hb;
  148. }

  149. // 打开演示页面(openApp + 校验,同案例27;只用实测能切过去的两个页面)
  150. function 打开页面(页面) {
  151.     try {
  152.         app.openApp(页面.包名);
  153.     } catch (e) {
  154.         printl("🚪 openApp 异常(照常截当前屏): " + e);
  155.         return false;
  156.     }
  157.     printl("🚪 打开【" + 页面.名称 + "】(" + 页面.包名 + "),等待 " + 开页等待秒 + " 秒渲染...");
  158.     sleep.second(秒 = 开页等待秒);
  159.     var 前台 = "" + app.getTopPackName();
  160.     if (前台.indexOf(页面.包名) >= 0) {
  161.         printl("📱 校验通过:前台已是 " + 前台);
  162.         return true;
  163.     }
  164.     printl("⚠ 页面没切过去(前台是 " + 前台 + "),照常截当前屏");
  165.     return false;
  166. }

  167. // 一轮比色:截屏→实时采5点拼指纹→自检比色→自检找色→色数统计→旧指纹守卫→入库
  168. // 返回 false 表示本轮失败(截图/比色异常),主循环跳过
  169. function 比色一轮(页面) {
  170.     var img = null;
  171.     var mat = null;
  172.     try {
  173.         img = screen.screenShotFull();
  174.         if (!img) {
  175.             printl("[比色] ❌ 截图返回空(检查屏幕录制权限)");
  176.             return false;
  177.         }
  178.         // 全屏宽高现在取好(案例27 铁律:凡是算像素坐标,数据在动手前取)
  179.         var 屏宽 = img.getWidth();
  180.         var 屏高 = img.getHeight();
  181.         mat = img.getMat();

  182.         // 步骤1:从这张截图**实时采色**拼指纹(零素材:颜色是从当前画面现取的)
  183.         var 采样们 = [];
  184.         for (var i = 0; i < 采样点列表.length; i++) {
  185.             var pt = 采样点列表[i];
  186.             var rgb = img.getPointRGB(pt.x, pt.y);
  187.             var 色 = rgb转hex(rgb);
  188.             采样们.push({
  189.                 名称: pt.名称, 色: 色,
  190.                 px: Math.round(pt.x * 屏宽), py: Math.round(pt.y * 屏高)
  191.             });
  192.             printl("🎨 采色【" + pt.名称 + "】(" + Math.round(pt.x * 屏宽) + "," +
  193.                 Math.round(pt.y * 屏高) + ") → " + 色 +
  194.                 " | 原始 int[" + rgb.length + "]: " + rgb[0] + "," + rgb[1] + "," + rgb[2]);
  195.         }

  196.         // 步骤2:拼指纹——实测锤死:checkColors 的坐标是**绝对像素位置**(SDK 示例
  197.         // '10,9,#123233' 就是 (10,9) 那个点),传相对偏移会拿 (0,0)/负坐标去比,必挂。
  198.         // 所以比色指纹 = 5 条 "x,y,#色";找色色组仍用 "dx,dy,#色" 相对偏移(基点的偏移)
  199.         var 基点 = 采样们[0];
  200.         var 指纹 = [];
  201.         for (var j = 0; j < 采样们.length; j++) {
  202.             指纹.push(采样们[j].px + "," + 采样们[j].py + "," + 采样们[j].色);
  203.         }
  204.         var 多色 = [];
  205.         for (var k = 1; k < 采样们.length; k++) {
  206.             多色.push((采样们[k].px - 基点.px) + "," + (采样们[k].py - 基点.py) + "," + 采样们[k].色);
  207.         }
  208.         printl("🧬 颜色指纹已拼好: " + 指纹.length + " 个绝对坐标点(基点 " + 基点.色 +
  209.             ") | 找色偏移色组 " + 多色.length + " 条(纯字符串,零图片文件)");

  210.         // 步骤3:比色自检——刚采的指纹回同一屏比,应 true(不通过=链路或阈值有问题)
  211.         var 自检过 = false;
  212.         try {
  213.             自检过 = opencv.checkColors(mat, 指纹, 颜色误差, 坐标误差, 比色相似度);
  214.         } catch (e1) {
  215.             printl("⚠ checkColors 异常: " + e1);
  216.         }
  217.         printl("🔍 比色自检(同屏采同比): " + (自检过 ? "✅ 通过——链路正确" :
  218.             "❌ 未通过——颜色误差 " + 颜色误差 + " 可能太小(截图有损压缩会抖色),调大再试"));

  219.         // 步骤4:找色——SDK 没给基点格式示例(纯色串实测抛 NumberFormatException),
  220.         // 用格式探测:候选格式逐个试,"不抛异常且命中贴近基点"者为正确格式,探到一次就记住,
  221.         // 后续轮直接用记住的格式(命中中心应≈基点,案例27 同款 detect 用 getRealRect)
  222.         var 命中数 = 0;
  223.         var 偏差 = -1;
  224.         var 最佳cx = -1;
  225.         var 最佳cy = -1;
  226.         var 候选 = [
  227.             { 名: "x,y,#色", 基点: 基点.px + "," + 基点.py + "," + 基点.色, 色组: 多色 },
  228.             { 名: "x,y + 色组含0,0", 基点: 基点.px + "," + 基点.py, 色组: ["0,0," + 基点.色].concat(多色) },
  229.             { 名: "hex不带#", 基点: 基点.色.substring(1), 色组: 多色 }
  230.         ];
  231.         // 搜索区域:基点±找色搜索半径的小框(百分比)——实测教训:传 [0,0,1,1] 全屏,
  232.         // 纯色背景上基点色有 750 万个像素,每个都当候选验一遍,findMultiColor 几十分钟不返回
  233.         var 搜索区域 = [
  234.             Math.max(0, (基点.px - 找色搜索半径) / 屏宽),
  235.             Math.max(0, (基点.py - 找色搜索半径) / 屏高),
  236.             Math.min(1, (基点.px + 找色搜索半径) / 屏宽),
  237.             Math.min(1, (基点.py + 找色搜索半径) / 屏高)
  238.         ];
  239.         for (var c = 0; c < 候选.length; c++) {
  240.             if (基点格式索引 >= 0 && c !== 基点格式索引) continue;
  241.             // 调用前先打日志:再出现"卡住不动",最后一条 🧪 就是卡死的格式
  242.             printl("🧪 findMultiColor 调用中:格式 [" + 候选[c].名 + "]" +
  243.                 (基点格式索引 < 0 ? "(探测)" : "(记住的格式)") + " 区域±" + 找色搜索半径 + "像素...");
  244.             try {
  245.                 var 开始 = time.nowStamp();
  246.                 var 命中们 = opencv.findMultiColor(mat, 候选[c].基点, 候选[c].色组, 找色偏色阈值, 找色偏移阈值, 搜索区域, 找色相似度);
  247.                 var 耗时 = time.nowStamp() - 开始;
  248.                 var n = 命中们 == null ? 0 : 命中们.length;
  249.                 var bd = 999999999;
  250.                 var bx = -1;
  251.                 var by = -1;
  252.                 for (var m = 0; m < n; m++) {
  253.                     var 矩形 = 命中们[m].getRealRect();
  254.                     var dev = Math.round(Math.sqrt(Math.pow(矩形.getCenterX() - 基点.px, 2) + Math.pow(矩形.getCenterY() - 基点.py, 2)));
  255.                     if (dev < bd) {
  256.                         bd = dev;
  257.                         bx = 矩形.getCenterX();
  258.                         by = 矩形.getCenterY();
  259.                     }
  260.                 }
  261.                 if (n > 0 && bd <= 8) {
  262.                     命中数 = n;
  263.                     偏差 = bd;
  264.                     最佳cx = bx;
  265.                     最佳cy = by;
  266.                     if (基点格式索引 < 0) {
  267.                         基点格式索引 = c;
  268.                         printl("🧪 findMultiColor 基点格式探测成功: [" + 候选[c].名 + "](已记住,后续轮直接用)");
  269.                     }
  270.                     printl("🎯 找色命中 " + 命中数 + " 处(耗时 " + 耗时 + " 毫秒) | 最贴合中心 (" +
  271.                         最佳cx + "," + 最佳cy + ") | 距基点偏差 " + 偏差 + " 像素 ✅ 链路正确");
  272.                 } else if (基点格式索引 < 0) {
  273.                     printl("🧪 基点格式 [" + 候选[c].名 + "] 未抛异常但命中 " + n +
  274.                         (n > 0 ? " (最小偏差 " + bd + " 像素,不贴合基点,试下一种)" : "(试下一种)"));
  275.                 } else {
  276.                     printl("🎯 找色 0 命中/偏差 " + (bd > 999999 ? "-" : bd) + " 像素——记住格式 [" + 候选[c].名 +
  277.                         "] 下没找到贴近基点的命中:基点色 " + 基点.色 + " 撞纯色区歧义(案例27 同款)或偏色阈值太严");
  278.                 }
  279.             } catch (e2) {
  280.                 if (基点格式索引 < 0) {
  281.                     printl("🧪 基点格式 [" + 候选[c].名 + "] 抛异常: " + e2);
  282.                 } else {
  283.                     printl("⚠ findMultiColor 异常: " + e2);
  284.                 }
  285.             }
  286.         }
  287.         if (基点格式索引 < 0 && 偏差 < 0) {
  288.             printl("🎯 找色三种基点格式都没立住(见上面 🧪 日志)——把 🧪 行原样贴回来定位");
  289.         }

  290.         // 步骤5:色数统计——基点色全屏有多少像素?教学:稀有色才配当指纹
  291.         var 色数 = -1;
  292.         try {
  293.             色数 = opencv.getcolorNum(mat, [基点.色], 0.9, [0, 0, 1, 1]);
  294.             printl("📊 基点色 " + 基点.色 + " 全屏像素数: " + 色数 +
  295.                 (色数 > 20000 ? " ⚠ 太常见(白/黑/灰底),换内容区边缘点当指纹更独特" : " ✅ 够稀有,适合当指纹"));
  296.         } catch (e3) {
  297.             printl("⚠ getcolorNum 异常: " + e3);
  298.         }

  299.         // 步骤6:旧指纹守卫——拿上一轮的指纹比今天的屏:
  300.         // 没换页应 true;换页后应 false(旧颜色组合在新页面凑不齐)= 检测到页面变化
  301.         if (上轮指纹 != null) {
  302.             var 旧过 = false;
  303.             try {
  304.                 旧过 = opencv.checkColors(mat, 上轮指纹, 颜色误差, 坐标误差, 比色相似度);
  305.             } catch (e4) {
  306.                 printl("⚠ 旧指纹比色异常: " + e4);
  307.             }
  308.             printl("🛡 旧指纹(上一轮拼的)比色: " + (旧过 ?
  309.                 "仍通过——没换页属正常;若已换页还通过,说明指纹点位太集中/全撞白底,守卫不够独特" :
  310.                 "失效 ✅ 页面已变化——这就是游戏脚本里最便宜的『比色守卫』:几个字符串就判断出画面变了没"));
  311.         } else {
  312.             printl("🛡 首轮没有旧指纹可比(下轮开始演示守卫)");
  313.         }
  314.         上轮指纹 = 指纹;

  315.         // 入库:本轮全链路结果(比色守卫要留痕,事后 SQL 复盘哪一轮页面变的)
  316.         if (dbInsertColor(页面.名称, 基点.色, 命中数, 偏差, 色数, 自检过)) {
  317.             累计入库条数++;
  318.             printl("💾 已入库 [" + 累计入库条数 + "] 页面:" + 页面.名称 +
  319.                 " | 基点:" + 基点.色 + " | 自检:" + (自检过 ? "过" : "挂"));
  320.         }
  321.         return true;
  322.     } catch (e) {
  323.         printl("[比色] ❌ 本轮异常: " + e);
  324.         return false;
  325.     } finally {
  326.         // 两笔内存都要还:Mat 用 opencv.closeImg,image 用 recycle(案例27 铁律)
  327.         try { if (mat != null) opencv.closeImg(mat); } catch (ea) {}
  328.         try { if (img != null) img.recycle(); } catch (eb) {}
  329.     }
  330. }

  331. // ========== 主流程 ==========
  332. printl("===== 案例28 多点找色 + 比色守卫 启动 =====");
  333. dbConnect();
  334. dbEnsureTable();
  335. printl("⚙ 配置:每 " + 比色间隔秒 + " 秒一轮 · 颜色误差 " + 颜色误差 + " · 采样点 " +
  336.     采样点列表.length + " 个 · 库: " + SQLite路径);
  337. printl("ℹ 机器眼睛四选一:OCR(20,慢/只有字) | 控件树(23,快/读不到游戏) | 模板找图(27,准/要备图) | 比色(本案例,连图都不要,几个字符串当指纹)");
  338. printl("ℹ 零素材闭环:颜色从当前画面现采现拼→同屏自检比色应真→找色偏差≈0→旧指纹在新页面失效=检测到换页");

  339. // 停止按钮清理(顺序:先置标志,stopAllRuning 放最后)
  340. event.onStopBtnEvent(function () {
  341.     gStop = true;
  342.     dbClose();
  343.     runTime.stopAllRuning();
  344. });

  345. // 主循环:切页(每 2 轮一次)→ 比色一轮 → 分片等待
  346. var 页面索引 = 0;
  347. var 当前页面 = 演示页面列表[0];
  348. while (!gStop) {
  349.     累计轮数++;

  350.     // 每 2 轮换一次页面:正好演示"上一轮指纹拿到新页面比色→失效"
  351.     if ((累计轮数 - 1) % 2 === 0) {
  352.         当前页面 = 演示页面列表[页面索引 % 演示页面列表.length];
  353.         页面索引++;
  354.         printl("\n---- 第 " + 累计轮数 + " 轮:切页【" + 当前页面.名称 + "】----");
  355.         打开页面(当前页面);
  356.     } else {
  357.         printl("\n---- 第 " + 累计轮数 + " 轮:页面不变【" + 当前页面.名称 + "】----");
  358.     }

  359.     var ok = 比色一轮(当前页面);
  360.     if (!ok) {
  361.         printl("⚠ 本轮比色失败,跳过(下轮继续)");
  362.     }

  363.     var 剩余 = 比色间隔秒;
  364.     while (剩余 > 0 && !gStop) {
  365.         var 步长 = 剩余 >= 5 ? 5 : 剩余;
  366.         printl("⏳ 等待下一轮...剩余 " + 剩余 + " 秒(累计 " + 累计轮数 + " 轮/入库 " + 累计入库条数 + " 条)");
  367.         sleep.second(秒 = 步长);
  368.         剩余 = 剩余 - 步长;
  369.     }
  370. }

  371. dbClose();
  372. printl("===== 流程结束:共 " + 累计轮数 + " 轮,入库 " + 累计入库条数 + " 条,库: " + SQLite路径 + " =====");
复制代码


0

主题

1

回帖

2

积分

软件网站新手

积分
2
发表于 半小时前 | 显示全部楼层

机器的眼睛多点找色 + 比色守卫

看了下图,这个多点找色+比色守卫的思路挺聪明的,不用依赖图片文件,直接从当前画面实时采样。那这个方案能适应哪些场景呢?比如说,如果画面背景改变了,会不会影响它的准确性?还有,这个坐标偏移是固定的吗?还是可以根据需要调整的?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|

GMT+8, 2026-11-2 07:30

安卓脚本软件 · 键鼠盒子 · HID · 机械臂

快速回复 返回顶部 返回列表

随机推荐 · 热帖 / 新帖 / 随便看看

社区会员(随机展示)