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


    概述

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

    详细

    前些天下午没什么事,朋友有个需求,说要识别身份证上面的身份证号码,刚好闲着,就帮他解决了一下,不说多完美,但是至少算是解决需求了,好了,闲话少说。

    先来看一下我的DEMO吧

    接下来我们一个个介绍

    一、联网识别

    也是从别人的Demo里截出来的,其实也是用的别人的一个在线接口,但是我看了看应该算“非正常调用”(这个意思大家自己理解吧)。下面分析一下这个方法的优劣点吧。

    优点:速度极快,上传照片,会返回身份证上所有信息,包括姓名 地址 出生等等

    缺点:“非正常”调用就有一定的不可靠性,如果哪天人家关了或者改了这个接口,就比较尴尬了,当然你可以选择购买人家的正式版。

    二、本地识别

    基于Tess_two做的识别,这个大家可放心使用。先看一下大概怎么使用吧!

    首先引用:

    compile 'com.rmtheis:tess-two:6.0.0'

    然后使用,其实使用起来很简单,但是要注意几点

    1.要在SD卡有他的识别库,这个库你可以理解为一个字典,这个字典可以自己训练,因为我是用的别人训练好的(只包含英文和数字),所以就不说怎么训练了,百度一下会有很多。

    2.需要注意的是,放他字典的路径文件夹名必须为“tessdata”,否则报错

    好了,准备工作做好了,接下来介绍怎么使用,我直接贴核心代码,代码有注释,看不懂的留言或者私信我

    //训练数据路径,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研究。

    /**
         * 摄像头数据回调
         * @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%。

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    Android 编程代码手机定位
    Android 编程下快捷图标的创建
    Android 编程技巧设置 ADB 连接超时时间
    Android 编程下获得应用程序的签名
    Android 编程下如何获取有 Internet 访问权限的应用
    Android 编程下通知的发送
    Androidpn 消息推送总结
    Json 和 Jsonlib 的使用
    asp.net 控件不显示,提示无法找到
    做一课永远成长的苹果树!
  • 原文地址:https://www.cnblogs.com/demodashi/p/8491133.html
Copyright © 2020-2023  润新知