下面是整个详解步骤过程
- 效果图
- 一、OCR的含义
- 二、什么是Tesseract
- 三、前提准备
- 1、添加依赖
- 2、数据文件下载路径
- 四、实际代码案例Demo如下:
- Main.xml
- Main.java
效果图
- 流程:获取assets中的图片显示到页面,提取照片内的文字
一、OCR的含义
ocr是Optical Character Recognition(光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程
二、什么是Tesseract
官网奉上
简单地说,Tesseract 就是OCR所说的“识别软件”的具体实现
- 其实看官网已经是5、6年前就开始不维护了
- 这里也指明了,不在维护,可前往 Tesseract Tools 的一个分支Tesseract4Android官网,这里还是写一下Tesseract 的demo吧,做参考
当然你也可以直接去Tesseract4Android的参考文章
Tesseract4Android参考文章
三、前提准备
1、添加依赖
注意:
1、Android 2.3 或更高版本
2、数据文件必须是 复制到 Android 设备的子目录中tessdata(上一级文件夹的名称必须是tessdata,后缀必须是.traineddata)
dependencies {implementation 'com.rmtheis:tess-two:9.1.0'
}
2、数据文件下载路径
- 数据文件下载路径或者直接下载中文数据包中文数据包
- 数据包下载下来放到assets文件夹下
四、实际代码案例Demo如下:
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><ImageViewandroid:id="@+id/main_iv_image"android:layout_width="match_parent"android:layout_height="500dp"android:layout_gravity="center_horizontal"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"/><Buttonandroid:id="@+id/main_bt_recognize"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_gravity="center_horizontal"android:text="读取一张图片并识别" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_gravity="center_horizontal"android:text="识别结果:" /><TextViewandroid:id="@+id/main_tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_gravity="center_horizontal" />
</LinearLayout>
Main.java
package com.example.ocrapplication.ui;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;import com.example.ocrapplication.R;
import com.googlecode.tesseract.android.TessBaseAPI;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class TesseractActivity extends AppCompatActivity {public static final String TESS_DATA = "/tessdata";private static final String TARGET_FILENAME = "cs.png";// private static final String DATA_FILENAME = "eng.traineddata";private static final String DATA_FILENAME = "chi_sim.traineddata";private static final String TAG = TesseractActivity.class.getSimpleName();private Button main_bt_recognize;private TextView main_tv_result;private ImageView main_iv_image;private Bitmap bitmap;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_tesseract);// 检查并请求应用所需权限checkPermission();// 获取控件对象initView();// 设置控件的监听器setListener();}@SuppressLint("HandlerLeak")private Handler handler=new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);switch (msg.what){case 1:Bundle data = msg.getData();main_tv_result.setText(data.getString("data"));break;}}};private void setListener() {// 设置识别按钮的监听器main_bt_recognize.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {// 点击后的主程序mainProgram();}});}// 获得界面需要交互的控件private void initView() {main_bt_recognize = findViewById(R.id.main_bt_recognize);main_tv_result = findViewById(R.id.main_tv_result);main_iv_image = findViewById(R.id.main_iv_image);// 从assets中获取一张Bitmap图片bitmap = getBitmapFromAssets(TesseractActivity.this, TARGET_FILENAME);// 同时显示在界面main_iv_image.setImageBitmap(bitmap);}// OCR识别的主程序private void mainProgram() {if (bitmap != null) {// 准备工作:创建路径和Tesserect的数据prepareTess();// 初始化TesserectTessBaseAPI tessBaseAPI = new TessBaseAPI();String dataPath = getExternalFilesDir("/").getPath() + "/";tessBaseAPI.init(dataPath, "chi_sim");//因为识别比较耗时,建议开启开启子线程识别new Thread(new Runnable() {@Overridepublic void run() {// 识别并显示结果String result = getOCRResult(tessBaseAPI, bitmap);//把数据返回到主线程上面显示Message message=new Message();message.what=1;Bundle bundle = new Bundle();bundle.putString("data",result);message.setData(bundle);handler.sendMessage(message);}}).start();}}// 进行OCR并返回识别结果private String getOCRResult(TessBaseAPI tessBaseAPI, Bitmap bitmap) {tessBaseAPI.setImage(bitmap);String result = "-";try{result = tessBaseAPI.getUTF8Text();}catch (Exception e){}tessBaseAPI.end();return result;}// 为Tesserect复制(从assets中复制过去)所需的数据private void prepareTess() {try{// 先创建必须的目录File dir = getExternalFilesDir(TESS_DATA);if(!dir.exists()){if (!dir.mkdir()) {Toast.makeText(getApplicationContext(), "目录" + dir.getPath() + "没有创建成功", Toast.LENGTH_SHORT).show();}}// 从assets中复制必须的数据String pathToDataFile = dir + "/" + DATA_FILENAME;if (!(new File(pathToDataFile)).exists()) {InputStream in = getAssets().open(DATA_FILENAME);OutputStream out = new FileOutputStream(pathToDataFile);byte[] buff = new byte[1024];int len;while ((len = in.read(buff)) > 0) {out.write(buff, 0, len);}in.close();out.close();}} catch (Exception e) {Log.e(TAG, e.getMessage());}}// 从assets中读取一张Bitmap类型的图片private Bitmap getBitmapFromAssets(Context context, String filename) {Bitmap bitmap = null;AssetManager assetManager = context.getAssets();try {InputStream is = assetManager.open(filename);bitmap = BitmapFactory.decodeStream(is);is.close();Log.i("TAG", "图片读取成功。");
// Toast.makeText(getApplicationContext(), "图片读取成功。", Toast.LENGTH_SHORT).show();} catch (IOException e) {Log.i("TAG", "图片读取失败。");
// Toast.makeText(getApplicationContext(), "图片读取失败。", Toast.LENGTH_SHORT).show();e.printStackTrace();}return bitmap;}// 检查应用所需的权限,如不满足则发出权限请求private void checkPermission() {if (ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(TesseractActivity.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 120);}if (ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(TesseractActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 121);}}
}