「名刺撮影用カメラ」の文字をOCRで読んでみた(Computer Vision API)
1 はじめに
前回作成した、「名刺撮影用カメラ」で写した名刺から、OCRで文字をテキスト化してみました。
AVFoundation+OpenCVで矩形検出(「名刺撮影用カメラ」みたいなやつ作ってみました)
動作しているようすは、下記のとおりです。
2 Computer Vision API
OCRとしては、MicrosoftのComputer Vision API(Preview) の Read text in images を使用しました。
実は、iOSで利用可能なOSSのOCRを複数試してみたのですが、ちょっと日本語の読み取りは、きつい感じだったので、諦めました。 (すいません、使い方が未熟なだけかも知れません、精度を上げる方法をご存じの方がおられましたら、是非、教えてください。)
Computer Vision API(Preview) の Read text in images は、名刺のような活字であれば、ある程度以上の解像度で、ほぼ100%変換できる感じがしました。
Microsoft Cognitive Servicesは、“Developer Code of Conduct for Microsoft Cognitive Services”に従うことで利用可能です。
http://go.microsoft.com/fwlink/?LinkId=698895
月間、5,000トランザクション、分間、20トランザクションまでなら、無料で利用が可能ですので、色々試してみることができると思います。
3 swiftによる実装
キーの取得方法や、APIの使用方法については、各所で紹介されていますので、ここでは、Swiftでアクセスしたコードのみ紹介させて頂きます。
下記は、RestAPIへアクセスするためのクラスです。
class Ocr { let url = "https://api.projectoxford.ai/vision/v1.0/ocr" let key = "API Key xxxxxxxxxxxxxxxxxxxxxxxxxx" func recognizeCharacters(imageData: Data, language: String, detectOrientation: Bool,completion: @escaping (_ response: [String]? ) -> Void) throws { let requestUrlString = url + "?language=" + language + "&detectOrientation%20=\(detectOrientation)" var request = URLRequest(url: URL(string: requestUrlString)!) request.setValue(key, forHTTPHeaderField: "Ocp-Apim-Subscription-Key") request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") request.httpBody = imageData request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request){ data, response, error in if error != nil { completion(nil) return } else { let results = try! JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] DispatchQueue.main.async { completion(self.extractStringsFromDictionary(results!)) } } } task.resume() } // レスポンスのJSONから、文字列を行単位で抽出する fileprivate func extractStringsFromDictionary(_ dictionary: [String:AnyObject]) -> [String] { var result: [String] = [] let regions = dictionary["regions"] as? [[String:AnyObject]] for region in regions! { let lines = region["lines"] as! NSArray let inLine = lines.map {($0 as? NSDictionary)?["words"] as! [[String:AnyObject]] } inLine.map { $0.map { $0["text"] as! String }.reduce("", +) }.forEach { result.append($0) } result.append("") } return result } }
上のクラスを使用して、名刺の画像を送ると、文字列を取得できます。
try! ocr.recognizeCharacters(imageData: UIImagePNGRepresentation(image)!, language: "unk", detectOrientation: true, completion: { (response) in card.lines = response! })
Langageの指定を”unk”にしておくと、言語は向こうで判断してくれます。また、2値化や縦横も傾きの修正も何もかも全部丸投げで大丈夫です。
4 最後に
OCRによる文字の読み取りは、精度が重要だと思います。今回使用したComputer Vision API(Preview) は、非常に精度が高くてビックリしました。 ネットワーク経由での利用なので若干のレイテンシーはありますが、それほど気になるものでもなく、これから、このような分野は、クラウドでの作業が本命になる予感がしました。
5 参考リンク
Computer Vision curl Quick Starts
Computer Vision API - v1.0 OCR
[C#] Cognitive Servicesで光学文字認識(Computer Vision API OCR)