Android OCR数字识别

1 篇文章 0 订阅
1 篇文章 0 订阅

        由于工作需要,需要对快递单上的手机号码进行快速扫描识别。查询各种OCR识别方式后还是决定采用Android+Tesseract进行识别。

        今天开始记录开发过程。首先是开发环境的配置。

       我的Android Studio 版本是最新的4.0。

1:环境搭建,新建项目,采用JAVA编程。

      项目建成后开始部署OCR识别包。

     首先需要下载OCR识别包。但由于该识别包内包含了英文所以对于识别数字来说有点厚重冗余。所以在在网上搜索后得到了一个只包含数字的OCR识别包。资源会上传到资源中。

     在APP目录下新建资源包assets 右键在项目下选择NEW 在选择Folder然后选择Assets Folder .将OCR识别文件复制到该资源目录下。存放到该目录下的原因是需要将OCR识别包拷贝到手机的SD卡下。 方便以后进行OCR识别。 

        OCR识别包部署完成。

2:开始配置OCR的导入。

在配置文件builder.gradle中导入google的识别包。

我使用的是9.1目前是最新版。可以根据需要来下载最新版本。 识别包导入后可以进行正常开发了。 

二 开始布局开发及基本的自定义相机应用。

1:在布局之前 先在配置文件 AndroidManifest.xml  中申请 权限。

      SD卡的读写权限。

      相机的使用权限。

     其他权限可以根据应用的情况来进行申请。

   

 

 

判断并申请权限。

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;


public class permission {

    //申请权限
    public void permission(Context context, Activity activity) {
        //判断权限。如果没有SD卡的写权限,没有相机的权限则开始申请权限。
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

            //没有权限开始进行申请。
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) &&
                    ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)) {

                //开始提示信息
                Toast.makeText(context, "请先申请权限再进行操作。", Toast.LENGTH_SHORT).show();

            } else {
                ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE},
                        1);
            }
        }
    }
}

权限申请后开始在主程序中调用该方法进行权限申请。

开始自定义相机开发。

这里 只说相机开发的注意点,以及相机的蒙版开发过程中遇到的坑和解决办法。 

1:相机开发。

我这里用的是 android.hardware.Camera 进行的自定义相机的开发。这种架构以及属于淘汰阶段。但也可以正常使用。 

相机在预览过程中如果需要得到Bitmap 的话 一定要先进行数据流的转换因为Camera默认的格式是YuvImage格式所以需要在重写预览的事件。也就是   camera.setPreviewCallback(new Camera.PreviewCallback()) 重写这个事件。在此事件中有data参数。该参数是相机预览中的数据流。通过转换可以得到Bitmap从而可以进行图片的裁剪。

2:相机的蒙版 。

 相机蒙版开发中由于资料较少 ,所以研究了比较长的时间 。在这里记录一下 可以让后来的人或者自己以后少走弯路。

新建java class 继承 view .

     蒙版的建立其实就是 画笔的定义。也就是 层 。

在画布Canvas 固定的情况下  我们可以定义不同的Paint 来进行绘画。从而可以达到蒙版的效果。

首先定义第一个Paint .这个用来绘画蒙版的底层。在这一层中 一定要采用混合图像模式。这样才会形成中间亮四周黑的效果。

也就是:

//设置 抗锯齿
paint.setAntiAlias(true);
//设置 抖动
paint.setDither(true);
//设置混合图像为清除模式。
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

在这里采用清除模式 可以将制定的区域进行清除。

最为重要的是如果想得到这个效果 一定要重写 Canvas的onDraw事件。

定义第二个paint 重要是用来绘制边框。 

定义第三个paint 可以用来绘制四角的短线。最终效果如下:

这样也就形成了最终的蒙版。

 

数字识别 

在UI设计完成并可以对生成的Bitmap进行裁剪后 我们可以调用OCR来进行图片的识别。

由于是实时进行图片的识别 。所以最好重新建立一个线程 。在单独的线程中进行操作。

这样就可以实时进行图片的识别 。

//将识别文件拷贝到SD卡中。目前我这里是不管文件在不在都进行拷贝。
private void ocrfilecopy() {
    //在SD卡中创建存放识别库的目录。该目录名必须是tessdata 这个文件名是在API使用中规定了的。

    //定义tessdata目录在SD 卡的路径。
    String Chisim_dir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tessdata";

    //定义识别文件的绝对路径和文件名。chi_sim.traineddata 识别文件名。
    String orc_filename = Chisim_dir + "/chi_sim.traineddata";

    Log.i("path", Chisim_dir);
    //检查是否存在此目录。如果存在则不创建,否则则创建目录。
    File dirfile = new File(Chisim_dir);
    if (dirfile.exists() == false) {
        //目录不存在。则创建。
        dirfile.mkdir();
        Log.i("提示信息", "目录已创建。");
    }

    //目录创建完成后将OCR识别文件CHI_SIM拷贝到该目录下。

    //判断识别文件Chi_sim.traineddata是否存在。
    File ocrfile = new File(orc_filename);

    //不管识别文件是否存在先删除在创建。
    ocrfile.delete();

    //开始创建文件。
    //首先文件是存放在资源文件夹assets下的。所以要先获取资源;
    AssetManager assetManager;
    assetManager = getAssets();

    //开始读取识别文件并开始复制。输入。
    InputStream inputStream;
    //开始写入文件。输出。
    OutputStream outputStream;

    try {
        //将识别文件读入到输入流中。
        inputStream = assetManager.open("chi_sim.traineddata");

        //创建目标文件。
        outputStream = new FileOutputStream(orc_filename);

        //开始复制,每次复制1024k的字节。
        byte[] buff = new byte[1024];

        //开始循环写入。
        int ll_count;
        while ((ll_count = inputStream.read(buff)) != -1) {
            outputStream.write(buff, 0, ll_count);
        }
        //释放资源
        outputStream.flush();
        outputStream.close();
        inputStream.close();


    } catch (IOException e) {
        e.printStackTrace();
    }
}


//开始识别图片中的数字。
private String disocrnumber(Bitmap bitmap) {
    String number = null;
    //定义使用的字符集。
    String orctype = "chi_sim";
    //实例化  ocr  API
    TessBaseAPI tessbaseapi = new TessBaseAPI();

    //开始初始化 指定识别所用的资源位置。在SD卡中的位置。
    tessbaseapi.init(Environment.getExternalStorageDirectory().getAbsolutePath(), orctype);
    //初始化后开始识别图片。设置需要识别的图片。
    tessbaseapi.setImage(bitmap);
    //得到识别内容
    number = tessbaseapi.getUTF8Text();

    Log.i("fasdasdfsdafasd", "number=" + number);


    return number;
}

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值