道无涯的AutojsPro文字识别插件(PP-OCRv3)使用教程

引言

  • 本插件是基于百度EasyEdge开发的AutojsPro插件,插件 完全免费
  • 已在安卓13、安卓14机型测试,目前没发现有啥问题
  • 插件最新版 已支持 雷电9模拟器,其它模拟器和云机自行测试,原则上讲同样适配
  • 若需定制脚本请移步 软件|源码定制
  • 插件提供了两个架构:armeabi-v7a arm64-v8a

QQ交流群

Autojs、按键精灵、易语言、懒人精灵等自动化编程学习交流,知识探讨,共同进步!欢迎萌新与大佬们的加入!

自动化编程学习交流群:606759894

插件界面

插件下载

注:如果用手机浏览器打开的话会显示非会员无法浏览,去浏览器的设置里把浏览器标识设置为桌面端再打开就行了!

蓝奏云网盘:点我跳转下载页(密码:aup0)

对接视频教程(附实战)

待录制...估计2024.11.5前录制

识别模型

插件提供了两个OCR识别模型:

  • PP-OCRv3(精度高)
    检测模块基于DB算法优化,识别模型基于文本识别算法SVTR,并对其进行产业适配,模型大小为15.6M。
  • PP-OCRv3-tiny(速度快)
    PP-OCRv3模型的量化版本,在稍微精度损失的条件下,模型压缩到6M。

关于报错的解决办法

这是没选好对应插件架构的问题

详细报错如下:

Wrapped com.stardust.autojs.core.plugin.Plugin$PluginLoadException:
com.stardust.autojs.core.plugin.Plugin$PluginLoadException: 
java.lang.UnsatisfiedLinkError: dlopen failed: 
"/data/app/com.daowuya.ppocrv3-nslAuNQgs_svQInvH0Vghw==/lib/arm/libdwynbProtect.so" is 32-bit instead of 64-bit

解决方式:

  • 如果是调试时报错,换另一个架构的插件就行了
  • 如果是打包后报错,强烈建议aj打包界面的CPU结构选项不要选择armeabi-v7a,arm64-v8a,建议单独选一个就好了,选的是哪个就对应使用哪个架构的插件。

为啥呢?因为可能出现某些情况:例如如果两个架构都勾选,有些模拟器可能使用脚本的v7a架构,但却使用插件的v8架构,这样就触发了上面的报错了!

Autojs对接代码

插件JSON返回示例

  • text:识别到的文本
  • region:文本所在范围:左上角x,左上角y,右上角x,右上角y
  • confidence:置信度
[
  { text: '道无涯',
    region: [173, 666, 302, 1133],
    confidence: 0.91
  },
  { text: '插件',
    region: [298, 674, 1161, 1076],
    confidence: 0.94
  }
]

读取本地图片进行识别

/***
 * 作者: 道无涯i,脚本定制联系:daowuya02
 * 日期: 2024-10-1 15:21:29
 * 描述: 读取本地图片进行OCR识别代码示例
 * 必填参数1:imagePath,图片路径
 * 必填参数2:confidence,识别置信度
 */

// 加载插件,只需要加载一次
var ppOCR = $plugins.load("com.daowuya.ppocrv3");
// 是否加载PP-OCRv3-tiny量化模型,true为加载;否则默认加载PP-OCRv3模型
var tiny = false
//初始化,加载模型,只需要加载一次
ppOCR.init(tiny)

var imagePath = "/storage/emulated/0/daowuya.png"
var confidence = 0.3

var ocr_image = null
ocr_image = images.read(imagePath)
var result = ppOCR.ocr(ocr_image.bitmap, confidence)
console.log(result)

// 识别完回收图片,防止内存泄漏
ocr_image.recycle()
ocr_image = null

events.on("exit", function () {
    //脚本退出或者不需要识别时调用,卸载模型,释放内存
    ppOCR.exit()
    if(ocr_image){
        ocr_image.recycle()
    }
});

实时截屏识别并绘制

/***
 * 作者: 道无涯i,脚本定制联系:daowuya02
 * 日期: 2024-10-1 15:21:29
 * 描述: 实时截屏进行OCR识别代码示例
 * 必填参数:confidence,识别置信度
 * 注意:使用下面代码前,请在根目录创建drawFloaty.js,并将文章文末的【附录:drawFloaty.js】内容黏贴并保存
 */

// 加载插件,只需要加载一次
var ppOCR = $plugins.load("com.daowuya.ppocrv3");
// 是否加载PP-OCRv3-tiny量化模型,true为加载;否则默认加载PP-OCRv3模型
var tiny = false
//初始化,加载模型,只需要加载一次
ppOCR.init(tiny)

// 绘制初始化
var drawFloaty = require('./drawFloaty.js');
drawFloaty.init({
    statusBarHeight: drawFloaty.getStatusBarHeight()
});

var capture = null
events.on("exit", function () {
    //脚本退出或者不需要识别时调用,卸载模型,释放内存
    ppOCR.exit()
    if(capture){
        capture.recycle()
    }
});

var confidence = 0.3
while (true) {
    capture = $automator.takeScreenshot();
    // // 如果需要裁剪的话
    // capture = images.clip(capture, left, top, w, h);
    var result = ppOCR.ocr(capture.bitmap, confidence)
    var bbox = []
    for (let i = 0; i < result.length; i++) {
        bbox.push({
            region: result[i].region,
            text: result[i].text
        })
    }
    drawFloaty.draw(bbox, 500);
    console.log(`\n本次共识别到${result.length}个结果`)
    capture.recycle()
    capture = null
    sleep(1000);
}

附录:drawFloaty.js

实时绘制代码,本代码来自群聊 webpack-autojs 群文件,最新代码优化自 Ling

let drawFloaty = {
    instance: null,
    toDraw: [],
    option: {
        statusBarHeight: 0
    },

    getStatusBarHeight() {
        let resources = context.getResources();
        let resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        let height = resources.getDimensionPixelSize(resourceId);
        return height;
    },
    init(option) {
        if (!!this.instance) return;
        this.option.statusBarHeight = option.statusBarHeight || 0;

        this.instance = floaty.rawWindow(
            <frame id="frame">
                <canvas id="board" />
            </frame>
        );

        ui.run(() => {
            this.instance.frame.getRootView().getLayoutParams().alpha = 0.8; // alpha设置0.8,在安卓12以上实现悬浮窗穿透
            this.instance.setTouchable(false);
            this.instance.setSize(-1, -1);
        });

        // 绘制区域 描边
        let paintRect = new Paint();
        paintRect.setStyle(Paint.Style.STROKE); // 设置画笔样式,描边
        paintRect.setAntiAlias(false); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintRect.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintRect.setStrokeWidth(10); // 设置画笔宽度
        paintRect.setARGB(204, 255, 48, 48); // 设置画笔透明度和颜色

        // 绘制区域 填充内部和描边
        let paintRect2 = new Paint();
        paintRect2.setStyle(Paint.Style.FILL_AND_STROKE); // 设置画笔样式,填充内部和描边
        paintRect2.setAntiAlias(false); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintRect2.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintRect2.setStrokeWidth(10); // 设置画笔宽度
        paintRect2.setARGB(204, 255, 48, 48); // 设置画笔透明度和颜色

        // 绘制文字 填充内部
        let paintText = new Paint();
        paintText.setStyle(Paint.Style.FILL); // 设置画笔样式,填充内部
        paintText.setAntiAlias(true); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintText.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintText.setFakeBoldText(false); // 模拟实现粗体文字,设置在小字体上效果会非常差 
        paintText.setTextSize(32); // 设置字体大小,必须大于0
        paintText.setARGB(255, 255, 255, 255); // 设置画笔透明度和颜色

        // 参数为 LAYER_TYPE_SOFTWARE 时,使用软件来绘制 View Layer,绘制到一个 Bitmap,并顺便关闭硬件加速;
        // 参数为 LAYER_TYPE_HARDWARE 时,使用 GPU 来绘制 View Layer,绘制到一个 OpenGL texture(如果硬件加速关闭,那么行为和 VIEW_TYPE_SOFTWARE 一致)
        // 参数为 LAYER_TYPE_NONE 时,关闭 View Layer。 View Layer 可以加速无 invalidate() 时的刷新效率,但对于需要调用 invalidate() 的刷新无法加速。
        this.instance.board.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);

        this.instance.board.on("draw", canvas => {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);

            let now = Date.now();
            let toDraw = this.toDraw || [];
            toDraw.forEach((item, i) => {
                if (item && now >= item.old) {
                    this.toDraw.splice(i, 1);
                    return;
                }

                canvas.drawRect(item.region[0], item.region[1], item.region[2], item.region[3], paintRect);
                if (item.text) {
                    let textWidth = paintText.measureText(item.text);
                    canvas.drawRect(item.region[0], item.region[1] - 38, item.region[0] + textWidth + 10, item.region[1], paintRect2);
                    canvas.drawText(item.text, item.region[0] + 6, item.region[1] - 8, paintText);
                }
            });
        });
    },
    draw(arr, time) {
        if (arr.length == 0) return;
        arr.forEach(item => {
            item.region[1] = item.region[1] - this.option.statusBarHeight;
            item.region[3] = item.region[3] - this.option.statusBarHeight;
            item.old = Date.now() + (time || 500);
        })
        this.toDraw = arr
        // this.toDraw = this.toDraw.concat(arr);
    },
    drawImg(arr, image, path) {
        // 绘制区域 描边
        let paintRect = new Paint();
        paintRect.setStyle(Paint.Style.STROKE); // 设置画笔样式,描边
        paintRect.setAntiAlias(false); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintRect.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintRect.setStrokeWidth(4); // 设置画笔宽度
        paintRect.setARGB(153, 255, 48, 48); // 设置画笔透明度和颜色

        // 绘制区域 填充内部和描边
        let paintRect2 = new Paint();
        paintRect2.setStyle(Paint.Style.FILL_AND_STROKE); // 设置画笔样式,填充内部和描边
        paintRect2.setAntiAlias(false); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintRect2.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintRect2.setStrokeWidth(4); // 设置画笔宽度
        paintRect2.setARGB(153, 255, 48, 48); // 设置画笔透明度和颜色

        // 绘制文字 填充内部
        let paintText = new Paint();
        paintText.setStyle(Paint.Style.FILL); // 设置画笔样式,填充内部
        paintText.setAntiAlias(true); // 设置是否开启抗锯齿,一般在绘制棱角分明的图形比如矩形,位图时不需要开启
        paintText.setFilterBitmap(true); // 对位图进行滤波处理,如果该项设置为 true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示
        paintText.setFakeBoldText(false); // 模拟实现粗体文字,设置在小字体上效果会非常差 
        paintText.setTextSize(32); // 设置字体大小,必须大于0
        paintText.setARGB(204, 255, 255, 255); // 设置画笔透明度和颜色

        let canvas = new Canvas(image);

        arr.forEach(item => {
            let region = item.region;
            let text = item.text;

            canvas.drawRect(region[0], region[1], region[2], region[3], paintRect);
            if (text) {
                let textWidth = paintText.measureText(text);
                canvas.drawRect(region[0], region[1] - 38, region[0] + textWidth + 10, region[1], paintRect2);
                canvas.drawText(text, region[0] + 6, region[1] - 8, paintText);
            }
        });

        let image = canvas.toImage();
        images.save(image, path);
        media.scanFile(path)
        image.recycle();
    },
    destroy() {
        if (this.instance) {
            this.instance.board.removeAllListeners();
            this.instance.close();
            this.instance = null;
        }
    }
};

module.exports = drawFloaty;

作 者:道无涯
来 源:道无涯博客
链 接: https://www.daowuya.love/道无涯的-autojspro文字识别pp-ocrv3-插件使用教程/
版 权 声 明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。文章版权归作者所有,未经允许请勿转载!


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇