Android 身份证号码识别 (本地,在线,实时),网络识别用的别人的接口,不保障什么时候就用不了了,本地识别基于tess_two,位置对的话识别准确率达到90%以上。
详细
前些天下午没什么事,朋友有个需求,说要识别身份证上面的身份证号码,刚好闲着,就帮他解决了一下,不说多完美,但是至少算是解决需求了,好了,闲话少说。
先来看一下我的DEMO吧
接下来我们一个个介绍
一、联网识别
也是从别人的Demo里截出来的,其实也是用的别人的一个在线接口,但是我看了看应该算“非正常调用”(这个意思大家自己理解吧)。下面分析一下这个方法的优劣点吧。
优点:速度极快,上传照片,会返回身份证上所有信息,包括姓名 地址 出生等等
缺点:“非正常”调用就有一定的不可靠性,如果哪天人家关了或者改了这个接口,就比较尴尬了,当然你可以选择购买人家的正式版。
二、本地识别
基于Tess_two做的识别,这个大家可放心使用。先看一下大概怎么使用吧!
扫描二维码关注公众号,回复:
7277102 查看本文章
首先引用:
1
|
compile
'com.rmtheis:tess-two:6.0.0'
|
然后使用,其实使用起来很简单,但是要注意几点
1.要在SD卡有他的识别库,这个库你可以理解为一个字典,这个字典可以自己训练,因为我是用的别人训练好的(只包含英文和数字),所以就不说怎么训练了,百度一下会有很多。
2.需要注意的是,放他字典的路径文件夹名必须为“tessdata”,否则报错
好了,准备工作做好了,接下来介绍怎么使用,我直接贴核心代码,代码有注释,看不懂的留言或者私信我
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
|
//训练数据路径,tessdata
static
final
String TESSBASE_PATH = Environment.getExternalStorageDirectory() +
"/"
;
//识别语言英文
static
final
String DEFAULT_LANGUAGE =
"eng"
;
/**
* 传SD卡图片路径(当然你们也可以传Bitmap)
* @param url
*/
private
void
localre(String url) {
//把图片转为Bitmap
Bitmap bmp = BitmapFactory.decodeFile(url);
//创建Tess
final
TessBaseAPI baseApi =
new
TessBaseAPI();
//下面这一块代码为裁取身份证号码区域(否则识别乱码,不准确)
int
x, y, w, h;
x = (
int
) (bmp.getWidth() *
0.340
);
y = (
int
) (bmp.getHeight() *
0.800
);
w = (
int
) (bmp.getWidth() *
0.6
+
0
.5f);
h = (
int
) (bmp.getHeight() *
0.12
+
0
.5f);
Bitmap bit_hm = Bitmap.createBitmap(bmp, x, y, w, h);
//这个只是我将裁取的号码区展示在了一个ImageView上,这个可以没有
iv_number.setImageBitmap(bit_hm);
//初始化OCR的训练数据路径与语言
baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
//设置识别模式
baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_SINGLE_LINE);
//设置要识别的图片
baseApi.setImage(bit_hm);
//设置字典白名单
baseApi.setVariable(
"tessedit_char_whitelist"
,
"0123456789Xx"
);
//把识别内容设置到EditText里
tv_result.setText(baseApi.getUTF8Text());
//收尾
baseApi.clear();
baseApi.end();
}
|
OK,就这么简单,图片清晰切裁取区域正确的情况下,准确度几乎100%;
给大家举个身份证照片的例子吧,否则裁取号码会不
上一张结果图
实时识别
其实就是本地识别的拓展版,把摄像头的数据转为Bitmap,去识别,还是贴核心代码吧,看不懂的自己下Demo研究。
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
|
/**
* 摄像头数据回调
* @param data
* @param camera
*/
@Override
public
void
onPreviewFrame(
byte
[] data, Camera camera) {
camera.addCallbackBuffer(data);
//将byte数组转为Bitmap
ByteArrayOutputStream baos;
byte
[] rawImage;
Bitmap bitmap;
Camera.Size previewSize = camera.getParameters().getPreviewSize();
//获取尺寸,格式转换的时候要用到
BitmapFactory.Options newOpts =
new
BitmapFactory.Options();
newOpts.inJustDecodeBounds =
true
;
YuvImage yuvimage =
new
YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null
);
baos =
new
ByteArrayOutputStream();
yuvimage.compressToJpeg(
new
Rect(
0
,
0
, previewSize.width, previewSize.height),
100
, baos);
// 80--JPG图片的质量[0-100],100最高
rawImage = baos.toByteArray();
//将rawImage转换成bitmap
BitmapFactory.Options options =
new
BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
bitmap = BitmapFactory.decodeByteArray(rawImage,
0
, rawImage.length, options);
if
(bitmap ==
null
) {
Log.d(
"zka"
,
"bitmap is nlll"
);
return
;
}
else
{
//裁取图片中央身份证区域
int
height = bitmap.getHeight();
int
width = bitmap.getWidth();
final
Bitmap bitmap1 = Bitmap.createBitmap(bitmap, width/
2
- dip2px(
150
),height /
2
- dip2px(
92
), dip2px(
300
), dip2px(
185
));
//截取身份证号码区域
int
x, y, w, h;
x = (
int
) (bitmap1.getWidth() *
0.340
);
y = (
int
) (bitmap1.getHeight() *
0.800
);
w = (
int
) (bitmap1.getWidth() *
0.6
+
0
.5f);
h = (
int
) (bitmap1.getHeight() *
0.12
+
0
.5f);
Bitmap bit_hm = Bitmap.createBitmap(bitmap1, x, y, w, h);
// 识别
if
(bit_hm !=
null
){
String localre = localre(bit_hm);
if
(localre.length() ==
18
) {
Log.e(TAG,
"onPreviewFrame: "
+localre );
Toast.makeText(getApplicationContext(),localre,Toast.LENGTH_SHORT).show();
}
}
}
}
/**
* 识别
* @param bm
* @return
*/
private
String localre(Bitmap bm) {
String content =
""
;
bm = bm.copy(Bitmap.Config.ARGB_8888,
true
);
iv_result.setImageBitmap(bm);
TessBaseAPI baseApi =
new
TessBaseAPI();
baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
//设置识别模式
baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_SINGLE_LINE);
//设置要识别的图片
baseApi.setImage(bm);
baseApi.setVariable(
"tessedit_char_whitelist"
,
"0123456789Xx"
);
Log.e(TAG,
"localre: "
+ baseApi.getUTF8Text());
content = baseApi.getUTF8Text();
baseApi.clear();
baseApi.end();
return
content;
}
|
三、源码包截图
四、其他
Ok,就这样吧!核心也就这些东西,有问题的可以留言或私信,有好的解决办法也可以交流,,出于隐私,就把人家的信息打码, 不过识别出来准确度是100%。