Android离线文字识别-tesseract4android调用

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 instancetess.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 blocke.printStackTrace();return "";}return str;}}

3)APP启动释放文件

        //release ocr data fileFileManager 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.hqwc.cn/news/107636.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王道考研计算机网络

文章目录 计算机网络体系结构计算机网络概述计算机网络的性能指标 计算机网络体系结构与参考模型错题 物理层通信基础基础概念奈奎斯特定理和香农定理编码与调制电路交换、报文交换和分组交换数据报与虚电路 传输介质物理层设备错题 数据链路层数据链路层的功能组帧差错控制检错…

二进制安全虚拟机Protostar靶场(2)基础知识讲解,栈溢出覆盖变量 Stack One,Stack Two

前言 Protostar靶场的安装和一些二进制安全的基础介绍在前文已经介绍过了&#xff0c;这里是文章链接 https://blog.csdn.net/qq_45894840/article/details/129490504?spm1001.2014.3001.5501什么是缓冲区溢出 当系统向缓冲区写入的数据多于它可以容纳的数据时&#xff0c;…

从0到1理解ChatGPT原理

目录 写在前面 1.Tansformer架构模型 2.ChatGPT原理 3.提示学习与大模型能力的涌现 3.1提示学习 3.2上下文学习 3.3思维链 4.行业参考建议 4.1拥抱变化 4.2定位清晰 4.3合规可控 4.4经验沉淀 机械工业出版社京东自购链接 写在前面 2022年11月30日&#xff0c;ChatG…

【C语言】库宏offsetof

一.offsetof简介 因此,宏offsetof的作用是: 当你传入结构体的类型及其成员时,它会返回该成员在结构体中的偏移量. 二.offsetof的使用 如下,我们使用offsetof打印一下结构体foo中,成员a,成员b及成员c相对于首地址的偏移量分别是多少: #include <stdio.h> #include …

Vue框架--收集表单数据

下面我们介绍Vue收集表单中的数据。这一节比较重要&#xff0c;需要大家好好听&#xff0c;因为后面数据交互的时候使用的特别的多。

Redis新篇一:认识Redis

首先&#xff0c;很抱歉小伙伴们&#xff0c;前段时间一直都没有更新&#xff0c;我很抱歉&#xff0c;现在开始持续更新Redis相关内容啦&#xff01;有需要的小伙伴们可以持续关注一下小博主的新篇哦~ 希望对你们有帮助&#xff01; 作者&#xff1a;爱撸猫的程序员 博客地址…

Android kotlin开源项目-功能标题目录

目录 一、BRVAH二、开源项目1、RV列表动效&#xff08;标题目录&#xff09;2、拖拽与侧滑&#xff08;标题目录&#xff09;3、数据库&#xff08;标题目录&#xff09;4、树形图(多级菜单)&#xff08;标题目录&#xff09;5、轮播图与头条&#xff08;标题目录&#xff09;6…

Mybatis中传递多个参数的4种方法

现在大多项目都是使用Mybatis了&#xff0c;但也有些公司使用Hibernate。使用Mybatis最大的特性就是sql需要自己写&#xff0c;而写sql就需要传递多个参数。面对各种复杂的业务场景&#xff0c;传递参数也是一种学问。下面给大家总结了以下几种多参数传递的方法&#xff1a; 方…

Scrum敏捷开发流程及关键环节

​Scrum是一种敏捷开发流程&#xff0c;它旨在使软件开发更加高效和灵活。Scrum将软件开发过程分为多个短期、可重复的阶段&#xff0c;称为“Sprint”。每个Sprint通常为两周&#xff0c;旨在完成一部分开发任务。 在Scrum中&#xff0c;有一个明确的角色分工&#xff1a; 产…

使用纯C语言定义通用型数据结构的方法和示例

文章目录 前言以实现优先队列来描述实现思想基本类型的包装类型比较函数演示总结 前言 最近一段时间在复习数据结构和算法&#xff0c;用的C语言&#xff0c;不得不说&#xff0c;不学个高级语言再回头看C语言根本不知道C语言的强大和完美&#xff0c;不过相比之下也有许多不便…

小程序源码:多功能口袋工具箱微信小程序源码-带流量主|云开发(更新)

这里主要分享多功能口袋工具箱微信小程序源码&#xff0c;有带流量主&#xff0c;而且超多功能工具箱组合的微信小程序源码。无需服务器即可搭建&#xff0c;可以设置流量主赚取收益。 源码链接&#xff1a; 网盘源码 密码&#xff1a;hma8 工具箱的应用一览&#xff1a; 1…

软件测试总结1

1、 什么是软件测试? 答: 软件测试是在规定的条件下对程序进行操作&#xff0c;以发现错误&#xff0c;对软件质量进行评估。 什么是软件测试&#xff1a; 明确地提出了软件测试以检验是否满足需求为目标。 1、保证软件质量的重要手段 预期 ≈ 实际 2、 软件测试的意义 给…