Android离线文字识别-tesseract4android调用

news2024/11/19 3:39:06

Android在线文字识别可以调阿里云的接口Android文字识别-阿里云OCR调用__花花的博客-CSDN博客

需要离线文字识别的话,可以调tesseract4android。个人测试效果不是特别理想,但是速度真的很快,VIVO S10后摄照片,80ms内识别完成。现有的蛮多资料都写的是调用tess-two,但是这个库,已经慢慢不维护了,最新版本是tesseract4android。这是一个开源库,源码路径:https://github.com/adaptech-cz/Tesseract4Android

这个库的调用非常简单,官方readme也有介绍。

1,在build.gradle中增加

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
dependencies {
    // To use Standard variant:
    implementation 'cz.adaptech.tesseract4android:tesseract4android:4.5.0'

}

2,代用也很简单,官方示例代码如下。主要就是给个训练库,然后就可以给照片,最后取结果就行。

// Create TessBaseAPI instance (this internally creates the native Tesseract instance)
TessBaseAPI tess = new TessBaseAPI();

// Given path must contain subdirectory `tessdata` where are `*.traineddata` language files
// The path must be directly readable by the app
String dataPath = new File(context.getFilesDir(), "tesseract").getAbsolutePath();

// Initialize API for specified language
// (can be called multiple times during Tesseract lifetime)
if (!tess.init(dataPath, "eng")) { // could be multiple languages, like "eng+deu+fra"
    // Error initializing Tesseract (wrong/inaccessible data path or not existing language file(s))
    // Release the native Tesseract instance
    tess.recycle();
    return;
}

// Load the image (file path, Bitmap, Pix...)
// (can be called multiple times during Tesseract lifetime)
tess.setImage(image);

// Start the recognition (if not done for this image yet) and retrieve the result
// (can be called multiple times during Tesseract lifetime)
String text = tess.getUTF8Text();

// Release the native Tesseract instance when you don't want to use it anymore
// After this call, no method can be called on this TessBaseAPI instance
tess.recycle();

3,训练数据库路径:GitHub - tesseract-ocr/tessdata at 4.0.0

我只需要做英文识别所以下载eng.traineddata即可,需要做多语言识别的按自己的需求下载多个语训练数据库。这些数据库下下来后,需要放到一个规定名称为tessdata的子目录下,调用init的时候需要提供它的父目录。

4,训练数据库的提取这里要注意权限问题,否则会初始化失败,错误就一个ERROR。我的处理办法是把训练数据库打包到APP,APP启动后释放到内部目录,然后再使用。

1)训练数据库放到raw目录下

2)文件释放类


import static androidx.camera.core.impl.utils.ContextUtil.getApplicationContext;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class FileManager {
    String TAG = "FILE";
    Context context = null;

    public FileManager(Context context)
    {
        this.context = context;
    }

    private File getFilePtr(String outName, String subFolder) throws IOException {
        //找到目录
        File filesDir = context.getFilesDir();
        if (!filesDir.exists()) {
            filesDir.mkdirs();
        }
        //创建专属目录
        File outFileFolder = new File(filesDir.getAbsolutePath()+"/target/"+subFolder);
        if(!outFileFolder.exists()) {
            outFileFolder.mkdirs();
        }
        //创建输出文件
        File outFile=new File(outFileFolder,outName);
        String outFilename = outFile.getAbsolutePath();
        Log.i(TAG, "outFile is " + outFilename);
        if (!outFile.exists()) {
            boolean res = outFile.createNewFile();
            if (!res) {
                Log.e(TAG, "outFile not exist!(" + outFilename + ")");
                return null;
            }
        }
        return outFile;
    }
    private int copyData(File outFile, InputStream is){
        try {
            FileOutputStream fos = new FileOutputStream(outFile);
            //分段读取文件,并写出到输出文件,完成拷贝操作。
            byte[] buffer = new byte[1024];
            int byteCount;
            while ((byteCount = is.read(buffer)) != -1) {
                fos.write(buffer, 0, byteCount);
            }
            fos.flush();
            is.close();
            fos.close();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    public String getFilePathAfterCopy(Uri uri, String outName, String subFolder, boolean ifReturnParent){
        try {
            File outFile=getFilePtr(outName,subFolder);
            //创建输入文件流
            InputStream is= context.getContentResolver().openInputStream(uri);
            if(0!=copyData(outFile,is)) {
                return null;
            }
            //返回路径
            if(ifReturnParent) {
                return  outFile.getParent();
            } else {
                return outFile.getPath();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public String getFilePathAfterCopy(int resId,String outName,String subFolder,boolean ifReturnParent) {
        try {
            //找到目录
            File outFile=getFilePtr(outName,subFolder);
            //创建输入文件流
            InputStream is = context.getResources().openRawResource(resId);
            if(0!=copyData(outFile,is)) {
                return null;
            }
            //返回路径
            if(ifReturnParent) {
                return  outFile.getParent();
            } else {
                return outFile.getPath();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public String byteToString(byte[] data) {
        int index = data.length;
        for (int i = 0; i < data.length; i++) {
            if (data[i] == 0) {
                index = i;
                break;
            }
        }
        byte[] temp = new byte[index];
        Arrays.fill(temp, (byte) 0);
        System.arraycopy(data, 0, temp, 0, index);
        String str;
        try {
            str = new String(temp, "ISO-8859-1");//ISO-8859-1//GBK
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
        return str;
    }

}

3)APP启动释放文件

        //release ocr data file
        FileManager fileManager = new FileManager(this);
        String filePath = fileManager.getFilePathAfterCopy(R.raw.eng, "eng.traineddata", "tessdata", true);
        Log.e("OCR", "datapath + " +filePath);

4)init接口调用的文件路径:

filePath.substring(0, filePath.length() - 8)

5,加上摄像头调用后测试效果

摄像头调用,请看下篇。

新人入行,经验分享,如有所误,欢迎指出~

版权归属:深圳市琪智科技有限公司-花花

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手写Spring:第13章-把AOP扩展到Bean的生命周期

文章目录 一、目标&#xff1a;把AOP扩展到Bean的生命周期二、设计&#xff1a;把AOP扩展到Bean的生命周期三、实现&#xff1a;把AOP扩展到Bean的生命周期3.1 工程结构3.2 AOP动态代理融入Bean的生命周期类图3.3 定义Advice拦截器链3.3.1 定义拦截器链接口3.3.2 方法拦截器链接…

算法笔记:堆

【如无特别说明&#xff0c;皆为最小二叉堆】 1 介绍 2 特性 结构性&#xff1a;符合完全二叉树的结构有序性&#xff1a;满足父节点小于子节点&#xff08;最小化堆&#xff09;或父节点大于子节点&#xff08;最大化堆&#xff09; 3 二叉堆的存储 顺序存储 二叉堆的有序…

问道管理:a股交易时间和规则?

A股是指中国境内流通的人民币普通股票&#xff0c;是国内投资者最为熟悉和广泛的投资工具之一。作为投资者&#xff0c;了解A股的买卖时刻和规矩是非常重要的。本文从买卖时刻、买卖规矩、买卖方式等多个视点来分析A股买卖时刻和规矩&#xff0c;期望对读者有所协助。 A股买卖…

C#事件event

事件模型的5个组成部分 事件拥有者&#xff08;event source&#xff09;&#xff08;类对象&#xff09;&#xff08;有些书将其称为事件发布者&#xff09; 事件成员&#xff08;event&#xff09;&#xff08;事件拥有者的成员&#xff09;&#xff08;事件成员就是事件本身…

2023年03月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;最短路径问题 平面上有n个点&#xff08;n<100&#xff09;&#xff0c;每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。 若有连线&#xff0c;则表示可从一个点到达另一个点&#xff…

C++——STL容器【map和set】

文档&#xff1a;map、set 文章目录 &#x1f36f;1. 关联式容器&#x1fad6;2. set&#x1f37c;1. 模板参数&#x1f37c;2. 构造函数&#x1f37c;3. 修改&#x1f37c;4.操作&#x1f95b;find&#x1f95b;count&#x1f95b;lower_bound & upper_bound & equal_…

Increment Selection 插件

Increment Selection 插件实现递增 初次使用 按下快捷键 Alt Shift 鼠标左键向下拖拽 向下拖拽之后&#xff0c;在输入一个数字&#xff0c;比如我这里输入了一个数字1 然后按下快捷键 Ctrl Shift ← 进行选中数字 然后按下快捷键 Ctrl Alt i 建自动递增。 然后鼠标随…

网络是如何进行通信

网络是如何进行通信的 简介 在现代社会中&#xff0c;网络已经成为我们生活中不可或缺的一部分。从上网搜索信息、在线购物到远程工作和社交媒体&#xff0c;我们几乎无时无刻不与网络保持着联系。但是&#xff0c;网络究竟是个什么玩意&#xff0c;它是如何工作的呢&#xf…

MinIO集群模式信息泄露漏洞(CVE-2023-28432)

前言&#xff1a;MinIO是一个用Golang开发的基于Apache License v2.0开源协议的对象存储服务。虽然轻量&#xff0c;却拥有着不错的性能。它兼容亚马逊S3云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据。该漏洞会在前台泄露用户的账户和密码。 0x00 环境配置 …

数字信封技术概论

数字信封技术是一种通过加密手段实现信息保密性和验证的技术&#xff0c;它在保护敏感信息传输过程中得到了广泛应用。本文将详细介绍数字信封技术的原理、实现和应用场景。 一、数字信封技术的原理 数字信封技术是一种将对称密钥通过非对称加密手段分发的方法。在数字信封中…

《C++设计模式》——行为型

前言 行为型模式是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构&#xff0c;而且重点关注它们之间的相互作用。 Interpreter(解释器) Template Method(模板方法) Chain of Responsibility(责任链) Command(命令) Iterator(迭代器) Me…

海康NVR(Network Video Recorder)启用SSH过程摸索

文章目录 海康NVR具备的特点启用SSH模式优劣比较启用SSH模式的优势启用SSH模式的坏处 Hik NVR启用SSH功能1&#xff0c;Web登录NVR2&#xff0c;SSH登录NVR SSH shell模式特点SSH shell模式指令作用1&#xff0c;简要帮助“help”可以列出常用的shell指令部分可用shell指令输出…

实现一台电脑登录多个微信账号/一个微信账号在多台电脑登录

一、一台电脑登录多个微信账号 在电脑桌面建立一个txt文档文件。 输入内容: echo off start /d"C:\Program Files\Tencent\WeChat\" WeChat.exe start /d"C:\Program Files\Tencent\WeChat\" WeChat.exe exit 如下图&#xff0c;/d"引号内容写微信安…

KT142C-sop16语音芯片ic的串口指令详细说明_默认9600指令可设

3.1 通讯格式 支持异步串口通讯模式,通过串口接受上位机发送的命令 通讯标准:9600 bps --- 可以发送指令修改&#xff0c;并且记忆&#xff0c;详见3.4.5 数据位 :8 停止位 :1 校验位 :none 流控制 :none 格式&#xff1a;$S VER Len CMD Feedback para1 …

简单便捷的行为验证码,让登录更轻松

前言 在当今数字化的世界里&#xff0c;登录账户已成为我们日常生活中不可或缺的一部分。然而&#xff0c;传统的输入验证码方式却常常给用户带来不必要的繁琐和麻烦。为了解决这一问题&#xff0c;简单便捷的行为验证码应运而生&#xff0c;让登录变得更加轻松。 行为验证码…

TuyaOS Sensor Hub组件介绍

文章目录 Sensor Hub 设计思想分层设计Sensor Hub 层(tdl)Sensor Driver 层(tdd) 传感数据元素类型抽象传感器采集策略 Sensor Hub 对上数据与接口数据结构1. 数据读取的触发模式2. 元素型数据订阅规则3. 数据就绪通知回调4. 传感设备信息 应用接口1. 创建传感器实例2. 启动传感…

vue3路由跳转params传参接收不到

import { useRouter } from "vue-router";const router useRouter(); // 提现记录 const withdrawalClick (item) > {router.push({ name: "Devwithdrawal", params: { name: 123 } }); };//跳转页面接收参数 import { useRoute } from "vue-rou…

指针和字符数组笔试题及其解析(第二组)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 数组名在寻常情况下表示首元素地址&#xff0c;但有两种情况例外&#xff1a; 1.sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小 2.&数组名&#xff0c;这里的…

OLED透明屏模块:引领未来显示技术的突破

OLED透明屏模块作为一项引领未来显示技术的突破&#xff0c;以其独特的特点和卓越的画质在市场上引起了广泛关注。 根据行业报告&#xff0c;预计到2025年&#xff0c;OLED透明屏模块将占据智能手机市场的20%份额&#xff0c;并在汽车导航系统市场中占据30%以上份额。 那么&am…

TD3算法

TD3算法 全称Twin Delayed DDPG&#xff0c;是对DDPG算法的继承、发展和改进&#xff0c;论文 改进如下&#xff1a; T w i n \mathcal{T}win Twin&#xff1a;使用了两个critic来评估actor的动作价值&#xff0c;对应两个critic target&#xff0c;一个actor target&#xff0…