Android 识别身份证号码(图片识别)
详细
前些天下午没什么事,朋友有个需求,说要识别身份证上面的身份证号码,刚好闲着,就帮他解决了一下,不说多完美,但是至少算是解决需求了,好了,闲话少说。
先来看一下我的DEMO吧
接下来我们一个个介绍
一、联网识别
也是从别人的Demo里截出来的,其实也是用的别人的一个在线接口,但是我看了看应该算“非正常调用”(这个意思大家自己理解吧)。下面分析一下这个方法的优劣点吧。
优点:速度极快,上传照片,会返回身份证上所有信息,包括姓名 地址 出生等等
缺点:“非正常”调用就有一定的不可靠性,如果哪天人家关了或者改了这个接口,就比较尴尬了,当然你可以选择购买人家的正式版。
二、本地识别
基于Tess_two做的识别,这个大家可放心使用。先看一下大概怎么使用吧!
首先引用:
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%。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2016-09-14 黄聪: Bootstrap之Form表单验证神器: BootstrapValidator(转)
2015-09-14 jQuery 获取屏幕高度、宽度