基于PaddleOCR开发懒人精灵文字识别插件

这篇具有很好参考价值的文章主要介绍了基于PaddleOCR开发懒人精灵文字识别插件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目的

       懒人精灵是 Android 平台上的一款自动化工具,它通过编写 lua 脚本,结合系统的「 无障碍服务 」对 App 进行自动化操作。在文字识别方面它提供的有一款OCR识别插件,但是其中有识别速度慢,插件大的缺点,所以这里将讲解一下如何集成基于PaddleOCR文字识别开发的插件,阅读本篇文字需要对PaddleOCR有个基本的了解,还需要有一点Android开发基础,文章最后有相关插件下载地址。

准备工作

1、android studio最新版本即可

下载地址:Download Android Studio & App Tools - Android Developers

2、下载PaddleOCR提供的安卓版文字识别demo

下载地址:PaddleOCR/deploy/android_demo at release/2.5 · PaddlePaddle/PaddleOCR · GitHub

3、导入Android studio并成功运行

以上三步工作完成后,将开始我们的懒人精灵文字识别插件开发。

插件开发

1、项目结构对比

修改前 VS 修改后,调整了一些文件,去除了Activity入口。

基于PaddleOCR开发懒人精灵文字识别插件

 2、插件SDK集成

在项目的build.gradle文件中添加:

allprojects {
    repositories {
        // ...
        maven { url 'https://jitpack.io' }
    }
}

在app的build.gradle文件中添加

dependencies {
    // ... 
    implementation 'com.alibaba:fastjson:1.1.46.android'
}

3、删除无用的Activity文件

基于PaddleOCR开发懒人精灵文字识别插件

 4、修改AndroidManifest.xml

两处包名替换成自己的包名,其他地方如下代码不动。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.tomato.ocr">
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:debuggable="true"
        android:theme="@style/AppTheme"
        tools:ignore="HardcodedDebugMode">
 
    </application>
</manifest>

5、修改Predictor文件

添加这两行文件:

基于PaddleOCR开发懒人精灵文字识别插件

基于PaddleOCR开发懒人精灵文字识别插件

 调整loadLabel代码如下:

基于PaddleOCR开发懒人精灵文字识别插件

6、修改cpp包名 

修改native.cpp文件,将官方的_com_baidu_paddle_lite_demo_ocr_替换成我们自己的包名,如_com_tomato_ocr_,如下截图:

基于PaddleOCR开发懒人精灵文字识别插件

基于PaddleOCR开发懒人精灵文字识别插件

7、新建OCRApi接口类

package com.tomato.ocr.ec;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.media.ExifInterface;
import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tomato.ocr.OCRResultModel;
import com.tomato.ocr.Predictor;
import com.tomato.ocr.Utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class OCRApi {

    private final int useOpencl = 0;
    private final int cpuThreadNum = 1;
    private final String cpuPowerMode = "LITE_POWER_HIGH";
    private final int detLongSize = 960;
    private final float scoreThreshold = 0.1f;

    // 检测
    protected int run_det = 1;
    // 分类
    protected int run_cls = 1;
    // 识别
    protected int run_rec = 1;

    private final String assetModelDirPath = "models/ch_PP-OCRv2";
    private String assetlabelFilePath = "labels/ppocr_keys_v1.txt";

    private Context mContext;
    private Predictor mPredictor;
    private static OCRApi ocrApi;

    public static OCRApi init(Context mContext) {
        if (ocrApi == null) {
            ocrApi = new OCRApi(mContext);
        }
        return ocrApi;
    }

    public OCRApi(Context mContext) {
        this.mContext = mContext;
        try {
            String path = Utils.setPathForDefaultDataForLr(mContext, this.getClass());
            Log.d("OCR加载路径", path);
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.mPredictor = new Predictor();
        boolean flag = this.mPredictor.init(this.mContext, assetModelDirPath, assetlabelFilePath, useOpencl, cpuThreadNum,
                cpuPowerMode,
                detLongSize, scoreThreshold);
        if (!flag) {
            Log.d("*************", "初始化失败");
        } else {
            Log.d("*************", "初始化成功");
        }
    }

    public void release() {
        if (mPredictor != null) {
            mPredictor.releaseModel();
        }
        if (ocrApi != null) {
            ocrApi = null;
        }
    }

    public String ocrFile(final String imagePath) {
        return this.ocrFile(imagePath, -1);
    }

    public String ocrFile(final String imagePath, int type) {
        if (type == 0) {
            // 只检测
            return this.ocrFile(imagePath, 1, 0, 0).toJSONString();
        } else if (type == 1) {
            // 方向分类 + 识别
            return this.ocrFile(imagePath, 0, 1, 1).toJSONString();
        } else if (type == 2) {
            // 只识别
            return this.ocrFile(imagePath, 0, 0, 1).toJSONString();
        } else if (type == 3) {
            // 检测 + 识别
            return this.ocrFile(imagePath, 1, 0, 1).toJSONString();
        }
        // 默认 检测 + 方向分类 + 识别
        return this.ocrFile(imagePath, 1, 1, 1).toJSONString();
    }

    private JSONArray ocrFile(final String imagePath, int run_det, int run_cls, int run_rec) {
        try {
            Bitmap image;
            if (imagePath.contains(".jpg") || imagePath.contains(".JPG") || imagePath.contains(".jpeg") || imagePath.contains(".JPEG")) {
                ExifInterface exif = null;
                exif = new ExifInterface(imagePath);
                int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                        ExifInterface.ORIENTATION_UNDEFINED);
                image = BitmapFactory.decodeFile(imagePath);
                image = Utils.rotateBitmap(image, orientation);
            } else {
                image = BitmapFactory.decodeFile(imagePath);
            }
            this.mPredictor.setInputImage(image);
            boolean flag = runModel(run_det, run_cls, run_rec);
            if (!flag) {
                Log.d("****************", "无法运行!");
                return new JSONArray();
            }
            return transformOCRResult(this.mPredictor.outputResultList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new JSONArray();
    }

    public String ocrBitmap(final Bitmap bitmap) {
        return this.ocrBitmap(bitmap, -1);
    }

    public String ocrBitmap(final Bitmap bitmap, int type) {
        if (type == 0) {
            // 只检测
            return this.ocrBitmap(bitmap, 1, 0, 0).toJSONString();
        } else if (type == 1) {
            // 方向分类 + 识别
            return this.ocrBitmap(bitmap, 0, 1, 1).toJSONString();
        } else if (type == 2) {
            // 只识别
            return this.ocrBitmap(bitmap, 0, 0, 1).toJSONString();
        } else if (type == 3) {
            // 检测 + 识别
            return this.ocrBitmap(bitmap, 1, 0, 1).toJSONString();
        }
        // 默认 检测 + 方向分类 + 识别
        return this.ocrBitmap(bitmap, 1, 1, 1).toJSONString();
    }

    private JSONArray ocrBitmap(Bitmap bitmap, int run_det, int run_cls, int run_rec) {
        this.mPredictor.setInputImage(bitmap);
        boolean flag = runModel(run_det, run_cls, run_rec);
        if (!flag) {
            Log.d("****************", "无法运行!");
            return new JSONArray();
        }
        return transformOCRResult(this.mPredictor.outputResultList);
    }
    
    private boolean runModel(int run_det, int run_cls, int run_rec) {
        return this.mPredictor.runModel(run_det, run_cls, run_rec);
    }

    private JSONArray transformOCRResult(List<OCRResultModel> ocrResultModelList) {
        JSONArray jsonArray = new JSONArray();
        for (OCRResultModel ocrResultModel : ocrResultModelList) {
            JSONObject jsonObject = new JSONObject();

            jsonObject.put("words", ocrResultModel.getLabel());

            JSONArray objects = new JSONArray();
            for (Point point : ocrResultModel.getPoints()) {
                JSONArray points = new JSONArray();
                points.add(point.x);
                points.add(point.y);
                objects.add(points);
            }
            jsonObject.put("location", objects);
            jsonObject.put("score", ocrResultModel.getConfidence());
            jsonArray.add(jsonObject);
        }
        Log.d("OCR", jsonArray.toJSONString());
        return jsonArray;
    }

}

8、打包插件

执行:Build->Build Bundle(s)/APKS->Build APK(S)

基于PaddleOCR开发懒人精灵文字识别插件

 一个10M以下的插件就完成了。

基于PaddleOCR开发懒人精灵文字识别插件

9、在懒人精灵应用中编写lua代码

首先将apk文件放到资源目录下,然后用loadApk()加载该插件

// ***************************************************************************
// ********************加入群【754442166、469843332】可获取最新版本!!!*********************
// ***************************************************************************

import('java.io.File')
import('java.lang.*')
import('java.util.Arrays')
import('android.content.Context')
import('android.hardware.Sensor')
import('android.hardware.SensorEvent')
import('android.hardware.SensorEventListener')
import('android.hardware.SensorManager')
import('com.nx.assist.lua.LuaEngine')

local loader = LuaEngine.loadApk("TomatoOCR.apk")

local OCR = loader.loadClass("com.tomato.ocr.lr.OCRApi")

local ocr = OCR.init(LuaEngine.getContext())

local type = -1;
-- type 可传可不传
-- type=0 : 只检测
-- type=1 : 方向分类 + 识别
-- type=2 : 只识别
-- type=3 : 检测 + 识别

-- 只检测文字位置:type=0
-- 全屏识别: type=3或者不传type
-- 截取单行文字识别:type=1或者type=2

-- 例子一
local result1 = ocr.ocrFile("/storage/emulated/0/0.jpg", type)
-- local result1 = ocr.ocrFiles(["/storage/emulated/0/0.jpg","/storage/emulated/0/0.jpg",...],type)
printEx(result1);

-- 例子二
local result2 = ocr.ocrBitmap("bitmap对象", type)
-- local result2 = ocr.ocrBitmaps(["bitmap对象","bitmap对象",...],type)
printEx(result2);

-- 例子三
local result3 = ocr.ocrBase64("图片base64字符串", type)
-- local result3 = ocr.ocrBase64s(["图片base64字符串","图片base64字符串",...],type)
printEx(result3);

-- 释放
ocr.release()

完毕!!!

总结

        相对来说,在熟悉PaddleOCR和Android开发的情况下,进行懒人精灵插件开发还是比较容易的,而且通过自己开发插件的形式可以集成更多的功能,比如只进行文本检测、其他语言识别模型、身份识别模型等等,相对来说比较自由,这是官方提供不了的。今天就分享到这里,感谢支持!

插件下载地址:基于PaddleOCR开发懒人精灵文字识别插件资源-CSDN文库文章来源地址https://www.toymoban.com/news/detail-495982.html

到了这里,关于基于PaddleOCR开发懒人精灵文字识别插件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Paddle笔记:PaddleOCR文字识别,简单实用,默认训练模型识别度不错

            PaddleOCR是百度深度学习框架PaddlePaddle开源的OCR项目,旨在打造一套丰富、领先、且实用的OCR工具库,助力使用者训练出更好的模型,并应用落地。PaddleOCR包含丰富的文本检测、文本识别以及端到端算法。         你可能用到的网址: Paddle官网:飞桨PaddlePaddle-源于

    2024年02月16日
    浏览(39)
  • 9步搭建Windows下PaddleOCR图片文字识别WebAPI

    目录 本文实现在windows平台下依靠现有资源来搭建一个图片文字识别的WebAPI,便于其他项目通过Post方式将图片进行Base64编码后传到该API,能够得到图片中的文字信息 第一步:安装Python环境 第二步:安装 opencv-python 第三步:安装 paddleocr 第四步:安装 paddlepaddle   第五步:安

    2024年03月16日
    浏览(50)
  • python+paddleocr 进行图像识别、找到文字在屏幕中的位置

    目录 前言 1、安装paddleocr 2、安装PIL 3、安装numpy 4、 安装pyautogui 5、进行文本识别 6、识别结果 7、获取文字在图片/屏幕中的位置 8、pyautogui+paddleocr鼠标操作 9、完整代码 最近在做自动化测试,因为是处理过的界面,所以使用pywinauto,LDTP获取控件进行操作的方法不可行,于是选

    2024年02月03日
    浏览(35)
  • 基于PaddleOCR的车牌检测识别

    由于本人水平有限,难免出现错漏,敬请批评改正。 更多精彩内容,可点击进入YOLO系列专栏、自然语言处理 专栏或我的个人主页查看 基于DETR的人脸伪装检测 YOLOv7训练自己的数据集(口罩检测) YOLOv8训练自己的数据集(足球检测) YOLOv5:TensorRT加速YOLOv5模型推理 YOLOv5:I

    2024年02月13日
    浏览(30)
  • Python+OpenCV+paddleocr基于传统图像处理技术实现车牌识别

    目录 一、前言 二、预处理-提取车牌         1. 转灰度图         2. 顶帽运算         3. Sobel算子提取y方向边缘         4. 自适应二值化         5. 开运算分割(纵向去噪,分隔)         6. 闭运算合并         7. 膨胀/腐蚀         8. 腐蚀

    2024年02月04日
    浏览(39)
  • Chat GPT国内懒人专用版(基于网站开发使用)

    一:概述 小伙伴们肯定都知道沸沸扬扬的Chat GPT(全名:Chat Generative Pre-trained Transformer),美国Open AI研发的聊天机器人程序 ,于去年11月30日发布 。ChatGPT是人工智能技术驱动的工具,它能够通过理解和学习人类的语言来进行对话,还能根据聊天的上下文进行互动。在这里为

    2024年02月12日
    浏览(43)
  • 基于opencv的图片文字识别实战

    1. 图像边缘检测。 2. 获取轮廓信息。 3. 透视变换,经过旋转、平移等操作对文档图片进行处理。 4. OCR识别图片当中每一个字符。 图片展示:    我们这里以一个英文的文件,一个自己用中文的一首诗来去做这个项目。因为怕其他东西干扰边缘,于是自己画了个框把边缘圈起

    2024年02月08日
    浏览(23)
  • 懒人神器:自动生成单元测试插件 Squaretest

    你是否常常因代码需编写单元测试而痛苦不堪,你是否因单元测试历史债而惆怅不断,Squaretest或许能帮你消除痛苦消除惆怅 前言 一、Squaretest是什么? 二、使用步骤 1.引入插件 2.使用步骤 总结 近来公司增加了代码质量门控,会对代码提交单元测试覆盖率进行检测,覆盖率要

    2024年02月10日
    浏览(39)
  • IDEA懒人必备插件:自动生成单元测试!

    因为公司最近实施了代码质量控制指标,以评估各种项目的单元测试覆盖率和声纳扫描的各种问题。 许多旧项目和旧代码,或者需要匆忙交付的项目,都严重缺少单元测试,覆盖率不到20%。所以最近几天,几个小伙伴一直在疯狂地堆积单元测试。几个人把单元测试累积到50

    2024年02月03日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包