美文网首页
OpenCV+TesseractOCRiOS实现身份证号/银行卡

OpenCV+TesseractOCRiOS实现身份证号/银行卡

作者: 一蓑烟雨满眼风波 | 来源:发表于2017-08-11 13:44 被阅读0次
  • iOS 文字识别准备
  • 图片灰度化
  • 图片二值化
  • 根据特征点提取某一区域

声明:思路来源于 iOS身份证号码识别 ,在此我对作者表示感谢,一下内容,是我结合http://www.opencv.org.cn写的一个简单教程,对该工程所用到的方法进行解读,在本文的最后,会附上完整的代码.

正文

iOS 文字识别准备

文字识别重要点在对图片的预处理,预处理做的比较好,识别率就会比较高,本次所介绍的身份证号识别是基于OpenCV、TesseractOCRiOS来实现的
首先使用CocoaPods导入三方库

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

灰度化

灰度化,在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值,因此,灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。
下面说一下如何使用OpenCV进行灰度化处理,使用的OpenCV是一个C++ 的代码,在使用的类中要将.m文件改为.mm

    //将UIImage转换成矩阵
    cv::Mat resultImage;//定义矩阵
    UIImageToMat(image, resultImage);
    //转为灰度图
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
原图.png 灰度化.png

二值化

图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。

固定阈值门限分割
  • 方法
double threshold( InputArray src, OutputArray dst,
                               double thresh, double maxval, int type );
  • 参数说明
src 输入矩阵
dst 输出矩阵
thresh 阀值
maxval 最大值(这里通常设置为255)
thresholdType 分割类型
  • 分割类型说明
//value 矩阵中一个单位的颜色的值
//threshold 阀值
CV_THRESH_BINARY      =0,  /**value > threshold ? max_value : 0       */
    CV_THRESH_BINARY_INV  =1,  /**value > threshold ? 0 : max_value       */
    CV_THRESH_TRUNC       =2,  /** value > threshold ? threshold : value   */
    CV_THRESH_TOZERO      =3,  /**value > threshold ? value : 0           */
    CV_THRESH_TOZERO_INV  =4,  /** value > threshold ? 0 : value */
  • 使用
    cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);
阀值为100二值化.png

这里又有一个很重要的点,阀值的确定,我是在某个博客找到个计算阀值的算法,不过不是很理想,现在也贴出来,但是不知道作者是谁了,很抱歉...

int cvThresholdOtsu(IplImage* src)
{
    int height=src->height;
    int width=src->width;
    
    //histogram
    float histogram[256]={0};
    for(int i=0;i<height;i++) {
        unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;
        for(int j=0;j<width;j++) {
            histogram[*p++]++;
        }
    }
    //normalize histogram
    int size=height*width;
    for(int i=0;i<256;i++) {
        histogram[i]=histogram[i]/size;
    }
    
    //average pixel value
    float avgValue=0;
    for(int i=0;i<256;i++) {
        avgValue+=i*histogram[i];
    }
    
    int threshold = 0;
    float maxVariance=0;
    float w=0,u=0;
    for(int i=0;i<256;i++) {
        w+=histogram[i];
        u+=i*histogram[i];
        
        float t=avgValue*w-u;
        float variance=t*t/(w*(1-w));
        if(variance>maxVariance) {
            maxVariance=variance;
            threshold=i;
        }
    }
    
    return threshold;
}
  • 截取卡号区域
    思路,现将黑色的点放大,这样点会连接到一起,变成一块儿黑色,然后我们通过图片的轮廓,宽高比例来寻找复合的一个区域,将其截取下来

腐蚀&膨胀

  • 官方解释:
    腐蚀:进行腐蚀操作时,将内核B划过图像,将内核B覆盖区域的最小相素值提取,并代替锚点位置的相素。
    膨胀:进行膨胀操作时,将内核B划过图像,将内核B覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。对上图采用膨胀操作我们得到:
  • 个人理解:
    腐蚀:定义一个size,用这个size替换图片每个点(加粗)
    膨胀:与腐蚀相反(变细)
    个人的认识比较low,在这里呢使用腐蚀目的是将相近的黑色点连接到一块,已便后面获取所有数字连接到一块儿的轮廓,对比每个轮廓的宽高比,截取到卡号区域。
cv::Mat erodeElement = getStructuringElement(cv::MORPH_RECT, cv::Size(25,1));
cv::erode(resultImage, resultImage, erodeElement);
腐蚀之后的照片

在图像中寻找轮廓

  • 方法
//获取图片轮廓
findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset = Point());
//将存放Point的数组转为Rect
Rect boundingRect( InputArray points );
  • findContours参数说明
InputOutputArray:输入输出的图片
OutputArrayOfArrays:输出的轮廓点,这是一个三维数
std::vector<std::vector<cv::Point>> contours;

mode:轮廓检索模式,具体参考cv::RetrievalModes
CV_RETR_EXTERNAL:只检索最外面的轮廓;
CV_RETR_LIST:检索所有的轮廓,并将其放入list中;
CV_RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
CV_RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次。

method:轮廓近似法,具体参考cv::ContourApproximationModes
CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CV_CHAIN_APPROX_NONE:将所有的连码点,转换成点。
CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:使用the flavors of Teh-Chin chain近似算法
的一种。
CV_LINK_RUNS:通过连接水平段的1,使用完全不同的边缘提取算法。使用CV_RETR_LIST检索模式能使用此方法。
offset:偏移量,用于移动所有轮廓点。
  • 使用
    cv::findContours(resultImage, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

根据轮廓选取目标区域

(未完)

相关文章

  • OpenCV+TesseractOCRiOS实现身份证号/银行卡

    iOS 文字识别准备 图片灰度化 图片二值化 根据特征点提取某一区域 声明:思路来源于 iOS身份证号码识别 ,在...

  • 移动端充值/提现绑定银行卡

    用户充值绑定银行卡需要提供持卡人姓名、身份证号、银行、银行卡号、银行预留手机号。根据四要素(姓名、省份证号、银行卡...

  • 互金当中可以参考判断用户的纬度

    验证申请人身份: 姓名、身份证号码:通过国政通来验证 姓名、银行卡号:通过银行验证 手机号、姓名、身份证号码、家庭...

  • 04-事务-索引-视图-游标

    一、事务 人员信息如下:(第二列是身份证号,第三列是银行卡卡号) --刘备 420107198905064135...

  • 在洋钱罐薅羊毛的过程

    从手机助手下载洋钱罐APP安装到手机,注册,绑定手机号,输入姓名和身份证号码,关联银行卡,平台自动从我银行卡中扣除...

  • 当年因不会它被罚款如今却被狠狠打脸

    记得08年刚进公司做出纳,那时经常输员工的身份证号码以及员工银行卡号,当初多输入了银行卡位数导致把员工工资退回,需...

  • GDK金钥匙

    GDK金钥匙 收账号 10块一个 需要银行卡预留手机号 注册只需要填写姓名 身份证号 手机号跟银行卡号《支付宝账号...

  • iOS-swift3.0 点滴积累:身份证号码校验

    身份证号码校验,server端和app端都可以实现。下面实现swift3.0 校验身份证号码是否合法。用swfit...

  • 面试-计数器相关

    面试官问: 文件里有m个身份证号,统计每个身份证号出现的次数 回答: 使用hashMap实现,key作为身份证号C...

  • 基于Luhn算法的银行卡卡号的格式校验

    引言 在金融类软件开发过程中,经常会涉及到用户银行卡信息的校验,包括银行卡卡号、开户人姓名、身份证号和手机号等。理...

网友评论

      本文标题:OpenCV+TesseractOCRiOS实现身份证号/银行卡

      本文链接:https://www.haomeiwen.com/subject/icpotxtx.html