项目地址
https://github.com/979451341/OrcTest

我们说说实现这个项目已实现的功能,能够截图手机界面的某一块,将这个某一块图片的Bitmap传给tess-two的代码来获取扫描结果

我这里在贴出tess-two这个专为Android而创建的文字识别框架的地址
https://github.com/rmtheis/tess-two

接下来我就说我如何一步一步的实现项目

1.实现基础界面,我这里贴出已完成的界面

这样是为了模仿扫描二维码的界面,因为扫描身份证号码或者是手机号那样长条的数字,就将扫描区域也做成长条状,这个扫描区域是有意义的,因为到时候截图会只将扫描区域里的图片信息拿去扫描,这也是为了提高扫描速度和精度。

首先要实现这个界面,我们需要画出四个灰色长方体的位置大小,上下左右。

left是扫描区域左边离手机屏幕左边的距离是手机屏幕宽度的1/10,right就是扫描区域右边离手机屏幕左边的距离是手机屏幕宽度的9/10,top是扫描区域顶部离手机屏幕顶部的距离是手机屏幕宽度的1/3,bottom是扫描区域底部离手机屏幕顶部的距离是手机屏幕宽度的4/9

        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay(); PMwidth = display.getWidth();
PMheight = display.getHeight(); left = PMwidth/10;
top = PMheight/3;
right = PMwidth*9/10;
bottom = PMheight*4/9;
mFrameRect = new Rect(left,top,right,bottom);

画画

    @Override
public void onDraw(Canvas canvas) {
int width = PMwidth;
int height = PMheight;
Rect frame = mFrameRect; // 绘制焦点框外边的暗色背景
mPaint.setColor(mMaskColor);
canvas.drawRect(0, 0, width, frame.top, mPaint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, mPaint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, mPaint);
canvas.drawRect(0, frame.bottom + 1, width, height, mPaint); }

还没有完,还有布局文件放SurfaceView和按钮,还有刚才做的自定义View

2.显示Camera预览和Camera拍摄

这里SurfaceView如何显示Camera我不多说,只说如何把Camera预览变清晰,这里是通过循环自动对焦来完成。

设置自动对焦接口

mCamera.autoFocus(autoFocusCallback);

这个接口初始化传入了Handler

autoFocusCallback.setHandler(handler,MSG_AUTOFUCS);

然后这个接口实现类里,当完成自动对焦,会通过handler发送一个消息

    @Override
public void onAutoFocus(boolean success, Camera camera) {
Log.v("zzw", "autof focus "+success);
if (mAutoFocusHandler != null) {
mAutoFocusHandler.sendEmptyMessageDelayed(mAutoFocusMessage,AUTO_FOCUS_INTERVAL_MS);
// mAutoFocusHandler = null;
} else {
Log.v(TAG, "Got auto-focus callback, but no handler for it");
}
}

然后handler如何执行以下代码,再进行一次自动对焦,这样就完成了循环

                    case MSG_AUTOFUCS:
cameraUtil.autoFocus();
break;

然后给按钮赋予拍摄功能,拍摄的还要停止聚焦

                handler.removeCallbacksAndMessages(null);
cameraUtil.takePicture(TwoActivity.this,TwoActivity.this,TwoActivity.this);

这个函数会被调用,data就是图片数据

    @Override
public void onPictureTaken(byte[] data, Camera camera)

这里要注意一件事,拍摄后Camera预览界面就会停止,因为他停止聚焦了,我们需要重新设置自动对焦,并开启预览

    // 刷新相机
public void refreshCamera(){
if (surfaceHolder.getSurface() == null){
// preview surface does not exist
return;
} // stop preview before making changes
try {
mCamera.stopPreview();
} catch(Exception e){
// ignore: tried to stop a non-existent preview
} // set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) { }
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

3.处理图片数据,完成局部截图

继续在onPictureTaken函数的data数据处理

因为处理图片是耗时任务,所以开启子线程完成

这里先开启一个等待对话框

        if(!mypDialog.isShowing())
mypDialog.show();

然后开启子线程

        if(data != null){
new Thread(new BitmapThread(bitmap,data,handler,TwoActivity.this)).start(); }

将data转换为Bitmap数据

        bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

将图片旋转90度

        bitmap = rotateBitmap(bitmap,90);

这是旋转Bitmap的函数

    public static Bitmap rotateBitmap(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

切割Bitmap,将扫描区域的图片切割出来

        int PMwidth = bitmap.getWidth(); // 得到图片的宽,高
int PMheight = bitmap.getHeight(); int left = PMwidth/10;
int top = PMheight/3;
int right = PMwidth*9/10;
int bottom = PMheight*4/9;
int width = right - left;
int height = bottom - top; Log.v("zzw",PMheight+" "+PMwidth); bitmap = Bitmap.createBitmap(bitmap, left, top, width, height, null,
false);

4.扫描出结果

其实tess-two框架的使用很简单,但是使用这个框架需要依靠训练文件来完成扫描,我在res目录下放了raw文件夹,里面的eng_traineddata文件就是这个用途,但是我们不能直接使用它们,我们需要将他们复制到手机存储里

下面的代码意思是在应用私有路径里创建tesseract/tessdata/eng.traineddata相关路径的文件并使用输入流将文件的数据读出来,然后使用输出流将数据传入eng.traineddata文件

    public static void initTessTrainedData(Context context){

        if(initiated){
return;
} File appFolder = context.getFilesDir();
File folder = new File(appFolder, tessdir);
if(!folder.exists()){
folder.mkdir();
} tesseractFolder = folder.getAbsolutePath(); File subfolder = new File(folder, subdir);
if(!subfolder.exists()){
subfolder.mkdir();
} File file = new File(subfolder, filename);
trainedDataPath = file.getAbsolutePath();
Log.d(TAG, "Trained data filepath: " + trainedDataPath); if(!file.exists()) { try {
FileOutputStream fileOutputStream;
byte[] bytes = readRawTrainingData(context);
if (bytes == null){
return;
} fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(bytes);
fileOutputStream.close();
initiated = true;
Log.d(TAG, "Prepared training data file");
} catch (FileNotFoundException e) {
Log.e(TAG, "Error opening training data file\n" + e.getMessage());
} catch (IOException e) {
Log.e(TAG, "Error opening training data file\n" + e.getMessage());
}
}
else{
initiated = true;
}
}

好了再说说tess-two框架的使用

创建TessBaseAPI

        TessBaseAPI tessBaseAPI = new TessBaseAPI();

关闭测试

        tessBaseAPI.setDebug(true);

设置训练数据路径和识别文字是英文

        tessBaseAPI.init(path, "eng");

设置白名单

        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");

设置黑名单

        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=-[]}{;:'\"\\|~`,./<>?"); 

设置识别模式

        tessBaseAPI.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_OSD);

传入bitmap数据

        tessBaseAPI.setImage(bitmap);

获取扫描结果

        String inspection = tessBaseAPI.getHOCRText(0);

结束TestBaseAPI的使用

        tessBaseAPI.end();

实现扫描身份证号码,这里是通过正则表达式来判断扫描出的结果是否有身份证号码,也就是说tess-two其实是只是扫描出Bitmap文件里面有哪些文字,然后使用正则表达式来筛选出我们需要的数据。也就是说我们通过换取正则表达式就能做到扫描手机号等,带有某种规律的数字或者字母

这是正则表达式的线上工具地址,大家可以自己试试 http://tool.oschina.net/regex/#

    private static Pattern pattern = Pattern.compile("\\d{17}[\\d|x]|\\d{15}");
public static String getTelNum(String sParam){
if(TextUtils.isEmpty(sParam)){
return "";
} Matcher matcher = pattern.matcher(sParam);
StringBuilder bf = new StringBuilder();
while (matcher.find()) {
bf.append(matcher.group()).append(",");
}
int len = bf.length();
if (len > 0) {
bf.deleteCharAt(len - 1);
}
return bf.toString();
}

然后通过handler返回结果

        Message message = Message.obtain();
message.what = 1;
Bundle bundle = new Bundle();
bundle.putString("decode",strDecode);
message.setData(bundle);
message.what = TwoActivity.MSG_BITMAP;
handler.sendMessage(message);

取消加载框,并将局部截图的图像和扫描的结果通过DialogFragment显示出来

                        mypDialog.dismiss();
String strDecode = msg.getData().getString("decode","扫描失败"); if(strDecode == null ||strDecode.equals(""))
strDecode = "扫描失败"; imageDialogFragment.setImage(bitmap);
imageDialogFragment.setText(strDecode);
imageDialogFragment.show(getFragmentManager(), "ImageDialogFragment");

5.结论

其实还没有结束因为我本想做出一个能够扫描整张身份证的项目,我看一下网上有很多API都能实现这个功能,但都要钱,如果要是能够实现这个功能,并发到github,我岂不是成为大神了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

博客首发地址
http://blog.csdn.net/z979451341

Android ORC文字识别之识别身份证号等(附源码)的更多相关文章

  1. Python的开源人脸识别库:离线识别率高达99.38%(附源码)

    Python的开源人脸识别库:离线识别率高达99.38%(附源码) 转https://cloud.tencent.com/developer/article/1359073   11.11 智慧上云 ...

  2. C# 30分钟完成百度人脸识别——进阶篇(文末附源码)

    距离上次入门篇时隔两个月才出这进阶篇,小编惭愧,对不住关注我的卡哇伊的小伙伴们,为此小编用这篇博来谢罪. 前面的准备工作我就不说了,注册百度账号api,创建web网站项目,引入动态链接库引入. 不了解 ...

  3. 【Android初级】如何动态添加菜单项(附源码+避坑)

    我们平时在开发过程中,为了灵活多变,除了使用静态的菜单,还有动态添加菜单的需求.今天要分享的功能如下: 在界面的右上角有个更多选项,点开后,有两个子菜单:关于和退出 点击"关于", ...

  4. Android 音视频深入 五 完美的录视频(附源码下载)

    本篇项目地址,名字是录视频,求star https://github.com/979451341/Audio-and-video-learning-materials 这一次的代码录视频在各个播放器都 ...

  5. Android 音视频深入 二 AudioTrack播放pcm(附源码下载)

    本篇项目地址,名字是录音和播放PCM,求starhttps://github.com/979451341/Audio-and-video-learning-materials 1.AudioTrack ...

  6. EasyPlayer Android安卓流媒体播放器实现播放同步录像功能实现(附源码)

    本文转自EasyDarwin团队John的博客:http://blog.csdn.net/jyt0551,John是EasyPusher安卓直播推流.EasyPlayer直播流媒体播放端的开发和维护者 ...

  7. Android 音视频深入 八 小视频录制(附源码下载)

    本篇项目地址,求starthttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/%E5%B0%8F%E ...

  8. Android 音视频深入 四 录视频MP4(附源码下载)

    本篇项目地址,名字是<录音视频(有的播放器不能放,而且没有时长显示)>,求star https://github.com/979451341/Audio-and-video-learnin ...

  9. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  10. C#/ASP.NET MVC微信公众号接口开发之从零开发(四) 微信自定义菜单(附源码)

    C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...

随机推荐

  1. mysql和oracle分页查询

    MYSQL分页查询 方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实现分 ...

  2. 自动弹出pickerview

    UIPickerView是开发中常用的控件,日期选择.年龄选择.城市的多级联动等等都会使用,它一般是在点击某个按钮后出现,展现方式和UITextView一样,从页面底部弹出,选中后或者点击控件以外区域 ...

  3. BZOJ5279: [Usaco2018 Open]Disruption

    题目大意:给你一棵n个节点的树,这n条边称为原边,另给出m条带权值的额外边,求删去每条原边后通过给出的m额外条边变回一棵树的最小价值.题解:看完题面以为是Tarjan连通性之类的题目,冷静分析后想到是 ...

  4. 【Django基本命令002】

    在mac或者window的终端直接输入这些命令(不是Python的shell中) 一.创建Django项目之前必须先激活 具体方法可以参考Python机器语言学习博客 二.开始新建项目 1.新建一个d ...

  5. HDU 2665 Kth number(主席树静态区间第K大)题解

    题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...

  6. [Redis] - redis实战1

    rememberMe>>>>:null Creating a new SqlSession SqlSession [org.apache.ibatis.session.defa ...

  7. stm32库函数建工程和使用Keil自带库建工程有没有区别?发现了同样的程序在两种情况下keil自带库可以运行的情况,不知是什么原因

    我使用库函数建的工程(非Keil自带库),为了实现SPI对Si24r1芯片数据的读写,以验证stm32是否可以和si24r1能够正常通信,发现使用库函数建的工程程序不能通过,读出来的数据和写的数据不一 ...

  8. Python链接Oracle数据库

    说明:以下所需安装的所有软件版本必须跟系统一致,即系统是64位,软件就得是64位,否则会出现各种链接报错的情况. 现以64位系统,python 3.6.5  64位为例: (一)安装cx_Oracle ...

  9. SAP ERP SD模块中维护销售人员

    SAP ERP SD模块中维护销售人员信息并分配销售组织   分类: SAPHCM用户指南   在SAP ERP系统,销售和分销(SD)模块中需要创建销售人员(Sales Personnels)消息, ...

  10. 代码生成器——实现生成pojo,sql,mapper接口

    代码生成器(记录一次兴趣代码,多多指教.转载请标明作者) 在我们开始实现代码生成器之前我们先来对代码生成器有一个简单的了解. 1.什么是代码生成器? 故名思义,也就是生成代码的一个程序.那它是一个什么 ...