人工智能:身份证识别(OCR技术)

1.什么是身份证识别

身份证识别是指使用技术对身份证信息自动提取,并对身份证信息按要素格式化输出信息,供计算机系统管理。
目前身份证识别技术上有两种方式:
1、传统读卡器识别;
2、利用OCR技术识别,通过移动终端摄像头对身份证拍照,采集身份证信息。


接下来的要说的就是利用OCR技术识别身份证号码并抽取以及转化成文字显示

2.废话不都说,上demo运行演示

demo运行演示

3.主要使用技术

1.C++层使用的是opencv,主要是图形图像处理
2.java层使用的是google 提供的tess-two

) ,主要是光学字符识别

4.原理

4.1.身份证识别流程图

身份证件识别流程

OpenCv实现流程

4.2.什么是灰度化

将彩色图像转化成为灰度图像的过程称为图像的灰度化处理
灰度化:在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色(比如#AAAAAA和#333333的颜色显示都是灰色系列),其中R=G=B的值叫灰度值,因此,灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。
彩色图像中的每个像素的颜色有R、G、B三个分量决定,而每个分量有255个值可取,这样一个像素点可以有1600多万(255255255)的颜色的变化范围。而灰度图像一个像素点的变化范围为255种,所以在数字图像处理中一般先将各种格式的图像转变成灰度图像以使后续的图像的计算量变得少一些。灰度图像的描述与彩色图像一样仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征。

4.3.彩色图像进行灰度化处理方法:分量法、最大值法、平均值法、加权平均法。

转摘处:https://www.jianshu.com/p/6d7539edad97

4.3.1. 分量法
将彩色图像中的三分量的亮度作为三个灰度图像的灰度值,可根据应用需要选取一种灰度图像。

f1(i,j)=R(i,j) 
f2(i,j)=G(i,j) 
f3(i,j)=B(i,j)
其中fk(i,j)(k=1,2,3)为转换后的灰度图像在(i,j)处的灰度值。

4.3.2. 最大值法
将彩色图像中的三分量亮度的最大值作为灰度图的灰度值。

f(i,j)=max(R(i,j),G(i,j),B(i,j))

4.3.3. 平均值法
将彩色图像中的三分量亮度求平均得到一个灰度值。

f(i,j)=(R(i,j)+G(i,j)+B(i,j)) /3

4.3.4. 加权平均法
根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。

f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))

4.3.5.Opencv对图像灰度化处理
在Opencv中可以通过以上几种方法的数值计算来得到灰度图像也可以通过opencv提供的颜色空间转换函数来得到。
Opencv封装灰度法

    //灰度化
    cvtColor(src_img, dst_img, COLOR_BGR2GRAY);

5.图像二值化

图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。

    Opencv对图像二值化处理: 这里获取的是100~255
    cv::threshold(dst, dst, 100, 255, CV_THRESH_BINARY);

6.腐蚀膨胀(简单理解)

膨胀算法使图像扩大一圈。
腐蚀算法使二值图像减小一圈。
腐蚀:删除对象边界的某些像素
膨胀:给图像中的对象边界添加像素

    //加水膨胀,发酵
    Mat erodeElement = getStructuringElement(MORPH_RECT, Size(20, 10));
    erode(dst, dst, erodeElement);

7.轮廓检测

说白了,就是将符合检测的图片区域检测出来并裁剪

  vector< vector<Point> > contours;
    vector<Rect> rects;
    //opencv提供的检测方法
    cv:: findContours(dst, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    for (int i = 0; i < contours.size(); i++) {
        Rect rect = boundingRect(contours.at(i));
        if (rect.width > rect.height * 9) {
            //满足width:height>9:1就放在rects集合中
            rects.push_back(rect);
             // 在dst 图片上显示 rect 矩形
            rectangle(dst, rect, Scalar(0,255,255));
            dst_img = src_img(rect);
        }
    }
  if (rects.size() == 1) {
      //如果rects集合中只有一个,直接获取即可
        Rect rect = rects.at(0);
        dst_img = src_img(rect);
    }else {
        //存在多个的情况
        int lowPoint = 0;
        Rect finalRect;
        for (int i = 0; i < rects.size(); i++)  {
            Rect rect = rects.at(i);
            Point p = rect.tl();
            if (rect.tl().y > lowPoint) {
                //循环检测y坐标最高的并获取
                lowPoint = rect.tl().y;
                finalRect = rect;
            }
        }
        rectangle(dst, finalRect, Scalar(255, 255, 0));
        //获取最终的Rect进行切割
        dst_img = src_img(finalRect);
    }
    jobject  bitmap = createBitmap(env,dst_img,config);

在jni层反射创建Bitmap

jobject createBitmap(JNIEnv *env, Mat srcData, jobject config) {
     //通过jni反射创建Bitmap
    int imgWidth = srcData.cols;
    int imgHeight = srcData.rows;
    int numPix = imgWidth * imgHeight;
    jclass bmpCls = env->FindClass("android/graphics/Bitmap");
    jmethodID createBitmapMid = env->GetStaticMethodID(bmpCls, "createBitmap",
                                                       "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
    jobject jBmpObj = env->CallStaticObjectMethod(bmpCls, createBitmapMid, imgWidth, imgHeight,
                                                  config);
    Java_org_opencv_android_Utils_nMatToBitmap(env, 0, (jlong) &srcData, jBmpObj);
    return jBmpObj;
}

8.tess-two

tess-two是Tesseract在Android平台上的移植。
主要功能是通过样本和图片进行比对,从而将图片转换成文字
样本的训练请参考https://blog.csdn.net/sylsjane/article/details/83751297
build.gradle配置

       implementation 'com.rmtheis:tess-two:8.0.0'
new Thread(new Runnable() {
    @Override
    public void run() {
           baseApi = new TessBaseAPI();
                try {
                    InputStream is = null;
                    is = getAssets().open(language + ".traineddata");
                    File file = new File("/sdcard/tess/tessdata/" + language + ".traineddata");
                    if (!file.exists()) {
                        file.getParentFile().mkdirs();
                        FileOutputStream fos = new FileOutputStream(file);
                        byte[] buffer = new byte[2048];
                        int len;
                        while ((len = is.read(buffer)) != -1) {
                            fos.write(buffer, 0, len);
                        }
                        fos.close();
                    }
                    is.close();
                    //初始化TessBaseAPI
                    return baseApi.init("/sdcard/tess", language);
                } catch (IOException e) {
                    e.printStackTrace();
                }
    }
});
//查找ID
 public void searchId(View view) {
        tesstext.setText(null);
        ResultImage = null;
        Bitmap bitmapResult = ImageProcess.getIdNumber(fullImage, Bitmap.Config.ARGB_8888);
        fullImage.recycle();
        ResultImage = bitmapResult;
        //tesseract-ocr
        idCard.setImageBitmap(bitmapResult);
    }

 //识别文字并显示
public void recognition(View view) {
        // 识别Bitmap中的图片
        baseApi.setImage(ResultImage);
        tesstext.setText(baseApi.getUTF8Text());
        baseApi.clear();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容