このページの本文へ

Swift Playgroundsで学ぶiOSプログラミング第64回

低レベルのカメラ機能を使ってQRコードをスキャン

QRコードの内容を読み取るプログラム

2017年12月04日 17時00分更新

文● 柴田文彦 編集●吉田ヒロ

  • この記事をはてなブックマークに追加
  • 本文印刷

 前回は、ジェネレーターカテゴリーのCore Imageのフィルターを使って、入力した文字列をQRコード(2次元バーコード)の画像に変換するプログラムを作りました。しかし、そのままでは、生成したQRコードが正しいのか確認する術がありません。そこで今回は、QRコードの内容を読み取るプログラムを作成します。

 そのためには、もちろんiPadの内蔵カメラを使います。もし、Core ImageにQRコードの画像を入力としてその内容を出力するという、前回使ったものと逆の機能があれば楽なのですが、残念ながらそのようなフィルターはありません。もちろん撮影した写真のピクセルの値(画像の濃淡)を1つずつ調べて、QRコードをデコードするプログラムをゼロから書くことも不可能ではありませんが、画像解析の技術が必要となりプログラムもかなり大規模なものとなってしまいます。

 しかしiOSのAVFoundationには、カメラを使って撮影しながらその中に含まれるバーコードやQRコードをスキャンして内容を読み取る機能が備わっています。Core Imageと一緒に使ったImage Pickerより、ずっと低レベル(ハードウェアに近い)の機能です。撮影時のUIやファインダー機能も含んでいないので、すべて自前で用意してやる必要があります。とはいえ、その部分は大した手間ではありません。さっそくプログラムを書いていきましょう。

AVキャプチャー機能を利用

 撮影機能としては、AVFoundationのAVCaptureSessionというクラスを使います。これは、その名のとおり一種のキャプチャ機能ですが、かなりフレキシブルにできています。このオブジェクトには入力と出力を設定します。それらの設定次第で単なるカメラとしてだけでなく、さまざまな用途に対応するのです。

 今回は、入力にiPadのリアカメラを指定します。出力として、静止画を設定すれば写真撮影もできますし、動画を設定すればビデオ撮影も可能です。ただし今回はそのどちらでもなく、メタデータを出力に指定します。メタデータとは今回の場合、認識して読み取ったQRコードということになります。そのメタデータから、内容を表す文字列も取り出すことができます。

 今回のプログラムの大まかな流れは、まずAVCaptureSessionのオブジェクトを作成し、そこに入力と出力を設定してから、セッションを起動し、デコード可能なパターンが視野に入ったら、自動的にデコードして結果を表示する――といったものになります。実際には撮影中の画像(映像)を表示しないと、ユーザーがどこを狙ってカメラの視野を決めればいいかわかりません。そこで、プレビュー用のレイヤーというものも用意してイメージビュー(UIImageView)に表示します。

 すでに述べたように、AVFoundationはかなり低レベルな部分をカバーするものなので、今回のプログラムも、細かな設定が多くなっています。それらの解説は省きますが、上で説明した流れを理解していれば、自然に意味もわかってくるでしょう。

 プログラムの先頭部分では、いつものUIKitとPlaygroundSupportに加えてAVFoundationをインポートしています。プログラム本体としてCamViewControllerクラスを作りますが、そのクラスに対して、AVCaptureMetadataOutputObjectsDelegateのプロトコルを指定しています。これは撮影中の画像の中にQRコードなどが見つかると、自動的に呼び出されて、デコード処理などを実行するメソッドを利用可能にするものです。

 このクラスのプロパティとしては、カメラのファインダーとして機能するcamView、撮影を開始するボタンとしてscanButton、デコードされたQRコードの内容を表示するラベルのdecoded、上で説明したAVCaptureSessionのsession、プレビュー用のレイヤーのlayerを定義しています。

AVFoundationを使って、QRコードをデコードし内容を文字列として表示するCamViewControllerクラスの先頭部分です。ユーザーインターフェースとしては、撮影中の画像を表示するファインダーとして機能するイメージビュー、撮影を開始するボタン、結果を表示するラベルを使います

 ビューコントローラーのviewDidLoadメソッドの中では、ビューの背景色の設定の他、ファインダーとして使うイメージビュー、撮影ボタン、内容表示のラベルを初期設定して、ビューに張り付けています(図2)。

ビューコントローラーのビューが最初にロードされた直後に呼ばれるviewDidLoadメソッドの中では、ユーザーインターフェースの初期設定のみを実行しています。ボタンについては、タップすると別途定義するscanCodeメソッドを呼ぶように設定しています

この連載の記事

週間ランキングTOP5

ASCII倶楽部会員によく見られてる記事はコレだ!

ASCII倶楽部の新着記事

会員専用動画の紹介も!