踩了不少坑,终于把这个扫描版的身份证识别做出来了,图片识别引擎用的是tesseract,在已经训练好样本的情况下,感觉识别率还是一般般~ 
下面说一说大概几个坑、

一、 编译tesseract-orc Android版本 
首先你需要Android-ndk工具,Android ndk开发,我们这里不做开发,只需要编译tesseract变成so文件、tesseract Android版下载地址,这里只需要编译tesseract-two这个项目、编译方法在那篇博客说的很清楚了,编译时间有点久(耐心等待,并且大部分人在这里会扑街)

二、测试是否编译成功 
新建一个项目,用引用类库的方式引用tesseract-two,API的调用方法也很简单:

TessBaseAPI baseApi=new TessBaseAPI();
//这里进行初始化,第一个参数是训练语言的路径,第二个参数的语言名字,后面我们的训练文件都要放在这里面,这里可以先用eng代替下测试、
baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
baseApi.setPageSegMode(TessBaseAPI.PSM_AUTO);
//这里把图片放进去进行了
baseApi.setImage(bitmap);
final String outputText = baseApi.getUTF8Text();
Log.i(TAG, "识别结果:" + outputText);
baseApi.end();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上述就是整个API的调用流程,值得注意的是,该流程是一个耗时操作,不可在UI线程中调用、 
若没有闪退,并且有大概的识别文字出来,表示编译成功,接下来就开始训练新语言。

三、训练新语言,提高识别率 
说到训练语言这个问题,网上的文章是非常多的,不过我却在这里卡了很久,原因是因为网上大部分文章是针对3.01版本训练,而现在版本是3.02,有几个地方死活报错过不去、寻其原因在于文件名的问题!tesseract-orc3.02训练方法 这篇博客已经说的很清楚啦,我再把精简一下: 
图片名字的格式 一定需要按照 [lang].[fontname].exp[num].tif 该格式!用id.custom.exp0.tif 作为示范

1).转成 tif 格式图片,用jTessBoxEditor工具 合成为一张tif图片

2).生成box文件,调用命令行: 
tesseract id.custom.exp0.tif id.custom.exp0 batch.nochop makebox

3).利用jTessBoxEditor工具,对文件进行编辑,校正,得到新的box文件

4).生成.tr文件,调用命令行: 
tesseract id.custom.exp0.tif id.custom.exp0 nobatch box.train

5).生成字符集,调用命令行: 
unicharset_extractor id.custom.exp0.box

6).设置字体,新建文本文件font_properties,里面输入字体信息,内容格式为: 
第一个fontname 一定要对应之前文件的名字, 这里输入 custom 0 1 0 0 0 ,表示是加粗字体格式

7).接下来,进行聚合,分别调用三句命令: 
shapeclustering -F font_properties -U unicharset id.custom.exp0.tr 
mftraining -F font_properties -U unicharset -O id.unicharset id.custom.exp0.tr 
cntraining id.custom.exp0.tr id.custom.exp0.tr

8).把生成第7步生成的4个文件加入前缀“id.”(),调用命令行,生成最终数据 
combine_tessdata id. (别漏掉了.) 
type 1,type3, type4, type5对应的后面数据如果不是-1,就表示这次训练成功!

9).进行测试: 
tesseract id1.jpg output -l id

四、集成到项目中实现拍照识别 
如果上述训练没有问题,那么可以将训练文件 id.traineddata 放在assert文件夹中,当应用程序启动时,将其拷贝到sd卡,这里值得注意的是,拍照返回的图片都比较大,是需要进行压缩的、最终大小尽量和你训练时的大小一致,然后图片进行灰度处理,再调用API来识别。

五、扫描识别 
由于拍照后再识别的准确率实在是低,和拍照的角度,光线,以及拍照时身份证没有填满照片等等因素,很难做到高准确率的识别、于是我就仿造扫描二维码(支付宝扫描银行卡号)的方式,来增加识别次数提高识别率。扫描界面我是借鉴二维码扫描的代码、大致流程: 
需要一个Camera对象来获取相机资源,用一个SurfaceView来显示相机预览,surfaceview启动时获取相机资源,并且实现自动对焦和预览回调接口,自动对焦是定时的,每过1.5秒对焦一次、而在预览回调接口中:

    /**
* 拍照回调
*/
PreviewCallback previewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
if (isChoice) {
new MyOrcTask().execute(data);
isChoice = false;
} }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们把图片处理,图片识别放在了异步任务中,因为该接口是不停的回调的、每次传进一张照片进入后,把标志改为false,当异步任务执行完后,把标志改为true,这样就是单线程异步的执行图片识别任务、

/**
* 图片解析的异步任务!
*
* @author kaifa
*
*/
class MyOrcTask extends AsyncTask<byte[], Void, Void> { String text = ""; @Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
} @Override
protected Void doInBackground(byte[]... params) {
// TODO Auto-generated method stub
byte[] data = params[0]; Size size = camera.getParameters().getPreviewSize();
try {
YuvImage image = new YuvImage(data, ImageFormat.NV21,
size.width, size.height, null);
if (image != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(
new Rect(0, 0, size.width, size.height), 80, stream);
Bitmap bitmap = BitmapFactory.decodeByteArray(
stream.toByteArray(), 0, stream.size()); bitmap = Bitmap.createBitmap(bitmap, x, y, width, height);
// 去解析
if (bitmap != null) { bitmap = comp(bitmap);
bitmap = ImageFilter.grayScale(bitmap);
TessBaseAPI baseAPI = new TessBaseAPI();
// 初始化
baseAPI.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
baseAPI.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO); baseAPI.setImage(bitmap); text = baseAPI.getUTF8Text(); baseAPI.end();
} stream.close(); }
} catch (Exception ex) {
Log.e("Sys", "Error:" + ex.getMessage());
} return null;
} @Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
text.replaceAll("\n", "");
text = text.trim();
if (text.length() > 18) {
text = text.substring(text.length() - 18, text.length());
if (IDcheckClassUtil.validateIdCard18(text)) {
Toast.makeText(ScanActivity.this, "成功!请核对", 0).show();
isChoice = false;
textView.setText(text);
} else {
// Toast.makeText(ScanActivity.this, "就差一点点啦!", 0).show();
isChoice = true;
} } else {
// Toast.makeText(ScanActivity.this, "请再对齐一点点哦!", 0).show();
// 继续去选择图片
isChoice = true;
} }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

很多人都要代码,源码在这~

Android tesseract-orc之扫描身份证号码的更多相关文章

  1. Android之利用正则表达式校验邮箱、手机号、密码、身份证号码等

    概述 现在Android应用在注册的时候基本会校验邮箱.手机号.密码.身份证号码其中一项或多项,特此收集了相关的正则表达式给大家分享.除了正则表达式,文章末尾提供Demo中有惊喜哦! 具体验证的图片效 ...

  2. Android 识别身份证号码(图片识别)

    概述 Android 身份证号码识别 (本地,在线,实时),网络识别用的别人的接口,不保障什么时候就用不了了,本地识别基于tess_two,位置对的话识别准确率达到90%以上. 详细 代码下载:htt ...

  3. Android 身份证号码查询、手机号码查询、天气查询

    1.基本信息 身份证号码查询:http://apistore.baidu.com/apiworks/servicedetail/113.html 手机号码:http://apistore.baidu. ...

  4. iOS身份证号码识别

    一.前言   身份证识别,又称OCR技术.OCR技术是光学字符识别的缩写,是通过扫描等光学输入方式将各种票据.报刊.书籍.文稿及其它印刷品的文字转化为图像信息,再利用文字识别技术将图像信息转化为可以使 ...

  5. 【代码笔记】iOS-由身份证号码返回性别

    一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. ...

  6. Javascript身份证号码验证

    "来来来,坐这儿". "什么?我可是有身份的人,怎么能和你坐一块儿".沛笠晃了晃手里的身份证,不屑说道. "你咋不上天呢?有身份还喝油条吃豆浆&quo ...

  7. php验证身份证号码的正确性

    /********************php验证身份证号码是否正确函数*********************/function is_idcard( $id ) {   $id = strto ...

  8. JS身份证号码校验

    var Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 ]; // 加权因子 var ValideCode = [ 1, 0 ...

  9. js正则实现二代身份证号码验证详解

    js正则实现二代身份证号码验证详解 根据[中华人民共和国国家标准 GB 11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至 ...

随机推荐

  1. Mac下brew/memcached/nginx/iterm/zsh的安装

    brew  https://www.cnblogs.com/fireworld/p/8609190.html memcached https://blog.csdn.net/whereismatrix ...

  2. Android 设计原则【转载+整理】

    原文地址 本文内容 吸引我的眼球 简化我的生活 让我眼前一亮 在使用过大量 Android APP 后,你会发现,遵循了下面这些原则的 APP 将会有更好的用户体验. 我们知道,往往国企的那些软件,都 ...

  3. Android Activity 及其子类

    本文内容 ListActivity TabActivity LauncherActivity ExpandableListActivity PerferenceActivity 这些类都继承 Acti ...

  4. 使用Feign时报错Service id not legal hostname

    报错Service id not legal hostname的原因是服务名称不能带有下划线,可以使用中划线

  5. mssql批量删除数据库里所有的表

    go declare @tbname varchar(250) declare #tb cursor for select name from sysobjects where objectprope ...

  6. CSS 之 样式优先级机制

    多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使多重样式的情况. 1.一般情况下,优先级从低到高,如下: 浏览器缺省(即浏览器默认) →(外部样 ...

  7. DbScopeFactory

    using (var db = DbScopeFactory.Create()) { //这里修改数据 db.SaveChanges(); }

  8. JAVA GC优化入门

    为什么需要优化GC? JAVA的GC是面试必考的题目,可是在实际项目中什么时候使用GC哪?或者应该什么时候优化GC哪?有句名言:“GC优化永远是最后一项任务”. 在使用GC之前,应该考虑一下进行GC的 ...

  9. top高级技能

    默认输入top命令后进入的是交互模式,默认显示的TOP程序界面如下图所示: 我们注意到进程的内存区域数据很长一串,主要是因为这里用的单位是k表示的,我们可以修改显示的单位,在界面上直接输入E可以改变显 ...

  10. MySQL 批量杀mysql线程

    mysql> SELECT concat('KILL ',id,';') FROM information_schema.processlist WHERE user='root'; +---- ...