この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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)