2014-06-16 2 views
13

아래 유형의 내셔널 ID를 탐지하고 세부 정보를 얻으려고합니다. 예를 들어 서명의 위치는 사람 이미지의 오른쪽 상단 구석에 있어야합니다 ,이 경우에는 "BC"입니다.주민등록증을 발견하고 세부 정보를 얻는 중

enter image description here

나는 아이폰에서이 응용 프로그램을 할 필요가있다. 나는 그것을 위해 Opencv를 사용하는 것을 생각했다. 그러나 어떻게 표시된 세부 사항을 얻을 수 있을까? 비슷한 종류의 카드로 신청서를 교육해야합니까, 아니면 OCR이 도움이 될 수 있습니까?

모바일 응용 프로그램을위한 특정 구현이 있습니까?

또한 신용 카드 세부 정보를 감지하는 카드를 통해 카드 소니가 다른 카드 정보도 감지합니까?

업데이트 : 텍스트 검출 tesseract 사용한

. Tesseract는 이미지에 텍스트 만 있으면 잘 작동합니다. 그래서 붉은 색 영역을 자르고 Tesseract에 입력으로 주어지면 MRZ 부분에서 잘 작동합니다.

내가 테스트 한 Tesseract의 경우 IOS implementation이 있습니다.

내가해야 할 일은 무엇입니까?

이제 텍스트 감지 부분을 자동화하려고합니다. 이제 다음 항목을 자동화 할 계획입니다.

1) 비올라 죤스 얼굴 검출기를 사용하여 얼굴 잘라 내기.

2)이 예제에서 "BC"는 사진에서 가져와야합니다.

3) ID 카드에서 MRZ 영역 추출/검출.

2를 시도하고 있습니다. & 3, 아이디어 나 코드 조각이 훌륭합니다.

+4

실제 사람이라면 Antoine이 모든 사람이 볼 수 있도록 웹에 게시 된 ID가 마음에 들지 않았 으면합니다. – QED

+0

ID에서 데이터를 추출 하시겠습니까? MRZ에서 필요로하는 모든 데이터가 MRZ에서 찾을 수 있다고 생각합니다. 문제는 MRZ 인식입니다. 맞습니까? –

+0

@Vitalik 당신 말이 맞아, 나는 MRZ의 내용을 알지 못했다. 답장을 보내 주셔서 감사합니다. MRZ 부분 만 찾는 아이디어는 MRZ 부분을 찾기 위해 사각형 탐지를 시도 할 계획입니다. 운동할까요? – 2vision2

답변

2

Card.io는 양각 된 신용 카드 전용으로 설계되었습니다. 이 사용 사례에서는 작동하지 않습니다.

+0

답장을 보내 주셔서 감사합니다. 이 유스 케이스는 다른 방법으로도 구현할 수 있습니까? – 2vision2

+0

충분한 노력으로 무엇이든 가능합니다. ;) 여기에서 시작하겠습니다. http://stackoverflow.com/questions/3750719/getting-started-in-computervision-road-tracking – tomwhipple

14

이러한 ID는 특정 폭, 높이, 오프셋, 간격 등을 갖는 표준 템플리트에 따라 준비되었다고 가정하면 템플리트 기반 접근 방식을 시도 할 수 있습니다.

MRZ는 쉽게 감지 할 수 있습니다. 이미지에서이를 감지하면 템플릿의 MRZ를 매핑하는 변환을 찾습니다. 이 변환을 알면 템플릿의 모든 영역 (예 : 개인 사진)을 이미지에 매핑하고 해당 영역을 추출 할 수 있습니다.

다음은 행복한 경로를 따르는 매우 간단한 프로그램입니다. 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); 
     } 
    } 

결과 : 촬영 한 사진 및 성 영역 오렌지색입니다. 파란색으로 된 MRZ. enter image description here

2

이제이 목적으로 사용할 수있는 PassportEye 라이브러리가 있습니다. 완벽하지는 않지만 내 경험으로는 꽤 잘 작동합니다. https://pypi.python.org/pypi/PassportEye/

+0

내 테스트 및 기타 의견은 http://www.pyimagesearch.com/2015에서 확인할 수 있습니다./11/30/detect-machine-readable-zones-in-passport-images/(돈 참조),이 모듈은 자극받을 준비가되지 않았다. – comte