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.mzph.cn/news/71799.shtml

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

相关文章

qemu-system-x86_64 命令创建虚拟机,报gtk initialization failed的

因为是ssh命令行启动&#xff0c;增加--nographic # /opt/debug/bin/qemu-system-aarch64 -machine virt-6.2 -qmp tcp:localhost:1238,server,nowait --nographic configure accelerator virt-6.2 start machine init start cpu init start add rom file: virtio-net-pci…

【免费模板】2023数学建模国赛word+latex模板免费分享

无需转发 免费获取2023国赛模板&#xff0c;获取方式见文末 模板文件预览如下&#xff1a; 模板参考格式如下&#xff1a; &#xff08;题目&#xff09;XXXXXX 摘 要&#xff1a; 开头段&#xff1a;需要充分概括论文内容&#xff0c;一般两到三句话即可&#xff0c;长度控…

idea的git入门

&#xff08;1&#xff09;安装好git之后&#xff0c;在idea的设置里面&#xff0c;按照下面三步&#xff0c;配置git &#xff08;2&#xff09;创建本地git仓库 选择本地仓库的根目录&#xff0c;点击ok &#xff08;3&#xff09;创建成功之后&#xff0c;会发现文件名称都变…

Notepad++ 的安装及配置

由于电脑重装了Win11系统&#xff0c;干脆重头开始&#xff0c;重新安装每一个软件~~~ 很多博客或者博主都会推荐notepad的官网&#xff1a;https://notepad-plus-plus.org/ 但大家亲自点开就会发现是无响应&#xff0c;如下图 同时&#xff0c;也会有很多博主直接给网盘地址…

垃圾回收 - 分代垃圾回收

分代垃圾回收在对象中导入了“年龄”的概念&#xff0c;通过优先回收容易成为垃圾的对象&#xff0c;提高垃圾回收的效率。 1、新生代对象和老年代对象 分代垃圾回收中把对象分类成几代&#xff0c;针对不同的代使用不同的 GC 算法&#xff0c;我们把刚生成的对象称为新生代对…

三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课

三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课 现在不管什么GIS平台首先要解决的就是数据来源问题&#xff0c;因为没有数据的GIS就是一个空壳&#xff0c;下面我就目前一些主流的数据获取 方式了解做如下之我见&#xff08;主要针对互联网上的一些卫星…

java+ssm+mysql电梯管理系统

项目介绍&#xff1a; 使用javassmmysql开发的电梯管理系统&#xff0c;系统包含管理员&#xff0c;监管员、安全员、维保员角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;系统用户管理&#xff08;监管员、安全员、维保员&#xff09;&#xff1b;系统公告&#…

Android签名查看

查看签名文件信息 第一种方法&#xff1a; 1.打开cmd&#xff0c;执行keytool -list -v -keystore xxx.keystore&#xff0c;效果如下图&#xff1a; 第二种方法: 1.打开cmd&#xff0c;执行 keytool -list -v -keystore xxxx.keystore -storepass 签名文件密码&#xff0…

Python调试学习资料

Python调试学习资料 python -m pdb example.py网络资源 Python代码调试的几种方法总结Python 程序如何高效地调试&#xff1f;Python Debugging With Pdbpdb — The Python DebuggerThe Python Debugger (pdb)Python Debugger with ExamplesHow to port Python 2 Code to Pyth…

功率信号源可以应用在哪些方面

功率信号源是一种能够产生一定功率的信号源&#xff0c;广泛应用于各个领域。下面将介绍功率信号源在电子、通信、工业和科研等方面的应用。 在电子行业中&#xff0c;功率信号源是一种重要的测试工具。它可以产生各种波形的信号&#xff0c;如正弦波、方波、脉冲波等&#xff…

[Java]异常

目录 1.异常的概念与体系结构 1.1异常的概念 1.1.1算术异常 1.1.2数组越界异常 1.1.3空指针异常 1.2异常的体系结构 1.3异常的分类 2.异常的处理 2.1 防御式编程 2.2异常的抛出 2.3异常的捕获 2.3.1 异常声明throws 将光标放在抛出异常方法上&#xff0c;alt Insert …

合宙Air724UG LuatOS-Air LVGL API控件--下拉框 (Dropdown)

下拉框 (Dropdown) 在显示选项过多时&#xff0c;可以通过下拉框收起多余选项。只为用户展示列表中的一项。 示例代码 -- 回调函数 event_handler function(obj, event)if (event lvgl.EVENT_VALUE_CHANGED) thenprint("Option:", lvgl.dropdown_get_symbol(obj)…

IMX6ULL移植篇-uboot源码主要文件说明

一. uboot 源码分析前提 由于 uboot 会使用到一些经过编译才会生成的文件&#xff0c;因此&#xff0c;我们在分析 uboot的时候&#xff0c;需要先编译一下 uboot 源码工程。 这里所用的开发板是 nand-flash 版本。 本文学习续上一篇文章&#xff0c;如下&#xff1a; IMX6U…

Task :app:compileDebugKotlin FAILED

gradle.properties 里面加上 android.enableJetifiertrue

【LeetCode】19. 删除链表的倒数第 N 个结点

19. 删除链表的倒数第 N 个结点&#xff08;中等&#xff09; 方法&#xff1a;快慢指针 思路 为了找到倒数第 n 个节点&#xff0c;我们应该先找到最后一个节点&#xff0c;然后从它开始往前数 n-1 个节点就是要删除的节点。 对于一般情况&#xff1a;设置 fast 和 slow 两个…

idea配置gitLab

前言&#xff1a;网上有很多类似的文章&#xff0c;但描述不够详细 步骤1&#xff1a;安装git 如果安装成功再次点击TEST按钮展示如下&#xff1a;git版本 步骤2&#xff1a;idea配置gitlab 查看当前项目管理的 远程仓库再git的地址&#xff0c;该地址可是gitLab的&#xff0…

DNS解析

1.DNS介绍 DNS 表示域名系统。此系统实质上是用于整理和识别各个域名的网络电话簿。电话簿将“Acme Pizza”之类的名称转换为要拨打的正确电话号码&#xff0c;而 DNS 将“www.google.com”之类的网络地址转换为托管该网站的计算机的物理 IP 地址&#xff0c;如“74.125.19.147…

OpenCV(二十七):图像距离变换

1.像素间距离 2.距离变换函数distanceTransform() void cv::distanceTransform ( InputArray src, OutputArray dst, int distanceType, int maskSize, int dstType CV_32F ) src:输入图像&#xff0c;数据类型为CV8U的单通道图像dst:输出图像&#xff0c;与输入图像…

RabbitMQ学习笔记

1、什么是MQ&#xff1f; MQ全称message queue&#xff08;消息队列&#xff09;&#xff0c;本质是一个队列&#xff0c;FIFO先进先出&#xff0c;是消息传送过程中保存消息的容器&#xff0c;多 用于分布式系统之间进行通信。 在互联网架构中&#xff0c;MQ是一种非常常见的…

js中call、apply和bind:

文章目录 一、区别:二、案例&#xff1a;三、实现&#xff1a;【1】call实现【2】apply实现【3】bind实现 一、区别: call、apply、bind相同点&#xff1a;都是改变this的指向&#xff0c;传入的第一个参数都是绑定this的指向&#xff0c;在非严格模式中&#xff0c;如果第一个…