Help us understand the problem. What is going on with this article?

iOSのバーコードリーダーで読み取り範囲を設定する

More than 1 year has passed since last update.

1次元バーコードリーダーを使ったiPhoneアプリを作ろうとした時に,カメラの全画面でなく特定の範囲のみを読み取る設定をするだけのことで案外詰まった。
検索してもなかなか出てこなかったので共有。

環境

OS X 10.10.3
Xcode 6.4
iOS 8.4
iPhone6(実機でのみ動作)

カメラ画像の表示にはAVCaptureVideoPreviewLayerを
読み取りにはAVFoundationを使用

読み取り範囲を指定する

// metadata取得に必要な初期設定
let metaOutput = AVCaptureMetadataOutput();
metaOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue());
self.captureSession.addOutput(metaOutput);

// バーコードリーダーの読み取り範囲を設定する
metaOutput.rectOfInterest = CGRectMake(y, 1-x-width, height, width)

AVCaptureMetadataOutputのrectOfInterestにCGRectを渡すことで解析範囲を 0 ~ 1.0 の範囲で指定する。
metaOutputの初期設定ではカメラの向きが横(landscape)になっているためパラメータの位置関係が通常と異なるということに気をつけなければならない。

デフォルトの位置関係

layout_default.png

metaOutputでの位置関係

layout_camera.png

ソースコード全容

Single View Applicationで作成した新規プロジェクトのViewControllerにコピペするだけでOK
読み取り可能範囲に赤い囲み線を表示し,読み取った内容をログに吐き出している
https://github.com/tomosooon/barcode-reader-sample

ViewController.swift
import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    let captureSession = AVCaptureSession();
    var previewLayer: AVCaptureVideoPreviewLayer?
    var captureDevice: AVCaptureDevice?

    // 読み取り範囲(0 ~ 1.0の範囲で指定)
    let x: CGFloat = 0.1
    let y: CGFloat = 0.4
    let width: CGFloat = 0.8
    let height: CGFloat = 0.2

    override func viewDidLoad() {
        super.viewDidLoad()

        // カメラがあるか確認し,取得する
        self.captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        var error : NSError?
        let inputDevice = AVCaptureDeviceInput(device: self.captureDevice, error: &error)
        if let inp = inputDevice {
            self.captureSession.addInput(inp)
        } else {
            println(error)
        }

        // カメラからの取得映像を画面全体に表示する
        self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
        self.previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        self.previewLayer?.frame = CGRectMake(0, 0, self.view.bounds.width, self.view.bounds.height)
        self.view.layer.insertSublayer(self.previewLayer, atIndex: 0)

        // metadata取得に必要な初期設定
        let metaOutput = AVCaptureMetadataOutput();
        metaOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue());
        self.captureSession.addOutput(metaOutput);

        // どのmetadataを取得するか設定する
        metaOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN13Code];

        // どの範囲を解析するか設定する
        metaOutput.rectOfInterest = CGRectMake(y, 1-x-width, height, width)

        // 解析範囲を表すボーダービューを作成する
        let borderView = UIView(frame: CGRectMake(x * self.view.bounds.width, y * self.view.bounds.height, width * self.view.bounds.width, height * self.view.bounds.height))
        borderView.layer.borderWidth = 2
        borderView.layer.borderColor = UIColor.redColor().CGColor
        self.view.addSubview(borderView)

        // capture session をスタートする
        self.captureSession.startRunning()
    }

    // 映像からmetadataを取得した場合に呼び出されるデリゲートメソッド
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

        // metadataが複数ある可能性があるためfor文で回す
        for data in metadataObjects {
            if data.type == AVMetadataObjectTypeEAN13Code {
                // 読み取りデータの全容をログに書き出す
                println("読み取りデータ:\(data)")
                println("データの文字列:\(data.stringValue)")
                println("データの位置:\(data.bounds)")
            }
        }
    }
}
tomosooon
東京大学工学部機械情報工学科→東京大学院知能機械情報学と進んだ後,1年次に休学し株式会社mikanのCTOとして日々開発中
fringe81
Fringeは、最新のテクノロジーとプロフェッショナルによるサービスにより、社会課題に仮説を立てて市場に広げていくことで、数十年という長期的なスパンで価値を生み出し続け、より良い世界を創る集団です。 既存の領域に限らず、時流を読み、仮説を生み出し、テクノロジーの力で優れたサービスを生み出し続けます。
https://www.fringe81.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした