当前位置: 首页 > news >正文

Android开发 OCR:通过Tesseract实现图片文字识别

下面是整个详解步骤过程

  • 效果图
  • 一、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);}}
}

相关文章:

  • 题目:新一的宝藏搜寻加强版(蓝桥OJ 4059)
  • 学习笔记——C语言基本概念指针(下)——(8)
  • 【Linux】文件查看命令(六)
  • AMD GPUs - Radeon™ PRO W7900与NVIDIA 4000系列GPU性能
  • 工作日志- 不定期更新
  • git 更改仓库地址
  • Java常见限流用法介绍和实现
  • Mysql的高级语句3
  • 蓝桥杯算法题-发现环
  • 【笔记】OpenHarmony设备开发:搭建开发环境(Ubuntu 20.04,VirtualBox 7.0.14)
  • 实时数据库测试-汇编小程序
  • 发票是扫码验真好,还是OCR后进行验真好?
  • 2024.4.1
  • MacBook终端安装brew命令
  • 给三分钟热度学习Python的同学的一条建议
  • [iOS]Core Data浅析一 -- 启用Core Data
  • CentOS 7 防火墙操作
  • create-react-app项目添加less配置
  • Date型的使用
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • flask接收请求并推入栈
  • Java 多线程编程之:notify 和 wait 用法
  • JavaScript新鲜事·第5期
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • react 代码优化(一) ——事件处理
  • scala基础语法(二)
  • vue-loader 源码解析系列之 selector
  • yii2中session跨域名的问题
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 后端_MYSQL
  • 解决iview多表头动态更改列元素发生的错误
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 普通函数和构造函数的区别
  • 前端设计模式
  • 实习面试笔记
  • 小程序 setData 学问多
  • 用简单代码看卷积组块发展
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​力扣解法汇总946-验证栈序列
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # Apache SeaTunnel 究竟是什么?
  • # 透过事物看本质的能力怎么培养?
  • #图像处理
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (30)数组元素和与数字和的绝对差
  • (day 12)JavaScript学习笔记(数组3)
  • (八)Spring源码解析:Spring MVC
  • (六)c52学习之旅-独立按键
  • (全注解开发)学习Spring-MVC的第三天
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .net core 依赖注入的基本用发