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并不推荐。

 

posted @ 2021-07-19 17:25  minminjy123  阅读(907)  评论(0编辑  收藏  举报