Posted at

OCRで名刺データをスキャンしてみる

More than 1 year has passed since last update.


はじめに

CamCard SDKを利用して、名刺データを読み取るサンプルをご紹介します。

詳細は、下記のサイトを参考にしてください。

https://dev.camcard.com/

REST APIの利用も出来ますが、オフラインでも利用するため、SDKを使いました。


1.導入


1.1.フレームワークをプロジェクトにコピーする。

・ISBusinessCardSDK.framework

・ISOpenSDKFoundation.embeddedframework

・IS_BCRAllTemplete.dat

・IS_BCRTemplete_AddressParse.dat


1.2. Linkied Frameworks and Librariesに下記を追加する。

・libstds++.tbd

・UIKit.framework

・CoreLocation.framework


1.3. Build Settings > Other Linker Flags に-ObjCをつける。

SDKは、Objective-C製です。


ISRecogenizeCard.h

//

// ISRecogenizeCard.h
// ISBusinessCardSDK
//
// Created by Simon liu on 17/02/15.
// Copyright (c) 2017年 xzliu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <ISOpenSDKFoundation/ISOpenSDKFoundation.h>
#import "ISBCRDefine.h"

typedef void(^ConstructResourcesFinishHandler)(ISOpenSDKStatus status);

@interface ISRecogenizeCard : NSObject

/**
* A singleton method for ISRecogenizeCard, you should use this singleton to call other methods.
*
* @return A ISRecogenizeCard instance.
*/

+ (ISRecogenizeCard *)sharedISOpenSDKController;

/*
You should call this method to construct resources before call other APIs in the SDK, calling this API will cause an online authorization for the first time this SDK is used.Once authorized successfully, this API will be returned immediately within expire time and try to update authorization status in background
*/

/**
* Use this method to construct resources and authorize SDK. You should call this method before any other API.
*
* @param appKey The app key you apply for.
* @param subAppKey For further use, now is nil.
* @param handler The construct result block. The status is defined in header file 'ISOpenSDKStatus.h'
*/

- (void)constructResourcesWithAppKey:(NSString *)appKey
subAppkey:(NSString *)subAppKey
finishHandler:(ConstructResourcesFinishHandler)handler;

/**
* Recognize card with recognize result content, if recognize failed, then return error.
*
* @param cardImage The image that need to be recognized.
* @param recognizeLanguages Recognized languages that need to be preset, e.g. @[@(ISOCRLanguageTypeEnglish), @(ISOCRLanguageTypeChineseSimp), @(ISOCRLanguageTypeJapanese)].
* @param needProcess If need to process image, please set to YES.
* @param recognizeResultHandler Return recognized result content and error if recognize failed.
* @param processResultHandler Return processed image and error if process failed.
*
* @return The authorize status, defined in header file 'ISOpenSDKStatus.h'
*/

- (ISOpenSDKStatus)recognizeCardWithImage:(UIImage *)cardImage
recognizeLanguage:(NSArray *)recognizeLanguages
needImageProcess:(BOOL)needProcess
recognizeResultHandler:(ISRecognizeResultHanler)recognizeResultHandler
imageProcessResultHandler:(ISProcessCardResultHandler)processResultHandler;

/**
* Release resources, call when you want to finish recognize.
*/

- (void)destructResources;

/**
* Use this method to get version information
*/

+ (NSString *)getSDKVersion;
@end



1.4. Build Settingsにある下記の設定をNoに変更する。

・Compress PNG Files

・Remove Text Metadata From PNG files

Compress PNG File Errorが出たため、上記の対応を行いました。


2.実装


2.1 名刺データ保存用の型を用意する。


BussinessCard.swift

import UIKit

import ISOpenSDKFoundation
import ISBusinessCardSDK

struct BussinessCard {

//性
var firstName = ""

//名
var lastName = ""

//電話番号
var cellNumbers = [String]()
var phoneNumbers = [String]()

//会社情報
var companies = [ISContactCompanyInfo]()

//メールアドレス
var emails = [String]()

//URL
var urls = [String]()

//住所
var address = [ISContactAddress]()

}



2.2. 名刺データの解析用のロジッククラスを用意する。


ORCManager.swift

import UIKit

import ISOpenSDKFoundation
import ISBusinessCardSDK

protocol OCRManagerDelegate: class {
func success(cardInfo: BussinessCard)
func failure()
}

final class ORCManager {

//MARK: - Property
let appkey = "" //this key just for test
let subKey = "" //reserved for future use

let languagesArray = [
Int(ISOCRLanguageType.english.rawValue),
Int(ISOCRLanguageType.japanese.rawValue)
]

weak var delegate: OCRManagerDelegate?

/// 認証
func verify() {
ISRecogenizeCard.sharedISOpenSDKController()
.constructResources(withAppKey: appkey, subAppkey: subKey) { status in

if case ISOpenSDKStatus.success = status {
print("Authorized success")
} else {
let statusInt = String.init(status.rawValue)
let statusAnalysis = IntSigSDKStatus.statusAnalysisEnglish(status: status)
let statusInfo = "Construct resource failed with:" + "[" + statusInt + "]" + "<" + statusAnalysis + ">"
print(statusInfo)
}
}
}

/// 名刺データを解析する
func analyze(originImage: UIImage) {

ISRecogenizeCard
.sharedISOpenSDKController()
.recognizeCard(with: originImage,
recognizeLanguage: languagesArray,
needImageProcess: true,
recognizeResultHandler: { info, error in

if let error = error {
self?.delegate?.failure()
return
}

if let info = info {
let cardInfo = self.parse(info: info)
self?.delegate?.success(cardInfo: cardInfo)
}
}, imageProcessResultHandler: nil)
}
}

extension ORCManager {

private func parse(info: ISContactInfo) -> BussinessCard {

var result = BussinessCard()

/// 姓
if let firstName = info.firstName {
result.firstName = firstName
print(firstName)
}

/// 名
if let lastName = info.lastName {
result.lastName = lastName
}

// 会社名、部署、役職
if let companies = info.companies as? [ISContactCompanyInfo] {
result.companies = companies
}

/// 電話番号
if let phones = info.phones as? [ISContactItem] {

for phone in phones {

// 携帯電話
if phone.itemLabel == "CELL" {
if let itemInfo = phone.itemInfo {
result.cellNumbers.append(itemInfo.description)
}
} else if phone.itemLabel == "WORK" {

// 固定電話
if let itemInfo = phone.itemInfo {
result.phoneNumbers.append(itemInfo.description)
}
}
}
}

/// メールアドレス
if let emails = info.emails as? [ISContactItem] {

for email in emails {

if email.itemLabel == "WORK" {

if let itemInfo = email.itemInfo {
result.emails.append(itemInfo.description)
}
}
}
}

/// URL
if let urls = info.urls as? [ISContactItem] {

for url in urls {

if url.itemLabel == "HOMEPAGE" {

if let itemInfo = url.itemInfo {
result.urls.append(itemInfo.description)
}
}
}
}

/// 住所
if let addresses = info.addresses as? [ISContactAddress] {
result.address = addresses
}
return result
}
}



2.3. 利用する。


ViewController.swift

import UIKit

final class ViewController: UIViewController {

private let ocrManager = ORCManager()

override func viewDidLoad() {
super.viewDidLoad()
ocrManager.verify()
}

@IBAction func clickTakePhotoButtonMethod(_ sender: Any) {

guard let image = UIImage(named: "demo.jpg") else {
return
}

ocrManager.analyze(originImage: image)
}
}



まとめ

OCRの精度については、お試しあれ!

参考までに