中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在iOS中識別身份證號碼

發布時間:2021-04-09 16:48:55 來源:億速云 閱讀:668 作者:Leah 欄目:移動開發

本篇文章給大家分享的是有關如何在iOS中識別身份證號碼,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創建一個iOS項目

用CocoPods導入上面兩個庫

由于OpenCV庫文件比較大,所以時間會稍微久一點,耐心等待就是。

如何在iOS中識別身份證號碼

導入完成之后運行項目,會發現報如下錯誤

如何在iOS中識別身份證號碼

由于導入的庫不支持Bitcode機制,需要關掉,在工程->TARGETS->Build Setting-> Enable Bitcode設置為NO就ok。

如何在iOS中識別身份證號碼

導入TesseractOCRiOS需要的語言包

TesseractOCRiOS庫中沒有自帶的語言包,需要我們自己手動導入,我們這里直接到tesseract-ocr網站,tessdata即是我們需要用到的語言包。下載下來的語言包有400多兆。這里我們只需要用到英語語言包,所以就只導入eng.traineddata就ok,其他的都刪掉。

導入語言包種需要注意幾點:

  • 語言包需要放在tessdata目錄下。TesseractOCRiOS中查找語言包是在tessdata目錄下進行查找的,所以我們不能單獨把eng.traineddata導入項目中,而需要放在tessdata目錄下導入項目中。

  • 將tessdata導入xcode項目,需要勾選Create folder refrences。上面已經提到了語言包需要放在tessdata目錄下,所以導入文件到xcode的時候需要創建文件夾的形式,而不是創建組的形式。如下圖:

如何在iOS中識別身份證號碼

創建一個RecogizeCardManager用來管理身份證識別相關的代碼。

由于OpenCV和TesseractOCRiOS庫都是基于c++編寫的,所以需要把RecogizeCardManager.m后綴的.m改成.mm

如何在iOS中識別身份證號碼

RecogizeCardManager中的代碼

.h文件

#import <Foundation/Foundation.h>
@class UIImage;

typedef void (^CompleateBlock)(NSString *text);

@interface RecogizeCardManager : NSObject

/**
* 初始化一個單例
*
* @return 返回一個RecogizeCardManager的實例對象
*/
+ (instancetype)recognizeCardManager;

/**
* 根據身份證照片得到身份證號碼
*
* @param cardImage 傳入的身份證照片
* @param compleate 識別完成后的回調
*/
- (void)recognizeCardWithImage:(UIImage *)cardImage compleate:(CompleateBlock)compleate;

@end

.m文件

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

@implementation RecogizeCardManager

+ (instancetype)recognizeCardManager {
  static RecogizeCardManager *recognizeCardManager = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    recognizeCardManager = [[RecogizeCardManager alloc] init];
  });
  return recognizeCardManager;
}

- (void)recognizeCardWithImage:(UIImage *)cardImage compleate:(CompleateBlock)compleate {
  //掃描身份證圖片,并進行預處理,定位號碼區域圖片并返回
  UIImage *numberImage = [self opencvScanCard:cardImage];
  if (numberImage == nil) {
    compleate(nil);
  }
  //利用TesseractOCR識別文字
  [self tesseractRecognizeImage:numberImage compleate:^(NSString *numbaerText) {
    compleate(numbaerText);
  }];
}

//掃描身份證圖片,并進行預處理,定位號碼區域圖片并返回
- (UIImage *)opencvScanCard:(UIImage *)image {

  //將UIImage轉換成Mat
  cv::Mat resultImage;
  UIImageToMat(image, resultImage);
  //轉為灰度圖
  cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
  //利用閾值二值化 
  cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);
  //腐蝕,填充(腐蝕是讓黑色點變大)
  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));
  //取出身份證號碼區域
  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;
  }
  //定位成功成功,去原圖截取身份證號碼區域,并轉換成灰度圖、進行二值化處理
  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轉換成UIImage
  UIImage *numberImage = MatToUIImage(resultImage);
  return numberImage;
}

//利用TesseractOCR識別文字
- (void)tesseractRecognizeImage:(UIImage *)image compleate:(CompleateBlock)compleate {

  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;
    // Start the recognition
    [tesseract recognize];
    //執行回調
    compleate(tesseract.recognizedText);
  });
}

RecognizeCardViewController代碼

故事版布局界面

如何在iOS中識別身份證號碼

.m文件

#import "RecognizeCardViewController.h"
#import "RecogizeCardManager.h"

@interface RecognizeCardViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>{
  UIImagePickerController *imgagePickController;
}

@property (weak, nonatomic) IBOutlet UIImageView *imgView;
@property (weak, nonatomic) IBOutlet UILabel *textLabel;
- (IBAction)cameraAction:(id)sender;
- (IBAction)photoAction:(id)sender;

@end

@implementation RecognizeCardViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  self.imgView.contentMode = UIViewContentModeScaleAspectFit;

  imgagePickController = [[UIImagePickerController alloc] init];
  imgagePickController.delegate = self;
  imgagePickController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
  imgagePickController.allowsEditing = YES;
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

//拍照
- (IBAction)cameraAction:(id)sender {

  //判斷是否可以打開照相機
  if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    imgagePickController.sourceType = UIImagePickerControllerSourceTypeCamera;
    //設置攝像頭模式(拍照,錄制視頻)為拍照
    imgagePickController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    [self presentViewController:imgagePickController animated:YES completion:nil];
  } else {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"設備不能打開相機" delegate:self cancelButtonTitle:@"知道了" otherButtonTitles: nil];
    [alert show];
  }
}

//相冊
- (IBAction)photoAction:(id)sender {
  imgagePickController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
  [self presentViewController:imgagePickController animated:YES completion:nil];
}

#pragma mark - UIImagePickerControllerDelegate
//適用獲取所有媒體資源,只需判斷資源類型
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
  NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
  UIImage *srcImage = nil;
  //判斷資源類型
  if ([mediaType isEqualToString:@"public.image"]){
    srcImage = info[UIImagePickerControllerEditedImage];
    self.imgView.image = srcImage;
    //識別身份證
    self.textLabel.text = @"圖片插入成功,正在識別中...";
    [[RecogizeCardManager recognizeCardManager] recognizeCardWithImage:srcImage compleate:^(NSString *text) {
      if (text != nil) {
        self.textLabel.text = [NSString stringWithFormat:@"識別結果:%@",text];
      }else {
        self.textLabel.text = @"請選擇照片";
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"照片識別失敗,請選擇清晰、沒有復雜背景的身份證照片重試!" delegate:self cancelButtonTitle:@"知道了" otherButtonTitles: nil];
        [alert show];
      }
    }];
  }
  [self dismissViewControllerAnimated:YES completion:nil];
}

//進入拍攝頁面點擊取消按鈕
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
  [self dismissViewControllerAnimated:YES completion:nil];
}

@end

總結

通過上面的實驗,該程序對身份證識別的正確率幾乎可以達到90%,剩下的10%主要取決于圖像的預處理,預處理程序是整個識別系統的關鍵所在。該系統的原理同樣也適用于獲取身份證上其他的信息,也可以應用于銀行卡、車牌號等的識別。

識別的正確率

主要取決于腐蝕、取出身份證號碼區域(輪廊提取)的算法這幾個關鍵點。

1、腐蝕: 腐蝕的參數很重要。

2、取出身份證號碼區域的算法(輪廊提取): 所有的處理都是為了在圖片中定位到身份證號碼的區域,輪廊提取就是這樣一個操作。篩選輪廊圖的算法很重要但是也是個難點。要提取身份證號碼區域的輪廊,算法的原理就是該輪廊的寬度是所有中最寬的,且寬度的長度必須大于高度的5倍。

不過這個算法還是存在不少問題。有的時候可能圖片背景比較復雜會影響到輪廊的檢測,基于這個問題:

  • 一方面可以通過對圖片的預處理來進行優化,減少對檢測身份證號碼區域的干擾

  • 第二個方面就是優化算法。

識別速度

使用TesseractOCRiOS對比較清晰的文字進行識別速度是比較快的,我試過用一張未經處理的寫著數字的圖片來處理,識別速度小于5s。但經過二值圖處理之后識別的速度就降低了,我認為可以對二值化處理后的圖片進一步處理,比如對二值圖進行細化描出骨架,然后在對骨架做均勻的膨脹處理,這樣得到的身份證號碼可能會清晰很多。

以上就是如何在iOS中識別身份證號碼,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

ios
AI

太仆寺旗| 收藏| 汤阴县| 云安县| 舟曲县| 和平县| 安丘市| 德州市| 皋兰县| 夹江县| 徐州市| 蓬溪县| 高密市| 广灵县| 巴东县| 涞源县| 永川市| 迁安市| 麟游县| 河间市| 孟津县| 扶绥县| 和静县| 南投县| 长春市| 全南县| 汶川县| 牟定县| 江津市| 醴陵市| 沾益县| 铁力市| 东明县| 黄骅市| 库尔勒市| 和硕县| 黄平县| 定安县| 南丹县| 金寨县| 故城县|