OCR-基于OpenCV、Tesseract的银行卡号识别

title: ‘OCR:基于OpenCV、Tesseract的银行卡号识别’
type: categories
date: 2016-12-01 16:50:30
categories: OC

tags: [OCR, OpenCV, Tesseract]

由于银行卡的卡面背景色彩千差万别,并且卡号的印制方式(平印、凸印)也不相同,所以这种识别方式的效果并不理想,可以说很差,暂时对平印的单一色彩的银行卡的识别效果还行;

这种方式可以用来做身份证的识别,效果很好,因为身份证背景颜色浅,而且样式一致。

效果图:

本文Demo

https://github.com/zhangzhaopds/OCR_OpenCV_Tesseract_demo.git

思路

1、对预览图进行初步的手动裁剪,缩小OpenCV的处理范围;

2、利用OpenCV对图片进行初步的处理,包括灰度化处理、二阈值处理、膨胀处理等;

3、利用TesseractIOSOCR进行图片的文字识别;

主要实现

依赖库:

pod 'OpenCV', '~> 3.0.0'
pod 'TesseractOCRiOS', '~> 4.0.0'

实现(代码中有解释):

图片的剪裁、识别与结果处理:
// 图片的剪裁、识别与结果处理
- (void)detecteCardWithImage:(UIImage *)cardImage compleate:(CompleteBlock)complete {

    /**
     相对于身份证来说,银行卡片的背景环境千差万别,有的卡片无需处理而有的则需要灰度值或二阈值重新处理,用一种方式处理千百种环境,结果可想而知;
     这里的话就简单的,在图片的不同处理阶段进行多次的文字识别,最后在统一处理;

     第一次:卡号所在位置的图片截取之后,进行识别;
     第二次:灰度值处理之后,进行识别;
     第三次:二阈值处理之后,进行识别;
     第四次:腐蚀化重新截图并灰度值处理之后,进行识别;
     第五次:腐蚀化重新截图、灰度值并二阈值处理之后,进行识别;
     */

    // 将卡号所在的大致位置在图片上截取出来,缩小OpenCV要识别的图片范围,认为的提高识别效率。
    UIImage *corpImage = [self cropImageFromImage:cardImage];
    if (corpImage == nil) {
        complete(nil);
        return;
    }

    // 识别结果的初步处理
    __weak typeof(self) weakSelf = self;
    self.myBlock = ^(NSString *res) {

        // 信用卡16位,储蓄卡19位
        if (res.length < 16) {
            return;
        }

        NSString *result = [weakSelf findNumFromStr:res];
        NSLog(@"��%@", result);

        if (result.length < 16) {
            return;
        }
        complete(result);
    };

    // 第一次识别:
    [self tesseractDetectorWithImage: corpImage withComplete:^(NSString *result) {
        NSLog(@"第一次识别:%@", result);
        weakSelf.myBlock(result);
    }];

    // 利用OpenCV,对截取出来的图片进一步处理,并进行类外四次的识别
    [self opencvScanCard:corpImage];

}

因为识别的次数增多,所以结果的反馈较慢,可相应减少识别次数。

利用OpenCV对图片的进一步处理
- (void)opencvScanCard:(UIImage *)image {

    // 图片转换
    cv::Mat resultImage;
    UIImageToMat(image, resultImage);

    // 灰度处理(去除图片的色彩和光亮)
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);

    // 第二次识别:
    __weak typeof(self) weakSelf = self;
    [self tesseractDetectorWithImage: MatToUIImage(resultImage) withComplete:^(NSString *result) {
        NSLog(@"第二次识别:%@", result);
        weakSelf.myBlock(result);
    }];

    // 二阈值处理
    cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);

    // 第三次识别:
    [self tesseractDetectorWithImage: MatToUIImage(resultImage) withComplete:^(NSString *result) {
        NSLog(@"第三次识别:%@", result);
        weakSelf.myBlock(result);
    }];

    // 腐蚀:白色背景缩小,黑色扩大
    cv::Mat erodeElement = getStructuringElement(cv::MORPH_RECT, cv::Size(25,25)); //3535
    cv::erode(resultImage, resultImage, erodeElement);

    UIImage *ccc = MatToUIImage(resultImage);
    UIImageWriteToSavedPhotosAlbum(ccc, nil, nil, nil);

    // 轮廊检测
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(resultImage, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

    // 取出卡号区域
    std::vector<cv::Rect> rects;
    cv::Rect numberRect = cv::Rect(0,0,0,0);
    std::vector<std::vector<cv::Point>>::const_iterator itContours = contours.begin();

    for ( ; itContours != contours.end(); ++itContours) {
        cv::Rect rect = cv::boundingRect(*itContours);
        rects.push_back(rect);

        if (rect.width > numberRect.width && rect.width > rect.height * 5) {
            numberRect = rect;
        }
    }

    if (numberRect.width == 0 || numberRect.height == 0) {
        NSLog(@"定位失败");
        return;
    }

    // 定位成功,重新截图
    cv::Mat matImage;
    UIImageToMat(image, matImage);
    resultImage = matImage(numberRect);

    // 第二次灰度值处理
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);

    // 第四次识别:
    [self tesseractDetectorWithImage: MatToUIImage(resultImage) withComplete:^(NSString *result) {
        NSLog(@"第四次识别:%@", result);
        weakSelf.myBlock(result);
    }];

    // 第二次二阈值处理
    cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);

    // 第五次识别:
    [self tesseractDetectorWithImage: MatToUIImage(resultImage) withComplete:^(NSString *result) {
        NSLog(@"第五次识别:%@", result);
        weakSelf.myBlock(result);
    }];
}
Tesseract识别
// Tesseract识别
- (void)tesseractDetectorWithImage:(UIImage *)img withComplete:(CompleteBlock)complete {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"eng"];
        tesseract.image = [img g8_blackAndWhite];
        tesseract.image = img;
        [tesseract recognize];
        complete(tesseract.recognizedText);
    });
}
银行卡片的初次裁剪
// 裁剪银行卡号
- (UIImage *)cropImageFromImage:(UIImage *)img {

    static CGFloat cardWidth = 400;
    static CGFloat cardHeight = 400/1.59;

    CGFloat h = img.size.height * 500 / img.size.width;
    UIGraphicsBeginImageContext(CGSizeMake(500, h));
    [img drawInRect:CGRectMake(0, 0, 500, h)];
    UIImage *scaleImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGFloat y = (scaleImg.size.height - cardHeight) / 2;

    CGImageRef sourceImageRef = [scaleImg CGImage];
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, CGRectMake(50, y, cardWidth, cardHeight));

    CGImageRef resultImgRef = CGImageCreateWithImageInRect(newImageRef, CGRectMake(0, 130, cardWidth, 50));
    UIImage *mm = [UIImage imageWithCGImage:resultImgRef];
    /**
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"%@", scaleImg);
        NSLog(@"%@", [UIImage imageWithCGImage:newImageRef]);
        NSLog(@"%@", mm);
        UIImageWriteToSavedPhotosAlbum(scaleImg, nil, nil, nil);
        UIImageWriteToSavedPhotosAlbum([UIImage imageWithCGImage:newImageRef], nil, nil, nil);
        UIImageWriteToSavedPhotosAlbum(mm, nil, nil, nil);
    })
    */
    return mm;
}
调用
- (void)clickedDetecteBtn:(UIButton *)sender {

    //【点击事件中调用图片识别,防止CPU飙升】
    [[DetectorManager shareInstance] detecteCardWithImage:self.myImage compleate:^(NSString *result) {
        NSLog(@"识别结果:%@", result);
    }];
}
参考文献

OpenCV教程-http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/tutorials.html

SwiftOCR教程-https://github.com/garnele007/SwiftOCR.git

Tesseract教程-https://github.com/tesseract-ocr/tesseract.git

http://www.jianshu.com/p/7462275f93ac

https://github.com/iosWellLin/OCR.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值