Tesstwo9.1.0配置步骤
一,配置步骤
环境:Tesstwo9.1.0+Android10(华为)+Android11(模拟器)
1.查看tess-two的最新版本(GitHub - rmtheis/tess-two: Fork of Tesseract Tools for Android),
在build.gradle中配置依赖包
dependencies {
implementation 'com.rmtheis:tess-two:9.1.0'
}
2.下载识别包,并将需要识别语言的识别包放置到需要的路径(后面的例子中会在代码里面从assets目录中拷贝到指定路径)
下载路径:https://github.com/tesseract-ocr/tessdata/tree/3.04.00
找到「需要的语言.traineddata」,复制到手机的任意路径中,此例子中测试了chi_sim.traineddata
※识别包必须放置在名为tessdata的文件夹下
3.添加下面的代码(因为识别过程比较耗时,在多线程中添加下面的代码)
1 val tessBaseApi = TessBaseAPI()
// DATAPATH为识别包放置的tessdata的上层路径
// 比如识别包放置在「storage/emulated/0/tessdata/chi_sim.traineddata」,那么DATAPATH=「storage/emulated/0」
//DEFAULT_LANGUAGE为识别包不带后缀的名字,如chi_sim
2 tessBaseApi.init(DATAPATH, DEFAULT_LANGUAGE)
// currentBitmap为需要识别的图片,Bitmap类型
3 tessBaseApi.setImage(currentBitmap)
// result为识别的结果
4 val result = tessBaseApi.utF8Text
5 tessBaseApi.end()
4. 如果识别包的路径为外部存储的话,需要在AndroidManifest.xml中添加权限,并进行权限申请(权限申请代码请参考下面的示例代码)
// Android6.0~Android10.0添加
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
// Android11.0添加
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
二,示例代码
chi_sim.traineddata复制到assets目录下
1 package com.example.ocr
2
3 import android.Manifest
4 import android.content.Intent
5 import android.content.pm.PackageManager
6 import android.graphics.Bitmap
7 import android.graphics.BitmapFactory
8 import android.os.Build
9 import android.os.Bundle
10 import android.os.Environment
11 import android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
12 import android.util.Log
13 import androidx.appcompat.app.AppCompatActivity
14 import com.example.ocr.databinding.ActivityMainBinding
15 import com.googlecode.tesseract.android.TessBaseAPI
16 import kotlinx.coroutines.Dispatchers
17 import kotlinx.coroutines.GlobalScope
18 import kotlinx.coroutines.launch
19 import kotlinx.coroutines.withContext
20 import org.opencv.android.Utils
21 import org.opencv.core.Mat
22 import org.opencv.core.Point
23 import org.opencv.core.Size
24 import org.opencv.imgproc.Imgproc
25 import java.io.File
26 import java.io.FileOutputStream
27
28 // TessBaseAPI初始化的第一个参数,目录
29 //val DATAPATH = "/data/user/0/com.example.ocr/files"
30 val DATAPATH = "storage/emulated/0"
31
32 // TessBaseAPI初始化的第二个参数,不带后缀名的识别库的名字
33 val DEFAULT_LANGUAGE = "chi_sim"
34
35 // 识别库名
36 val DEFAULT_LANGUATE_FILENAME = DEFAULT_LANGUAGE + ".traineddata"
37
38 // 识别库文件夹名
39 val FOLDER_NAME = "tessdata"
40
41 // RuntimePermission的request_code
42 val REQUEST_CODE = 0
43
44 class MainActivity : AppCompatActivity() {
45
46 private lateinit var binding: ActivityMainBinding
47
48 private lateinit var currentBitmap: Bitmap
49
50 override fun onCreate(savedInstanceState: Bundle?) {
51 super.onCreate(savedInstanceState)
52
53 val data_path = Environment.getExternalStorageDirectory().toString()
54
55 binding = ActivityMainBinding.inflate(layoutInflater)
56 setContentView(binding.root)
57
58 // Example of a call to a native method
59 binding.sampleText.text = stringFromJNI()
60
61 val drawable = R.drawable.download1
62 currentBitmap = BitmapFactory.decodeResource(resources, drawable)
63
64 // OCR
65 binding.ocrBtn.setOnClickListener() {
66 GlobalScope.launch {
67 val result = startOCR()
68 runOnUiThread {
69 binding.sampleText.text = result
70 }
71 }
72
73 }
74 // Android 11.0
75 if (Build.VERSION.SDK_INT >= 30) {
//「checkSelfPermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED」
// 不能判断权限是否被赋予
76 if (!Environment.isExternalStorageManager()) {
// 启动All Files access画面,让用户选择是否授权
77 val intent = Intent(ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
78 startActivity(intent)
79 } else {
80 copyData(DATAPATH)
81 }
82 // Android 6.0
83 } else if (Build.VERSION.SDK_INT >= 23) {
84 if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
85 checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
86 requestPermissions(
87 arrayOf(
88 Manifest.permission.READ_EXTERNAL_STORAGE,
89 Manifest.permission.WRITE_EXTERNAL_STORAGE),
90 REQUEST_CODE)
91 } else {
92 copyData(DATAPATH)
93 }
94 } else {
95 copyData(DATAPATH)
96 }
97 }
98
99 override fun onRequestPermissionsResult(
100 requestCode: Int,
101 permissions: Array<out String>,
102 grantResults: IntArray
103 ) {
104 if (requestCode == REQUEST_CODE) {
105 if (grantResults.size == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED
106 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
107 copyData(DATAPATH)
108 }
109 }
110 }
111
112 override fun onResume() {
113 super.onResume()
114 if (Build.VERSION.SDK_INT >= 30 &&
115 Environment.isExternalStorageManager()) {
116 copyData(DATAPATH)
117 }
118 }
119
120 private suspend fun startOCR() : String {
121 return withContext(Dispatchers.Default) {
122 val tessBaseApi = TessBaseAPI()
123 tessBaseApi.init(DATAPATH, DEFAULT_LANGUAGE)
124 tessBaseApi.setImage(currentBitmap)
125 val result = tessBaseApi.utF8Text
126 tessBaseApi.end()
127 result
128 }
129 }
130
131 /**
132 * assets下的chi_sim.traineddata复制到toPath下
133 */
134 private fun copyData(toPath: String) {
135 val inputStream = assets.open(DEFAULT_LANGUATE_FILENAME)
// 判断文件夹是否存在
136 val toPathFile = File(toPath)
137 if (!toPathFile.exists()) {
138 toPathFile.mkdir()
139 }
// 判断tessdata文件夹是否存在
140 val dstFolderPath = toPath + File.separator + FOLDER_NAME
141 val dstFolderFile = File(dstFolderPath)
142 if (!dstFolderFile.exists()) {
143 dstFolderFile.mkdir()
144 }
145 val dstFilePath = dstFolderPath + File.separator + DEFAULT_LANGUATE_FILENAME
146 val dstFile = File(dstFilePath)
147 if (!dstFile.exists() || dstFile.length().toInt() == 0) {
148 val outputStream = FileOutputStream(dstFile)
149 var buffer = ByteArray(1024)
150 var len = inputStream.read(buffer)
151 while (len != -1) {
152 outputStream.write(buffer, 0, len)
153 len = inputStream.read(buffer)
154 }
155 outputStream.flush()
156 inputStream.close()
157 outputStream.close()
158 }
159 }
160
161 /**
162 * A native method that is implemented by the 'native-lib' native library,
163 * which is packaged with this application.
164 */
165 external fun stringFromJNI(): String
166
167 companion object {
168 // Used to load the 'native-lib' library on application startup.
169 init {
170 System.loadLibrary("native-lib")
171 }
172 }
173 }
三,需要注意的问题
E/Tesseract(native): Could not initialize Tesseract API with language=chi_sim!
如果运行过程中,出现上面的error log,基本可以判断是权限问题,特别是android11后,
申请「READ_EXTERNAL_STORAGE」和「WRITE_EXTERNAL_STORAGE」,也是无法正常访问外部存储(storage/emulated/0)
示例中采取的申请「MANAGE_EXTERNAL_STORAGE」权限的方案,虽然在模拟器上运行成功了,但并不是一个非常好的方案。
因为「MANAGE_EXTERNAL_STORAGE」权限是为文件管理器,备份恢复用app的此类应用提供的,google并不推荐。
Tesstwo9.1.0配置步骤的更多相关文章
- Sitecore8.2 Solr5.1.0配置步骤
1.首先下载Solr安装包,官方提供了几种下载,我选的的solr的5.1.0版本zip包,下载链接:http://mirror.bit.edu.cn/apache/lucene/solr. 2.下载后 ...
- VS2017配置opencv-4.2.0详细步骤
VS2017配置opencv-4.2.0详细步骤 1.下载opencv的安装包并解压.下载网址https://sourceforge.net/projects/opencvlibrary/ 图1 ...
- [转]phoneGap3.0安装步骤(以windows下的android环境为例):
phoneGap3.0安装步骤(以windows下的android环境为例): 环境: WIN系统,JDK,Android,Eclipse,Ant,Git,PhoneGap3.x (Cordova) ...
- MySQL数据库集群进行正确配置步骤
MySQL数据库集群进行正确配置步骤 2010-06-09 10:47 arrowcat 博客园 字号:T | T 我们今天是要和大家一起分享的是对MySQL数据库集群进行正确配置,我前两天在相关网站 ...
- Windows 8.0上Eclipse 4.4.0 配置CentOS 6.5 上的Hadoop2.2.0开发环境
原文地址:http://www.linuxidc.com/Linux/2014-11/109200.htm 图文详解Windows 8.0上Eclipse 4.4.0 配置CentOS 6.5 上的H ...
- Oracle 11g客户端在Linux系统上的配置步骤详解
Oracle 11g客户端在Linux系统上的配置步骤详解 2011-07-26 10:47 newhappy2008 CSDN博客 字号:T | T 本文我们主要介绍了Oracle 11g客户端在L ...
- mysql传统主从、双主复制+keepalived配置步骤
mysql主从.主主复制(双主复制)配置步骤 一:MySQL复制: MySQL复制简介: 将master服务器中主数据库的ddl和dml操作通过二进制日志传到slaves服务器上,然后在master服 ...
- Eclipse集成Tomcat的配置步骤实例
使用Eclipse开发B/S结构Web应用时,必须使用Web应用服务器,常见的应用服务器有Tomcat, Jboss, WebLogic, WebSphere, SUN System Applicat ...
- Eclipse使用ButterKnife前,需要的配置步骤
ButterKnife下载地址(7.0.1版本):http://files.cnblogs.com/files/zzw1994/butterknife-7.0.1.zip 官方下载地址(7.0.1版本 ...
- KindEditor配置步骤
KindEditor是一套开源的HTML可视化编辑器,主要用于让用户在网站上获得所见即所得编辑效果,兼容IE.Firefox.Chrome.Safari.Opera等主流浏览器. KindEditor ...
随机推荐
- idea远程连接云服务器,并将本地代码部署在云端进行运算
电脑内存和显存过小,需要在云服务器进行运算我的模型,由于一直在自己的电脑上写的代码,于是之间迁移代码到云服务器,只要通过ssh链接到云端后,将python解释器使用云端的解释器就ok 从 file-- ...
- ctfshow web入门 命令执行 web29-36
29-36 全是基于get传参执行 eval() 函数,均采用黑名单匹配,不同点在于黑名单的变化 web29 1 error_reporting(0); 2 if(isset($_GET['c'])) ...
- 【Java学习Day10】类型转换
类型转换 由于Java是强类型语言,所以要进行某些运算的时候,需要用到类型转换 低------------------------------------------>高 byte-->s ...
- MyBatisPlus 报MP_OPTLOCK_VERSION_ORIGINAL not found. Available parameters are错误
配置mybatisplus乐观锁的过程 1.在数据库表中添加version字段类型int 2.在实体类中增加version属性,属性上增加@Version注解 3.配置乐观锁插件 @Configura ...
- https://github.com/wuweilin/springboot-login-demo
wuweilin/springboot-login-demo: Springboot后端登录注册项目演示demo (github.com) jdk-8u172-windows-x64.exe apac ...
- 深入理解 epoll 原理
从网卡如何接收数据说起 CPU 如何知道接受了数据? 进程阻塞为什么不占用 CPU 资源? 工作队列 等待队列 唤醒进程 内核接收网络数据全过程 同时监视多个 socket 的方法 select 的监 ...
- GuiLite 学习笔记(一) Mainloop与ViewTree
以GuiLiteSamples中的HelloSlide 为例,剖析一下GuiLite的设计思路和刷新机制: 首先是main.cpp; 可以分成3部分: 1.根据fb mode拿到对应的phy_fb, ...
- 抓包工具Fidder
第一步:直接在浏览器下载 第二步:设置Fiddler打开Fiddler, Tools-> Fiddler Options (配置完后记得要重启Fiddler)选中"Decrpt ...
- vm虚拟机和主机之间互传文件
u盘大家都有吧,用u盘吧,超方便! vmtools 从主机传文件到虚拟机 可以通过之间复制粘贴/拖拽 或者共享文件夹的方式 从虚拟机传文件到主机,查到了说说是要在虚拟机里面改一个什么映射设置,改完之后 ...
- spring boot 导出数据到excel
手把手教你springboot中导出数据到excel中 问题来源: 前一段时间公司的项目有个导出数据的需求,要求能够实现全部导出也可以多选批量导出(虽然不是我负责的,我自己研究了研究),我们的项目是x ...