[iOS 8]CIQRCodeFeatureを使って画像からQRコードを解析する

2014.10.23

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

はじめに

QRコードを検出するCIQRCodeFeatureが新しくiOS8から追加されたので試してみました。

Untitled

今回は下記のアプリを作ってみたいと思います。

写真をライブラリから読み込む ↓ 写真にQRコードがあるかCIQRCodeFeatureで解析する ↓ 見つけたらテキストに表示する

実装

画面構成

プロジェクトはSingleViewApplicationで作成します。 そして、storyboardは下図のように配置しました。

Main_storyboard_—_Edited

ViewController.swift に UIImageView、UITextViewのアウトレットを設定します。 Insert_Connection_と_Main_storyboard_—_Edited

Insert_Connection_と_Main_storyboard_—_Edited_1

また、ボタンのアクションも登録します。

Insert_Connection_と_Main_storyboard_—_Edited_2

これで下準備はOKです。

ソースコード

import UIKit

class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    /** 写真表示用ImageView */
    @IBOutlet weak var photoImageView: UIImageView!
    /** QRコードの読取りテキストを表示 */
    @IBOutlet weak var messageTextView: UITextView!
    /** 画像取得用 */
    var picker:UIImagePickerController?
    /** 画像認識用 */
    var detector:CIDetector?
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
        picker = UIImagePickerController()
        picker!.delegate = self
        picker!.allowsEditing = false
        messageTextView.resignFirstResponder()
    }
    /**
    * アルバムボタンをタップ
    */
    @IBAction func onTapAlbumButton(sender: AnyObject)
    {
        //ライブラリが使用できるかどうか判定
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary))
        {
            self.presentViewController(picker!, animated: true, completion: nil)
        }
    }
    /**
    * 写真選択
    */
    func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!){
        self.dismissViewControllerAnimated(true, completion: nil)
        //画面に写真を表示
        photoImageView.image = image
        //画像を変換
        var ciImage:CIImage = CIImage(image: image)
        var message:String = "";
        //画像内にQRコードがあるか調べる
        let features = detector?.featuresInImage(ciImage)
        for feature in features as [CIQRCodeFeature] {
            message += feature.messageString
        }
        //テキストに表示
        if(message == "") {
            messageTextView.text = "[QRコードは検出されませんでした]";
        } else {
            messageTextView.text = message;
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

41行目でUIImageを画像処理用のCIImageに変換をします。

//画像を変換
var ciImage:CIImage = CIImage(image: image)

画像の種類については下記になります。

UIImage : Viewとして表示するための画像クラス CIImage : CoreImageは画像処理のための画像クラス NSImage : Cocoaで画像データを扱う為のクラス CGImage : UIImageに含まれる

引用:http://qiita.com/oggata/items/8fc84124a256bfa505c0

そして、44行目で画像を渡し、QRコードが存在するか解析します。

//画像内にQRコードがあるか調べる
let features = detector?.featuresInImage(ciImage)
for feature in features as [CIQRCodeFeature] {
    message += feature.messageString
}

feature.messageStringにはQRコードの文字列が取得できます。 メッセージの他にも下記プロパティで位置や形なども取得できます。

CIQRCodeFeature.bottomLeft CIQRCodeFeature.bottomRight CIQRCodeFeature.bounds CIQRCodeFeature.topLeft CIQRCodeFeature.topRight

実行結果について

写真に以下のQRコードを埋め込んで比べてみました。 qr_code_without_logo

IMG_2440

IMG_2439

無事、メッセージを読取る事が出来ました!

最後に

画像に対してQRコード自体が小さめでも読み込む事が出来き、以前より読み込み精度が上がっている印象を受けました。(あくまで、個人的な主観ですが。。。) CIFeatureには他にも画像の中の四角形を検出するCIRectangleFeatureが追加されています。 また、CIDetectorがシミュレーター上では動作しなかったので、実機で試す必要がありますのでご注意下さい。