检测国民身份证并获取详细信息[关闭]
Posted
技术标签:
【中文标题】检测国民身份证并获取详细信息[关闭]【英文标题】:Detecting the National ID card and getting the details [closed] 【发布时间】:2014-08-06 11:05:24 【问题描述】:我正在尝试检测以下类型的国民身份证并获取其详细信息,例如签名的位置应在人物图像的右上角,在本例中为“BC”。
我需要在 iphone 中执行此应用程序。我想过使用 Opencv,但我怎样才能实现标记的细节?我需要用类似的卡片或 OCR 来训练应用程序吗?
有没有针对移动应用的具体实现?
我也通过 card-io 检测信用卡详细信息,Card-io 是否也检测其他卡详细信息?
更新:
我使用tesseract 进行文本检测。如果图像只有文本,则 Tesseract 效果很好。所以我裁剪了红色标记的区域并将其作为 Tesseract 的输入,它适用于 MRZ 部分。
Tesseract 有一个ios implementation,我已经用它进行了测试。
我需要做什么?
现在我正在尝试自动化文本检测部分。现在我打算自动化以下项目,
1) 裁剪面部(我已经使用 Viola-jones 面部检测器完成了)。
2) 本例中的首字母“BC”需要取自照片。
3) 从身份证中提取/检测机读区。
我正在尝试做 2 和 3,任何想法或代码 sn-ps 都会很棒。
【问题讨论】:
如果那是一个真人,那么我希望 Antoine 不介意他的 ID 被发布到网络上让所有人看到! 您想从 ID 中提取数据吗?我认为您需要的所有数据都可以在 MRZ 中找到,所以问题是 MRZ 识别,对吗? @Vitalik 你说得对,我没有注意到机读区的内容。谢谢回复。关于单独查找 MRZ 部分的任何想法,我计划尝试使用方形检测来查找 MRZ 部分。会锻炼吗? @QED。我在身份证上看到一个“标本”。这通常意味着它是假的并且仅用于测试目的 @RobAu QED 是对的,我在他的评论后更改了图片。我从谷歌图片中得到了安东尼的图片,但在那之后我改变了! 【参考方案1】:假设这些 ID 是根据具有特定宽度、高度、偏移量、间距等的标准模板准备的,您可以尝试基于模板的方法。
机读区很容易被发现。在图像中检测到它后,找到将模板中的 MRZ 映射到它的转换。当您知道此转换后,您可以将模板上的任何区域(例如个人照片)映射到图像并提取该区域。
下面是一个非常简单的程序,它遵循一条快乐的道路。您必须进行更多处理才能找到一般的机读区(例如,如果存在透视变形或旋转)。我只是通过测量图像来准备模板,它不适用于您的情况。我只是想传达这个想法。图片来自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);
结果:照片和姓氏区域为橙色。机读区为蓝色。
【讨论】:
【参考方案2】:Card.io 专为浮雕信用卡而设计。它不适用于此用例。
【讨论】:
感谢您的回复。我可以通过任何其他方法实现这个用例吗? 只要付出足够的努力,一切皆有可能。 ;) 我会从这里开始:***.com/questions/3750719/…【参考方案3】:现在有可用于此目的的 PassportEye 库。它并不完美,但根据我的经验,效果很好:https://pypi.python.org/pypi/PassportEye/
【讨论】:
来自我的测试和其他 cmets pyimagesearch.com/2015/11/30/…(参见 Don's),该模块还没有准备好进行生产(远非如此)以上是关于检测国民身份证并获取详细信息[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Asp.Net MVC 中JS通过ajaxfileupload上传图片获取身份证姓名生日家庭住址等详细信息