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

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;
     }

三、源码包截图

blob.png

四、其他

Ok,就这样吧!核心也就这些东西,有问题的可以留言或私信,有好的解决办法也可以交流,,出于隐私,就把人家的信息打码, 不过识别出来准确度是100%。

 

猜你喜欢

转载自www.cnblogs.com/Alex80/p/11518534.html
今日推荐