From 5fd0402cd5d964f295701e68c6c27c51268a2cb2 Mon Sep 17 00:00:00 2001 From: TonyJiangWJ Date: Tue, 8 Feb 2022 21:19:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96OCR=E6=8E=A5=E5=8F=A3=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/sample/7zip/7zip压缩.js | 23 +- app/src/main/assets/sample/7zip/rar解压缩.js | 18 +- app/src/main/assets/sample/OCR/OCR.js | 38 ++- app/src/main/assets/sample/OCR/PaddleOCR.js | 18 +- .../assets/sample/OCR/PaddleOCR截图识别.js | 188 ++++++++++ .../model/explorer/ExplorerFileItem.java | 2 +- autojs-aar/paddleocr/src/main/cpp/native.cpp | 6 + .../paddle/lite/ocr/OCRPredictorNative.java | 10 +- .../com/baidu/paddle/lite/ocr/OcrResult.java | 27 +- .../com/baidu/paddle/lite/ocr/Predictor.java | 321 +++--------------- autojs/src/main/assets/modules/__globals__.js | 4 +- .../autojs/core/image/ImageWrapper.java | 6 + .../autojs/rhino/DeleteOnFinalizeFile.java | 3 +- .../autojs/runtime/ScriptRuntime.java | 1 + .../com/stardust/autojs/runtime/api/OCR.java | 44 ++- .../stardust/autojs/runtime/api/SevenZip.java | 12 +- 16 files changed, 371 insertions(+), 350 deletions(-) create mode 100644 app/src/main/assets/sample/OCR/PaddleOCR截图识别.js diff --git a/app/src/main/assets/sample/7zip/7zip压缩.js b/app/src/main/assets/sample/7zip/7zip压缩.js index 7a14499c..154aa35a 100644 --- a/app/src/main/assets/sample/7zip/7zip压缩.js +++ b/app/src/main/assets/sample/7zip/7zip压缩.js @@ -1,19 +1,18 @@ -//目录路径(必须是完整路径) -var dirPath = "/sdcard/脚本/"; -if(!files.isDir(dirPath)) files.create(dirPath); -//压缩文件路径(必须是完整路径) -var filePath = "/sdcard/脚本.7z"; -//压缩类型 -//支持的压缩类型包括:zip 7z bz2 bzip2 tbz2 tbz gz gzip tgz tar wim swm xz txz。 +// 目录路径(必须是完整路径) +var dirPath = files.cwd(); +// 压缩文件路径(必须是完整路径) +var filePath = org.autojs.autojs.Pref.getScriptDirPath() + '/测试.7z'; +// 压缩类型 +// 支持的压缩类型包括:zip 7z bz2 bzip2 tbz2 tbz gz gzip tgz tar wim swm xz txz。 var type = "7z"; -//压缩密码 +// 压缩密码 var password = "password" -//7z加密压缩(若文件已存在则跳过) -//zips.A(type, filePath, dirPath, password) +// 7z加密压缩(若文件已存在则跳过) +// $zips.addFiles(type, filePath, dirPath, password) -//压缩 -switch (zips.A(type, filePath, dirPath)) { +// 压缩 +switch ($zips.addFiles(type, filePath, dirPath)) { case 0: toastLog("压缩成功!文件已保存为: " + filePath) break; diff --git a/app/src/main/assets/sample/7zip/rar解压缩.js b/app/src/main/assets/sample/7zip/rar解压缩.js index f4b4484a..4442d8f2 100644 --- a/app/src/main/assets/sample/7zip/rar解压缩.js +++ b/app/src/main/assets/sample/7zip/rar解压缩.js @@ -1,16 +1,16 @@ -//压缩文件路径(必须是完整路径) +// 压缩文件路径(必须是完整路径) var filePath = files.path("./bonus.rar"); -//目录路径(必须是完整路径) -var dirPath = "/sdcard/脚本"; -//压缩密码 +// 目录路径(必须是完整路径) +var dirPath = org.autojs.autojs.Pref.getScriptDirPath(); +// 压缩密码 var password = "password" -//支持的解压缩类型包括:zip、7z、bz2、bzip2、tbz2、tbz、gz、gzip、tgz、tar、wim、swm、xz、txz以及rar、chm、iso、msi等众多格式。 -//解压无加密的压缩包(若文件已存在则跳过) -//zips.X(filePath, dirPath) +// 支持的解压缩类型包括:zip、7z、bz2、bzip2、tbz2、tbz、gz、gzip、tgz、tar、wim、swm、xz、txz以及rar、chm、iso、msi等众多格式。 +// 解压无加密的压缩包(若文件已存在则跳过) +// $zips.X(filePath, dirPath) -//解压加密的压缩包(若文件已存在则跳过) -switch (zips.X(filePath, dirPath, password)) { +// 解压加密的压缩包(若文件已存在则跳过) +switch ($zips.extraFiles(filePath, dirPath, password)) { case 0: toastLog("解压缩成功!请到 " + dirPath + " 目录下查看。") break; diff --git a/app/src/main/assets/sample/OCR/OCR.js b/app/src/main/assets/sample/OCR/OCR.js index b1d9d174..005a0ef9 100644 --- a/app/src/main/assets/sample/OCR/OCR.js +++ b/app/src/main/assets/sample/OCR/OCR.js @@ -1,19 +1,29 @@ -const img = images.read("./test.png"); -const cpuThreadNum = 4; +const img = images.read("./test.png") +console.show() +let cpuThreadNum = 4 // PaddleOCR 移动端提供了两种模型:ocr_v2_for_cpu与ocr_v2_for_cpu(slim),此选项用于选择加载的模型,默认true使用v2的slim版(速度更快),false使用v2的普通版(准确率更高) -var useSlim = true; +let useSlim = true +let start = new Date() // 识别图片中的文字,返回完整识别信息(兼容百度OCR格式)。 -const result = ocr.R(img, cpuThreadNum, useSlim); -// 可以使用简化的调用命令,默认参数:cpuThreadNum = 4, useSlim = true; -// const result = ocr.R(img); -toastLog("完整识别信息(兼容百度OCR格式): " + JSON.stringify(result)); - -// 识别图片中的文字,只返回文本识别信息(字符串列表)。 -const stringList = ocr.T(img, cpuThreadNum, useSlim); -// 可以使用简化的调用命令,默认参数:cpuThreadNum = 4, useSlim = true; -// const stringList = ocr.T(img); -toastLog("文本识别信息(字符串列表): " + JSON.stringify(stringList)); +let result = $ocr.detect(img, cpuThreadNum, useSlim) +log('slim识别耗时:' + (new Date() - start) + 'ms') +// 可以使用简化的调用命令,默认参数:cpuThreadNum = 4, useSlim = true +// const result = $ocr.detect(img) +toastLog("完整识别信息: " + JSON.stringify(result)) +start = new Date() +// 识别图片中的文字,只返回文本识别信息(字符串列表)。当前版本可能存在文字顺序错乱的问题 建议先使用detect后自行排序 +const stringList = $ocr.recognizeText(img, cpuThreadNum, useSlim) +log('slim纯文本识别耗时:' + (new Date() - start) + 'ms') +// 可以使用简化的调用命令,默认参数:cpuThreadNum = 4, useSlim = true +// const stringList = $ocr.recognizeText(img) +toastLog("文本识别信息(字符串列表): " + JSON.stringify(stringList)) +// 增加线程数 +cpuThreadNum = 8 +start = new Date() +result = $ocr.detect(img, cpuThreadNum, useSlim) +log('8线程识别耗时:' + (new Date() - start) + 'ms') +toastLog("完整识别信息(兼容百度OCR格式): " + JSON.stringify(result)) // 释放模型 用于释放native内存 -ocr.release() +$ocr.release() // 回收图片 img.recycle() diff --git a/app/src/main/assets/sample/OCR/PaddleOCR.js b/app/src/main/assets/sample/OCR/PaddleOCR.js index bef661b0..877f25d8 100644 --- a/app/src/main/assets/sample/OCR/PaddleOCR.js +++ b/app/src/main/assets/sample/OCR/PaddleOCR.js @@ -2,15 +2,21 @@ importClass(com.baidu.paddle.lite.ocr.Predictor) console.show() let path = 'test.jpg' +// 指定是否用精简版模型 速度较快 +let useSlim = false // 创建检测器 let predictor = new Predictor() +// predictor.cpuThreadNum = 4 //可以自定义使用CPU的线程数 // 初始化模型 首次运行时会比较耗时 -let loadSuccess = predictor.init(context) -// 内置的模型只有一个models/ocr_v2_for_cpu,初始化自定义模型请写绝对路径否则无法获取到 -// 使用自定义模型时det rec cls三个模型文件名称需要修改为,后续版本开放自定义文件名 -// ch_ppocr_mobile_v2.0_det_opt.nb -// ch_ppocr_mobile_v2.0_rec_opt.nb -// ch_ppocr_mobile_v2.0_cls_opt.nb +let loadSuccess = predictor.init(context, useSlim) // predictor.init(context) 为默认不使用精简版 +// 内置默认 modelPath 为 models/ocr_v2_for_cpu,初始化自定义模型请写绝对路径否则无法获取到 +// 内置默认 labelPath 为 labels/ppocr_keys_v1.txt +// let modelPath = files.path('./models/customize') // 指定自定义模型路径 +// let labelPath = files.path('./models/customize') // 指定自定义label路径 +// 使用自定义模型时det rec cls三个模型文件名称需要手动指定 +// predictor.detModelFilename = 'ch_ppocr_mobile_v2.0_det_opt.nb' +// predictor.recModelFilename = 'ch_ppocr_mobile_v2.0_rec_opt.nb' +// predictor.clsModelFilename = 'ch_ppocr_mobile_v2.0_cls_opt.nb' // predictor.init(context, modelPath, labelPath) toastLog('加载模型结果:' + loadSuccess) let start = new Date() diff --git a/app/src/main/assets/sample/OCR/PaddleOCR截图识别.js b/app/src/main/assets/sample/OCR/PaddleOCR截图识别.js new file mode 100644 index 00000000..e88e7658 --- /dev/null +++ b/app/src/main/assets/sample/OCR/PaddleOCR截图识别.js @@ -0,0 +1,188 @@ +let currentEngine = engines.myEngine() +let runningEngines = engines.all() +let currentSource = currentEngine.getSource() + '' +if (runningEngines.length > 1) { + runningEngines.forEach(compareEngine => { + let compareSource = compareEngine.getSource() + '' + if (currentEngine.id !== compareEngine.id && compareSource === currentSource) { + // 强制关闭同名的脚本 + compareEngine.forceStop() + } + }) +} + +if (!requestScreenCapture()) { + toastLog('请求截图权限失败') + exit() +} + +sleep(1000) + +importClass(com.baidu.paddle.lite.ocr.Predictor) + +// 指定是否用精简版模型 速度较快 +let useSlim = false +// 创建检测器 +let predictor = new Predictor() +// predictor.cpuThreadNum = 4 //可以自定义使用CPU的线程数 +// 初始化模型 首次运行时会比较耗时 +let loadSuccess = predictor.init(context, useSlim) // predictor.init(context) 为默认不使用精简版 +// 内置默认 modelPath 为 models/ocr_v2_for_cpu,初始化自定义模型请写绝对路径否则无法获取到 +// 内置默认 labelPath 为 labels/ppocr_keys_v1.txt +// let modelPath = files.path('./models/customize') // 指定自定义模型路径 +// let labelPath = files.path('./models/customize') // 指定自定义label路径 +// 使用自定义模型时det rec cls三个模型文件名称需要手动指定 +// predictor.detModelFilename = 'ch_ppocr_mobile_v2.0_det_opt.nb' +// predictor.recModelFilename = 'ch_ppocr_mobile_v2.0_rec_opt.nb' +// predictor.clsModelFilename = 'ch_ppocr_mobile_v2.0_cls_opt.nb' +// predictor.init(context, modelPath, labelPath) +if (!loadSuccess) { + toastLog('初始化ocr失败') + exit() +} +// 识别结果和截图信息 +let result = [] +let img = null +let running = true +let capturing = true + +/** + * 截图并识别OCR文本信息 + */ +function captureAndOcr() { + capturing = true + img && img.recycle() + img = captureScreen() + if (!img) { + toastLog('截图失败') + } + let start = new Date() + result = predictor.runOcr(img.getBitmap()) + toastLog('耗时' + (new Date() - start) + 'ms') + capturing = false +} + +captureAndOcr() + +// 获取状态栏高度 +let offset = -getStatusBarHeightCompat() + +// 绘制识别结果 +let window = floaty.rawWindow( + +); + +// 设置悬浮窗位置 +ui.post(() => { + window.setPosition(0, offset) + window.setSize(device.width, device.height) + window.setTouchable(false) +}) + +// 操作按钮 +let clickButtonWindow = floaty.rawWindow( + +