iOS之身份证号码识别

##Begin

这里使用到两个C++的库

  1. OpenCV
  2. Tesseract

OpenCV在这里实现图像处理,Tesseract在这里实现数字识别

先上效果图:隐私打码谢谢

###0x00 获取视频流

iOS里获取视频流比较简单,当然OpenCV里也有这功能,这里只说前一种。大家可以直接搜 AVCaptureSession,这里我就直接上代码了。

在回调里获取到图片,并且转化为UIImage

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    CVImageBufferRef ref = CMSampleBufferGetImageBuffer(sampleBuffer);
    CIImage* ciImage = [[CIImage alloc]initWithCVPixelBuffer:ref];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:ciImage fromRect:[ciImage extent]];
    UIImage * image = [[UIImage alloc]initWithCGImage:cgImage];
    CGImageRelease(cgImage);
}

###0x01 OpenCV处理图片
集成OpenCV的方法很简单,直接使用Cocospod就可以了。

pod 'OpenCV', '~> 3.0.0'

OpenCV地址

这里说下主要的对身份证的处理

  • 灰度图

    cvtColor(dst, dst, COLOR_BGR2GRAY);
    
  • 二值化

    threshold(dst, dst, 80, 255, THRESH_BINARY);
    
  • 腐蚀

    erode(dst,dst,Mat(27,27,CV_8U),Point(-1,-1),2);
    
  • 轮廓检测

    Mat c = dst.clone();
    vector<vector<Point>> contours;
    findContours(c, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,cvPoint(0, 0));
    //除去太长或者太短的轮廓
    int cmin = 35;
    int cmax = 800;
    vector<std::vector<cv::Point>>::iterator itc = contours.begin();
    while(itc != contours.end())
    {
        Rect rect = boundingRect(*itc);
    
        if(itc->size() < cmin || itc->size() > cmax || rect.width < 40 || rect.height < 40){
            //std::cout << "EraseSize: " << itc->size() << std::endl;
            itc = contours.erase(itc);
            }
        else{
            ++itc;};
    
    }
    
  • 取出身份证号码区域

    vector<Rect> rects;
    Rect rr = Rect(0,0,0,0);
    std::vector<std::vector<cv::Point>>::const_iterator itContours = contours.begin();
    for ( ; itContours!=contours.end(); ++itContours){
        Rect rect = boundingRect(*itContours);
        rects.push_back(rect);
        //std::cout << "Size: " << rect << std::endl;
        if (rect.width > rr.width && rect.width > rect.height * 5) {
            rr = rect;
        }
    }
    

###0x02 Tesseract进行数字识别

集成OpenCV的方法也很简单,直接使用了别人封装好的一个库,当然也可以自己编译直接使用C++的。

pod 'TesseractOCRiOS', '~> 4.0.0'

GitHub地址

直接识别

self.tesseract = [[G8Tesseract alloc] initWithLanguage:@"chi_sim"];

tesseract.charWhitelist = @"0123456789";

self.tesseract.image = [i g8_blackAndWhite];

  // Optional: Limit the area of the image Tesseract should recognize on to a rectangle
self.tesseract.rect = CGRectMake(0, 0, i.size.width, i.size.height);

  // Optional: Limit recognition time with a few seconds
self.tesseract.maximumRecognitionTime = 2.0;

  // Start the recognition
[self.tesseract recognize];

  // Retrieve the recognized text
NSLog(@"识别:%@", [self.tesseract recognizedText]);