苹果群控 OCR 找字点击:PaddleOCR V6 四段代码拆解
节点读不到字的时候,用 OCR 读屏幕。中控 10.3.0 起内置 PaddleOCR V6,跑在中控电脑上,不联网,也不占手机性能。下面把整段流程拆成四段:初始化、截屏、找字、点击,每段都贴能跑的代码,省得你对着文档拼。
适用版本:中控 10.3.0+(内置 PP-OCRv6_small),type 为
paddleOcrOnnxV6。 走 USB HID 点击另需手机 iOS 17+;OCR 本身跑在中控电脑上。
第一段:初始化 V6 实例
function createOcrV6() { ocr.releaseAll(); let tocr = ocr.newOcr(); let ok = tocr.initOcr({ "type": "paddleOcrOnnxV6", "numThread": 2, "single": 0, "matMode": 1, "padding": 32, "maxSideLen": 640, "doAngleFlag": 0, "mostAngleFlag": 0 }); if (!ok) { loge("OCR 初始化失败: " + tocr.getErrorMsg()); return null; } return tocr;}这一组是偏快参数,适合正立、清晰的界面截图。single 设 0 的好处是多机场景下每台设备各用一个 OCR 实例,互不打扰;matMode 设 1 是把图片直接在内存里转成 Mat,省内存。日常扫描够用,要更高检测精度再把 maxSideLen 提到 960;画面可能倒置的话,doAngleFlag 和 mostAngleFlag 也要打开。
初始化失败的话,先看中控版本是不是到了 10.3.0,再对着文档核对参数名,别自己猜。
第二段:截屏
function shot() { let img = image.captureFullScreen(); if (!img) { loge("截图失败"); return null; } return img;}走 USB HID 的时候别用这个,改用无自动化截图 image.captureFullScreenNoAuto()——两条链路互斥,同一台设备只能开一条。截完图记得 image.recycle 回收,群控是长跑,图片不回收内存会一直涨。
第三段:找字算中心
function ocrFind(tocr, keyword) { let img = shot(); if (!img) return null;
let result = tocr.ocrImage(img, 30 * 1000, { "padding": 32, "numThread": 2, "maxSideLen": 640, "doAngleFlag": 0, "mostAngleFlag": 0 }); image.recycle(img);
if (!result) { logw("未识别到结果"); return null; } for (let i = 0; i < result.length; i++) { let item = result[i]; if (item.label && item.label.indexOf(keyword) >= 0) { return { x: item.x + item.width / 2, y: item.y + item.height / 2, label: item.label, confidence: item.confidence }; } } logw("没找到关键字: " + keyword); return null;}返回的数组里每一项都有 label、confidence、x、y、width、height,x 和 y 是文字框左上角,中心点就是 x+width/2、y+height/2。
关键字别写成整句。App 的文案常带空格、省略号和前后缀,用 indexOf 做包含匹配比全等稳。同一屏出现多个「确定」的时候,加个区域过滤或者置信度门槛再点,不然容易点错位置。
第四段:点击
function clickByOcr(tocr, keyword) { let hit = ocrFind(tocr, keyword); if (!hit) { logw("没找到: " + keyword); return false; } logd("命中「" + hit.label + "」置信度 " + hit.confidence);
let r = usbHidEvent.clickPoint(hit.x, hit.y); if (r && r !== "") { logw("点击失败: " + r); return false; } return true;}走 USB HID 点之前,先 sessionStart 再 setScreenSize(完整写法见同目录那篇 USB HID 四段代码)。不走 HID 的话,换成你正在用的点击接口,坐标算法一样:得跟当前截图的像素对齐,横竖屏一变就要重新设。
四段拼起来
function main() { let tocr = createOcrV6(); if (!tocr) { exit(); }
let r = usbHidEvent.sessionStart(true); if (r && r !== "") { loge("会话开启失败: " + r); tocr.releaseAll(); exit(); } usbHidEvent.setScreenSize(1170, 2532); // 按机型改
clickByOcr(tocr, "发布"); sleep(800 + Math.floor(Math.random() * 400));
usbHidEvent.sessionStop(); tocr.releaseAll();}
main();顺序就是:初始化 OCR、开会话定屏幕、找字点、收尾释放。实际项目里还要补上失败重试、每步日志和退出前清理,少一样都可能让脚本在无人值守的时候崩掉。
常见问题
PaddleOCR V6 从哪一版中控开始用?
中控 10.3.0 起内置 PP-OCRv6,changelog 写的「新增 PPOCR-V6 文字识别模型以及函数」。低版本没有这个 type。
type 写 paddleOcrOnnxV6 还是别的?
中控侧脚本写 paddleOcrOnnxV6。脱机版 App 在手机上跑 OCR 时 type 是 paddleOnnxOcrV6,名字差一个 Ocr 的位置,别混用。
OCR 要联网吗?
不用。模型在本地,识别跑在中控电脑上,不占手机性能。
V6 和 V5 能同时用吗?
能,文档写的是与 paddleOcrOnnxV5 并存,角度分类 cls 复用 v5 的模型。旧脚本继续挂 V5 没问题。
识得慢怎么办?
用偏快参数:maxSideLen 设 640,方向检测都关成 0。要更高精度再把 maxSideLen 提到 960,画面可能倒置的话再打开方向检测。
多台设备一起跑,OCR 实例怎么配?
init 时 single 设 0,每台设备各用一个实例;CPU 吃紧就降 numThread、错开各机识别节奏。
识别结果支持哪些语言?
中文简繁、英文、日文和多种拉丁文字;西里尔文不支持。
识到字之后点偏了怎么办?
先确认 setScreenSize 和当前截图分辨率一致,转屏后重设;坐标用框中心;USB HID 和代理自动化互斥,只能开一条。
关于我们:EasyClick 做手机自动化脚本开发和群控,覆盖安卓免 ROOT、iOS 免越狱、鸿蒙。USB HID 的完整写法看 苹果群控免签名脚本实战:USB HID 四段代码拆解。