检测国民身份证并获取详细信息 [英] Detecting the National ID card and getting the details

查看:289
本文介绍了检测国民身份证并获取详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图检测下面类型的国家ID,并获得它的详细信息,例如签名的位置应该在人物图像的右上角,在这种情况下,BC。 / p>



我需要在iphone中做这个应用程序。我想到使用Opencv为它,但如何实现标记的细节?我需要用类似的类型训练应用程序卡或OCR可以帮助?



移动应用程序有什么具体实现吗?



我还通过card-io检测到信用卡详细信息,卡io检测其他卡的详细信息吗?



我使用了 tesseract 进行文本检测。如果图像只有文字,Tesseract效果很好。所以我裁剪了红色标记的区域,并作为输入给Tesseract,它的MRZ部分很好。



有一个 IOS实现为Tesseract,我已经测试。



do?



现在我想自动化文本检测部分。现在我打算自动化以下项目,



1)裁剪面孔(我使用了Viola-jones面部检测器)。



2)需要从照片中获取初始值BC。



3)从ID中提取/检测MRZ区域



我试图做2&

解决方案

假设这些ID是根据具有特定宽度的标准模板准备的,高度,偏移,间距等,您可以尝试基于模板的方法。



MRZ将很容易被检测到。一旦在图像中检测到它,请找到将模板中的MRZ映射到其中的转换。当你知道这个转换时,你可以将模板上的任何区域(例如,个人的照片)映射到图像并提取该区域。



简单的程序,遵循一个快乐的路径。您将必须进行更多处理以查找一般的机读区(例如,如果有透视失真或旋转)。我只是通过测量图像准备模板,它不会为您的情况工作。我只是想表达这个想法。图片来自维基

  Mat rgb = imread(INPUT_FILE); 
Mat gray;
cvtColor(rgb,gray,CV_BGR2GRAY);

Mat grad;
Mat morphKernel = getStructuringElement(MORPH_ELLIPSE,Size(3,3));
morphologyEx(gray,grad,MORPH_GRADIENT,morphKernel);

Mat bw;
threshold(grad,bw,0.0,255.0,THRESH_BINARY | THRESH_OTSU);

//连接水平定向区域
Mat connected;
morphKernel = getStructuringElement(MORPH_RECT,Size(9,1));
morphologyEx(bw,connected,MORPH_CLOSE,morphKernel);

//找到轮廓
Mat mask = Mat :: zeros(bw.size(),CV_8UC1);
vector< vector< Point>>轮廓;
vector< Vec4i>层次;
findContours(connected,contour,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE,Point(0,0));

vector< Rect> mrz;
double r = 0;
//过滤器轮廓
for(int idx = 0; idx> = 0; idx = hierarchy [idx] [0])
{
Rect rect = boundingRect [idx]);
r = rect.height? (double)(rect.width / rect.height):0;
if((rect.width> connected.cols * .7)&& / * filter from rect width * /
(r> 25)&& / * :hight ratio * /
(r <36)/ * filter from width:hight ratio * /

{
mrz.push_back(rect);
rectangle(rgb,rect,Scalar(0,255,0),1);
}
else
{
rectangle(rgb,rect,Scalar(0,0,255),1);
}
}
if(2 == mrz.size())
{
//假设我们在MRZ中找到了两个数据条,
CvRect max = cvMaxRect(&(CvRect)mrz [0],&(CvRect)mrz [1]);
rectangle(rgb,max,Scalar(255,0,0),2); // draw the MRZ

vector< Point2f> mrzSrc;
vector< Point2f> mrzDst;

//我们的图像中的MRZ区域
mrzDst.push_back(Point2f((float)max.x,(float)max.y));
mrzDst.push_back(Point2f((float)(max.x + max.width),(float)max.y));
mrzDst.push_back(Point2f((float)(max.x + max.width),(float)(max.y + max.height)));
mrzDst.push_back(Point2f((float)max.x,(float)(max.y + max.height)));

// MRZ在我们的模板
mrzSrc.push_back(Point2f(0.23f,9.3f));
mrzSrc.push_back(Point2f(18.0f,9.3f));
mrzSrc.push_back(Point2f(18.0f,10.9f));
mrzSrc.push_back(Point2f(0.23f,10.9f));

//找到转换
Mat t = getPerspectiveTransform(mrzSrc,mrzDst);

//我们的模板中的照片区域
矢量< Point2f> photoSrc;
photoSrc.push_back(Point2f(0.0f,0.0f));
photoSrc.push_back(Point2f(5.66f,0.0f));
photoSrc.push_back(Point2f(5.66f,7.16f));
photoSrc.push_back(Point2f(0.0f,7.16f));

//我们的模板中的姓名区域
vector< Point2f>姓氏
surnameSrc.push_back(Point2f(6.4f,0.7f));
surnameSrc.push_back(Point2f(8.96f,0.7f));
surnameSrc.push_back(Point2f(8.96f,1.2f));
surnameSrc.push_back(Point2f(6.4f,1.2f));

vector< Point2f> photoDst(4);
vector< Point2f> surnameDst(4);

//将区域从我们的模板映射到图像
perspectiveTransform(photoSrc,photoDst,t);
perspectiveTransform(surnameSrc,surnameDst,t);
//绘制映射的区域
for(int i = 0; i <4; i ++)
{
line(rgb,photoDst [i],photoDst [ +1)%4],Scalar(0,128,255),2);
}
for(int i = 0; i <4; i ++)
{
line(rgb,surnameDst [i],surnameDst [(i + 1)%4 ],Scalar(0,128,255),2);
}
}

结果:照片和姓氏区域为橙色。 MRZ在蓝色。


I am trying to detect the National ID of the below type and get the details of it, For example the location of the signature should be found at the top right corner of the persons image, in this case "BC".

I need to do this application in iphone. I thought of using Opencv for it but how can I achieve the marked details? Do I need to train the application with similar kind Cards or OCR could help?

Is there any specific implementations for mobile applications?

I also gone through card-io which detects the credit card details, does Card-io detects the other card details also?

Update:

I have used tesseract for text detection. Tesseract works good if the image has text alone. So I cropped the red marked regions and given as input to Tesseract, it works good with the MRZ part.

There is a IOS implementation for Tesseract, with which I have tested.

What I need to do?

Now I am trying to automate the text detection part. Now I am planning to automate the following items,

1) Cropping the Face ( I have done using Viola-jones face detector ).

2) Need to take the Initial in this example "BC" from the Photo.

3) Extracting/detecting the MRZ region from the ID card.

I am trying to do 2 & 3, Any ideas or code snippets would be great.

解决方案

Assuming these IDs are prepared according to a standard template having specific widths, heights, offsets, spacing etc., you can try a template based approach.

MRZ would be easy to detect. Once you detect it in the image, find the transformation that maps the MRZ in your template to it. When you know this transformation you can map any region on your template (for example, the photo of the individual) to the image and extract that region.

Below is a very simple program that follows a happy path. You will have to do more processing to locate the MRZ in general (for example, if there are perspective distortions or rotations). I prepared the template just by measuring the image, and it won't work for your case. I just wanted to convey the idea. Image was taken from wiki

    Mat rgb = imread(INPUT_FILE);
    Mat gray;
    cvtColor(rgb, gray, CV_BGR2GRAY);

    Mat grad;
    Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    morphologyEx(gray, grad, MORPH_GRADIENT, morphKernel);

    Mat bw;
    threshold(grad, bw, 0.0, 255.0, THRESH_BINARY | THRESH_OTSU);

    // connect horizontally oriented regions
    Mat connected;
    morphKernel = getStructuringElement(MORPH_RECT, Size(9, 1));
    morphologyEx(bw, connected, MORPH_CLOSE, morphKernel);

    // find contours
    Mat mask = Mat::zeros(bw.size(), CV_8UC1);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(connected, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    vector<Rect> mrz;
    double r = 0;
    // filter contours
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
    {
        Rect rect = boundingRect(contours[idx]);
        r = rect.height ? (double)(rect.width/rect.height) : 0;
        if ((rect.width > connected.cols * .7) && /* filter from rect width */
            (r > 25) && /* filter from width:hight ratio */
            (r < 36) /* filter from width:hight ratio */
            )
        {
            mrz.push_back(rect);
            rectangle(rgb, rect, Scalar(0, 255, 0), 1);
        }
        else
        {
            rectangle(rgb, rect, Scalar(0, 0, 255), 1);
        }
    }
    if (2 == mrz.size())
    {
        // just assume we have found the two data strips in MRZ and combine them
        CvRect max = cvMaxRect(&(CvRect)mrz[0], &(CvRect)mrz[1]);
        rectangle(rgb, max, Scalar(255, 0, 0), 2);  // draw the MRZ

        vector<Point2f> mrzSrc;
        vector<Point2f> mrzDst;

        // MRZ region in our image
        mrzDst.push_back(Point2f((float)max.x, (float)max.y));
        mrzDst.push_back(Point2f((float)(max.x+max.width), (float)max.y));
        mrzDst.push_back(Point2f((float)(max.x+max.width), (float)(max.y+max.height)));
        mrzDst.push_back(Point2f((float)max.x, (float)(max.y+max.height)));

        // MRZ in our template
        mrzSrc.push_back(Point2f(0.23f, 9.3f));
        mrzSrc.push_back(Point2f(18.0f, 9.3f));
        mrzSrc.push_back(Point2f(18.0f, 10.9f));
        mrzSrc.push_back(Point2f(0.23f, 10.9f));

        // find the transformation
        Mat t = getPerspectiveTransform(mrzSrc, mrzDst);

        // photo region in our template
        vector<Point2f> photoSrc;
        photoSrc.push_back(Point2f(0.0f, 0.0f));
        photoSrc.push_back(Point2f(5.66f, 0.0f));
        photoSrc.push_back(Point2f(5.66f, 7.16f));
        photoSrc.push_back(Point2f(0.0f, 7.16f));

        // surname region in our template
        vector<Point2f> surnameSrc;
        surnameSrc.push_back(Point2f(6.4f, 0.7f));
        surnameSrc.push_back(Point2f(8.96f, 0.7f));
        surnameSrc.push_back(Point2f(8.96f, 1.2f));
        surnameSrc.push_back(Point2f(6.4f, 1.2f));

        vector<Point2f> photoDst(4);
        vector<Point2f> surnameDst(4);

        // map the regions from our template to image
        perspectiveTransform(photoSrc, photoDst, t);
        perspectiveTransform(surnameSrc, surnameDst, t);
        // draw the mapped regions
        for (int i = 0; i < 4; i++)
        {
            line(rgb, photoDst[i], photoDst[(i+1)%4], Scalar(0,128,255), 2);
        }
        for (int i = 0; i < 4; i++)
        {
            line(rgb, surnameDst[i], surnameDst[(i+1)%4], Scalar(0,128,255), 2);
        }
    }

Result: photo and surname regions in orange. MRZ in blue.

这篇关于检测国民身份证并获取详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆