Firebase Summit で発表されたすべての情報をご覧ください。Firebase を使用してアプリ開発を加速し、自信を持ってアプリを実行する方法を紹介しています。詳細

ML Kit を使用してバーコードをスキャンする(iOS)

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。
プレースホルダー32

ML Kitを使用して、バーコードを認識してデコードできます。

あなたが始める前に

  1. アプリにFirebaseをまだ追加していない場合は、スタートガイドの手順に従って追加してください。
  2. ポッドファイルにMLキットライブラリを含めます。l10n
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    プロジェクトのポッドをインストールまたは更新した後、必ず.xcworkspaceを使用してXcodeプロジェクトを開いてください。
  3. アプリで、Firebaseをインポートします。

    迅速

    import Firebase

    Objective-C

    @import Firebase;

入力画像のガイドライン

  • ML Kitがバーコードを正確に読み取るには、入力画像に十分なピクセルデータで表されるバーコードが含まれている必要があります。

    特定のピクセルデータ要件は、バーコードのタイプとそれにエンコードされているデータの量の両方に依存します(ほとんどのバーコードは可変長ペイロードをサポートしているため)。一般に、バーコードの意味のある最小単位は、少なくとも幅2ピクセル(2次元コードの場合は高さ2ピクセル)である必要があります。

    たとえば、EAN-13バーコードは、幅が1、2、3、または4単位のバーとスペースで構成されているため、EAN-13バーコード画像には、理想的には少なくとも2、4、6、および幅8ピクセル。 EAN-13バーコードの幅は合計95単位であるため、バーコードの幅は少なくとも190ピクセルである必要があります。

    PDF417などの高密度フォーマットでは、MLキットがそれらを確実に読み取るために、より大きなピクセル寸法が必要です。たとえば、PDF417コードでは、1行に最大34個の17単位幅の「単語」を含めることができます。これは、理想的には少なくとも1156ピクセル幅です。

  • 画像の焦点が合っていないと、スキャンの精度が低下する可能性があります。許容できる結果が得られない場合は、画像を再キャプチャするようにユーザーに依頼してみてください。

  • 一般的なアプリケーションでは、より高い解像度の画像(1280x720や1920x1080など)を提供することをお勧めします。これにより、カメラから離れた場所からバーコードを検出できるようになります。

    ただし、遅延が重要なアプリケーションでは、低解像度で画像をキャプチャすることでパフォーマンスを向上させることができますが、入力画像の大部分をバーコードで構成する必要があります。リアルタイムのパフォーマンスを向上させるためのヒントも参照してください。

1.バーコード検出器を構成します

読み取る予定のバーコード形式がわかっている場合は、それらの形式のみを検出するように構成することで、バーコード検出器の速度を向上させることができます。

たとえば、AztecコードとQRコードのみを検出するには、次の例のようにVisionBarcodeDetectorOptionsオブジェクトを作成します。

迅速

let format = VisionBarcodeFormat.all
let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)

次の形式がサポートされています。

  • Code128
  • Code39
  • Code93
  • CodaBar
  • EAN13
  • EAN8
  • ITF
  • UPCA
  • UPCE
  • QRコード
  • PDF417
  • アステカ
  • DataMatrix

Objective-C

FIRVisionBarcodeDetectorOptions *options =
    [[FIRVisionBarcodeDetectorOptions alloc]
     initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];

次の形式がサポートされています。

  • コード128( FIRVisionBarcodeFormatCode128
  • Code 39( FIRVisionBarcodeFormatCode39
  • コード93( FIRVisionBarcodeFormatCode93
  • Codabar( FIRVisionBarcodeFormatCodaBar
  • EAN-13( FIRVisionBarcodeFormatEAN13
  • EAN-8( FIRVisionBarcodeFormatEAN8
  • ITF( FIRVisionBarcodeFormatITF
  • UPC-A( FIRVisionBarcodeFormatUPCA
  • UPC-E( FIRVisionBarcodeFormatUPCE
  • QRコード( FIRVisionBarcodeFormatQRCode
  • PDF417( FIRVisionBarcodeFormatPDF417
  • アステカ( FIRVisionBarcodeFormatAztec
  • データマトリックス( FIRVisionBarcodeFormatDataMatrix

2.バーコード検出器を実行します

画像内のバーコードをスキャンするには、画像をUIImageまたはCMSampleBufferRefとしてVisionBarcodeDetectordetect(in:)メソッドに渡します。

  1. VisionBarcodeDetectorのインスタンスを取得します。

    迅速

    lazy var vision = Vision.vision()
    
    let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
    

    Objective-C

    FIRVision *vision = [FIRVision vision];
    FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector];
    // Or, to change the default settings:
    // FIRVisionBarcodeDetector *barcodeDetector =
    //     [vision barcodeDetectorWithOptions:options];
    
  2. UIImageまたはCMSampleBufferRefを使用してVisionImageオブジェクトを作成します。

    UIImageを使用するには:

    1. 必要に応じて、 imageOrientationプロパティが.upになるように画像を回転します。
    2. 正しく回転されたUIImageを使用してVisionImageオブジェクトを作成します。ローテーションメタデータは指定しないでください。デフォルト値の.topLeftを使用する必要があります。

      迅速

      let image = VisionImage(image: uiImage)

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    CMSampleBufferRefを使用するには:

    1. CMSampleBufferRefバッファーに含まれる画像データの方向を指定するVisionImageMetadataオブジェクトを作成します。

      画像の向きを取得するには:

      迅速

      func imageOrientation(
          deviceOrientation: UIDeviceOrientation,
          cameraPosition: AVCaptureDevice.Position
          ) -> VisionDetectorImageOrientation {
          switch deviceOrientation {
          case .portrait:
              return cameraPosition == .front ? .leftTop : .rightTop
          case .landscapeLeft:
              return cameraPosition == .front ? .bottomLeft : .topLeft
          case .portraitUpsideDown:
              return cameraPosition == .front ? .rightBottom : .leftBottom
          case .landscapeRight:
              return cameraPosition == .front ? .topRight : .bottomRight
          case .faceDown, .faceUp, .unknown:
              return .leftTop
          }
      }

      Objective-C

      - (FIRVisionDetectorImageOrientation)
          imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                                 cameraPosition:(AVCaptureDevicePosition)cameraPosition {
        switch (deviceOrientation) {
          case UIDeviceOrientationPortrait:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationLeftTop;
            } else {
              return FIRVisionDetectorImageOrientationRightTop;
            }
          case UIDeviceOrientationLandscapeLeft:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationBottomLeft;
            } else {
              return FIRVisionDetectorImageOrientationTopLeft;
            }
          case UIDeviceOrientationPortraitUpsideDown:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationRightBottom;
            } else {
              return FIRVisionDetectorImageOrientationLeftBottom;
            }
          case UIDeviceOrientationLandscapeRight:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationTopRight;
            } else {
              return FIRVisionDetectorImageOrientationBottomRight;
            }
          default:
            return FIRVisionDetectorImageOrientationTopLeft;
        }
      }

      次に、メタデータオブジェクトを作成します。

      迅速

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      Objective-C

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. CMSampleBufferRefオブジェクトと回転メタデータを使用してVisionImageオブジェクトを作成します。

      迅速

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. 次に、画像をdetect(in:)メソッドに渡します。

    迅速

    barcodeDetector.detect(in: visionImage) { features, error in
      guard error == nil, let features = features, !features.isEmpty else {
        // ...
        return
      }
    
      // ...
    }
    

    Objective-C

    [barcodeDetector detectInImage:image
                        completion:^(NSArray<FIRVisionBarcode *> *barcodes,
                                     NSError *error) {
      if (error != nil) {
        return;
      } else if (barcodes != nil) {
        // Recognized barcodes
        // ...
      }
    }];
    

3.バーコードから情報を取得します

バーコード認識操作が成功すると、検出器はVisionBarcodeオブジェクトの配列を返します。各VisionBarcodeオブジェクトは、画像で検出されたバーコードを表します。バーコードごとに、入力画像の境界座標と、バーコードによってエンコードされた生データを取得できます。また、バーコード検出器がバーコードによってエンコードされたデータのタイプを判別できた場合は、解析されたデータを含むオブジェクトを取得できます。

例えば:

迅速

for barcode in barcodes {
  let corners = barcode.cornerPoints

  let displayValue = barcode.displayValue
  let rawValue = barcode.rawValue

  let valueType = barcode.valueType
  switch valueType {
  case .wiFi:
    let ssid = barcode.wifi!.ssid
    let password = barcode.wifi!.password
    let encryptionType = barcode.wifi!.type
  case .URL:
    let title = barcode.url!.title
    let url = barcode.url!.url
  default:
    // See API reference for all supported value types
  }
}

Objective-C

 for (FIRVisionBarcode *barcode in barcodes) {
   NSArray *corners = barcode.cornerPoints;

   NSString *displayValue = barcode.displayValue;
   NSString *rawValue = barcode.rawValue;

   FIRVisionBarcodeValueType valueType = barcode.valueType;
   switch (valueType) {
     case FIRVisionBarcodeValueTypeWiFi:
       // ssid = barcode.wifi.ssid;
       // password = barcode.wifi.password;
       // encryptionType = barcode.wifi.type;
       break;
     case FIRVisionBarcodeValueTypeURL:
       // url = barcode.URL.url;
       // title = barcode.URL.title;
       break;
     // ...
     default:
       break;
   }
 }

リアルタイムのパフォーマンスを向上させるためのヒント

リアルタイムアプリケーションでバーコードをスキャンする場合は、次のガイドラインに従って、最高のフレームレートを実現してください。

  • カメラのネイティブ解像度で入力をキャプチャしないでください。一部のデバイスでは、ネイティブ解像度で入力をキャプチャすると、非常に大きな(10メガピクセル以上)画像が生成されるため、待ち時間が非常に短くなり、精度にメリットがありません。代わりに、バーコード検出に必要なサイズ(通常は2メガピクセル以下)のみをカメラに要求してください。

    ただし、名前付きのキャプチャセッションプリセット( AVCaptureSessionPresetDefaultAVCaptureSessionPresetLowAVCaptureSessionPresetMediumなど)は、一部のデバイスで不適切な解像度にマップされる可能性があるため、お勧めしません。代わりに、 AVCaptureSessionPreset1280x720などの特定のプリセットを使用してください。

    スキャン速度が重要な場合は、画像キャプチャの解像度をさらに下げることができます。ただし、上記の最小バーコードサイズ要件に注意してください。

  • スロットルが検出器を呼び出します。検出器の実行中に新しいビデオフレームが使用可能になった場合は、フレームをドロップします。
  • 検出器の出力を使用して入力画像にグラフィックをオーバーレイする場合は、最初にMLキットから結果を取得してから、画像とオーバーレイを1つのステップでレンダリングします。そうすることで、入力フレームごとに1回だけ表示面にレンダリングします。例については、ショーケースサンプルアプリのpreviewOverlayViewクラスとFIRDetectionOverlayViewクラスを参照してください。