身份證碼識別

感謝 http://www.reibang.com/p/ac4c4536ca3e 很早就想做的一個demo

寫在前面
用到的技術(shù):

  1. 圖像處理技術(shù), 包括包括灰度化處理猾昆,二值化儒搭,腐蝕脐湾,輪廊檢測,

  2. 文字識別技術(shù): 通過ocr識別技術(shù)可以將圖片中包含的數(shù)字信息以字符串的方式輸出。
    3.開源庫
    開源框架OpenCV和TesseractOCRiOS
    OpenCV(完成圖像處理技術(shù))
    ??OpenCV是一個開源的跨平臺計算機(jī)視覺和機(jī)器學(xué)習(xí)庫您单,通俗點(diǎn)的說却紧,就是他給計算機(jī)提供了一雙眼睛,一雙可以從圖片中獲取信息的眼鏡惨撇,從而完成人臉識別伊脓、身份證識別、去紅眼魁衙、追蹤移動物體等等的圖像相關(guān)的功能报腔。opencv官網(wǎng)
    TesseractOCRiOS(完成文字識別技術(shù))
    ??Tesseract是目前可用的最準(zhǔn)確的開源OCR引擎,可以讀取各種格式的圖片并將他們轉(zhuǎn)換成各種語言文本剖淀。而TesseractOCRiOS則是針對iOS平臺封裝的Tesseract引擎庫纯蛾。

  3. 必須保證背景純凈

  4. 灰度化處理:圖片灰度化處理就是將指定圖片每個像素點(diǎn)的RGB三個分量通過一定的算法計算出該像素點(diǎn)的灰度值,使圖像只含亮度而不含色彩信息纵隔。

  5. 二值化:二值化處理就是將經(jīng)過灰度化處理的圖片轉(zhuǎn)換為只包含黑色和白色兩種顏色的圖像翻诉,他們之間沒有其他灰度的變化。在二值圖中用255便是白色捌刮,0表示黑色碰煌。

  6. 腐蝕:圖片的腐蝕就是將得到的二值圖中的黑色塊進(jìn)行放大。即連接圖片中相鄰黑色像素點(diǎn)的元素绅作。通過腐蝕可以把身份證上的身份證號碼連接在一起形成一個矩形區(qū)域芦圾。

  7. 輪廊檢測:圖片經(jīng)過腐蝕操作后相鄰點(diǎn)會連接在一起形成一個大的區(qū)域,這個時候通過輪廊檢測就可以把每個大的區(qū)域找出來棚蓄,這樣就可以定位到身份證上面號碼的區(qū)域堕扶。

說完就開始吧

首先, 用CocoPods導(dǎo)入上面兩個庫, 這個demo做完差不多快200M

由于導(dǎo)入的庫不支持Bitcode機(jī)制,需要關(guān)掉梭依,在工程->TARGETS->Build Setting-> Enable Bitcode設(shè)置為NO

TesseractOCRiOS庫中沒有自帶的語言包稍算,需要我們自己手動導(dǎo)入,我們這里直接到tesseract-ocr網(wǎng)站役拴,tessdata即是我們需要用到的語言包糊探。下載下來的語言包有400多兆。這里我們只需要用到英語語言包河闰,所以就只導(dǎo)入eng.traineddata就ok科平,其他的都刪掉。

導(dǎo)入語言包種需要注意幾點(diǎn):

  1. 語言包需要放在tessdata目錄下姜性。TesseractOCRiOS中查找語言包是在tessdata目錄下進(jìn)行查找的瞪慧,所以我們不能單獨(dú)把eng.traineddata導(dǎo)入項(xiàng)目中,而需要放在tessdata目錄下導(dǎo)入項(xiàng)目中部念。
  2. 將tessdata導(dǎo)入xcode項(xiàng)目弃酌,需要勾選Create folder refrences氨菇。上面已經(jīng)提到了語言包需要放在tessdata目錄下,所以導(dǎo)入文件到xcode的時候需要創(chuàng)建文件夾的形式妓湘,而不是創(chuàng)建組的形式查蓉。

然后, 創(chuàng)建一個RecogizeCardManager用來管理身份證識別相關(guān)的代碼。
由于OpenCV和TesseractOCRiOS庫都是基于c++編寫的榜贴,所以需要把RecogizeCardManager.m后綴的.m改成.mm

VC里面子控件布局以及取怎么使用拍照和去相冊取照片以前寫過, 不再寫, 只寫manager里面的東西

創(chuàng)建一個NAReconizeIdCardManager繼承于NSObject

引入

#import <opencv2/opencv.hpp>
//#import <opencv2/imgproc/types_c.h>
#import <opencv2/imgcodecs/ios.h>

#import <TesseractOCR/TesseractOCR.h>

寫個單例聲明出去

+ (instancetype)sharedManager{

    static NAReconizeIdCardManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    
       manager = [[NAReconizeIdCardManager alloc] init];
    });
    return manager;
}

外部傳入UIImage然后進(jìn)行處理, 回調(diào)一個NSString作為身份證碼

- (void)reconizeWithImage:(UIImage *)image complete:(void (^)(NSString *))complete{

    //掃描身份證圖片, 并進(jìn)行預(yù)處理, 定位號碼區(qū)域圖片并返回
    UIImage *numberImage = [self opencvScanCard:image];
    if (numberImage == nil) {
        complete(nil);
    }
    //利用TesseractOCR識別文字
    [self tesseractReconizeImage:numberImage completion:^(NSString *numberText) {
    
        complete(numberText);
    }];
}

#pragma mark - 預(yù)處理圖片, 定位號碼區(qū)域并返回image
- (UIImage *)opencvScanCard:(UIImage *)image{

    //將UIImage轉(zhuǎn)換成Mat
    cv::Mat resultImage; //#import <opencv2/opencv.hpp>
    UIImageToMat(image, resultImage);//#import <opencv2/imgcodecs/ios.h>
    //轉(zhuǎn)為灰度圖
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
    //利用閾yu值二值化
    cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);
    //腐蝕, 填充(腐蝕是讓黑色點(diǎn)變大)
    cv::Mat erodeElement = getStructuringElement(cv::MORPH_RECT, cv::Size(26, 26));
    cv::erode(resultImage, resultImage, erodeElement);
    //輪廓檢測
    std::vector<std::vector<cv::Point>> contours;//定義一個容器來存儲所有檢測到的輪廓
    cv::findContours(resultImage, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
    //取出身份證號碼區(qū)域
    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){
        return nil;
    }
    //定位成功, 去原圖截取身份證號碼區(qū)域, 并轉(zhuǎn)換為灰度圖, 進(jìn)行二值化處理
    cv::Mat matImage;
    UIImageToMat(image, matImage);
    resultImage = matImage(numberRect);
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
    cv::threshold(resultImage, resultImage, 80, 255, CV_THRESH_BINARY);
    //將Mat轉(zhuǎn)換成UIImage
    UIImage *numberImage = MatToUIImage(resultImage);
    return numberImage;
}

#pragma mark - 利用TesseractOCR識別文字
//#import <TesseractOCR/TesseractOCR.h>
- (void)tesseractReconizeImage:(UIImage *)image completion:(void (^)(NSString *))completion{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    
        G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"eng"];
        tesseract.image = [image g8_blackAndWhite];
        tesseract.image = image;
        //開始識別
        [tesseract recognize];
        //回調(diào)結(jié)果
        completion(tesseract.recognizedText);
    });
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末豌研,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子唬党,更是在濱河造成了極大的恐慌鹃共,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件初嘹,死亡現(xiàn)場離奇詭異及汉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)屯烦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門坷随,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驻龟,你說我怎么就攤上這事温眉。” “怎么了翁狐?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵类溢,是天一觀的道長。 經(jīng)常有香客問我露懒,道長闯冷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任懈词,我火速辦了婚禮蛇耀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坎弯。我一直安慰自己纺涤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布抠忘。 她就那樣靜靜地躺著撩炊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪崎脉。 梳的紋絲不亂的頭發(fā)上拧咳,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音囚灼,去河邊找鬼骆膝。 笑死砾淌,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谭网。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼赃春,長吁一口氣:“原來是場噩夢啊……” “哼愉择!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起织中,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锥涕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后狭吼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體层坠,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年刁笙,在試婚紗的時候發(fā)現(xiàn)自己被綠了破花。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡疲吸,死狀恐怖座每,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摘悴,我是刑警寧澤峭梳,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站蹂喻,受9級特大地震影響葱椭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜口四,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一孵运、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窃祝,春花似錦掐松、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至探膊,卻和暖如春杠愧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逞壁。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工流济, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锐锣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓绳瘟,卻偏偏與公主長得像雕憔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子糖声,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容