ML Kit を使用すると、バーコードの認識やデコードができます。
始める前に
- まだアプリに Firebase を追加していない場合は、スタートガイドの手順に沿って追加してください。
- ML Kit ライブラリを Podfile に含めます:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
プロジェクトの Pod をインストールまたは更新した後に、.xcworkspace
を使用して Xcode プロジェクトを開くようにしてください。 - アプリに Firebase をインポートします。
Swift
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 Kit で読み取り精度を高めるため、より大きなピクセル数が必要になります。たとえば、PDF417 コードは 1 行に最大 34 個の 17 単位幅のワードを入れることができるため、1,156 ピクセル以上の幅が理想的です。
-
画像がぼやけていると、スキャン精度が低下する可能性があります。満足のいく結果が得られない場合は、ユーザーに画像をキャプチャし直すよう求めてください。
-
一般的なアプリケーションでは、カメラから遠く離れた位置からバーコードを検出できる、1,280x720 や 1,920x1,080 などの高解像度の画像を使用することをおすすめします。
レイテンシが重要なアプリケーションでは、低解像度で画像をキャプチャすることでパフォーマンスを改善できますが、入力画像の大部分がバーコードである必要があります。リアルタイムのパフォーマンスを改善するためのヒントもご覧ください。
1. バーコード検出器を構成する
読み取るバーコード形式がわかっている場合は、その形式のみを検出するように構成して、バーコード検出器の速度を向上させることができます。たとえば、Aztec コードと QR コードのみを検出するには、次の例のように VisionBarcodeDetectorOptions
オブジェクトをビルドします。
Swift
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
次の形式がサポートされています。
- Code128
- Code39
- Code93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- QRCode
- PDF417
- Aztec
- DataMatrix
Objective-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
次の形式がサポートされています。
- コード 128(
FIRVisionBarcodeFormatCode128
) - コード 39(
FIRVisionBarcodeFormatCode39
) - コード 93(
FIRVisionBarcodeFormatCode93
) - Codabar(
FIRVisionBarcodeFormatCodaBar
) - EAN-13(
FIRVisionBarcodeFormatEAN13
) - EAN-8(
FIRVisionBarcodeFormatEAN8
) - ITF(
FIRVisionBarcodeFormatITF
) - UPC-A(
FIRVisionBarcodeFormatUPCA
) - UPC-E(
FIRVisionBarcodeFormatUPCE
) - QR コード(
FIRVisionBarcodeFormatQRCode
) - PDF417(
FIRVisionBarcodeFormatPDF417
) - Aztec(
FIRVisionBarcodeFormatAztec
) - Data Matrix(
FIRVisionBarcodeFormatDataMatrix
)
2. バーコード検出器を実行する
画像内のバーコードをスキャンするには、画像をUIImage
または CMSampleBufferRef
として VisionBarcodeDetector
の detect(in:)
メソッドに渡します。
VisionBarcodeDetector
のインスタンスを取得します。Swift
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];
-
UIImage
またはCMSampleBufferRef
を使用してVisionImage
オブジェクトを作成します。UIImage
を使用するには:- 必要に応じて、
imageOrientation
プロパティが.up
になるように画像を回転させます。 - 適切に回転させた
UIImage
を使用してVisionImage
オブジェクトを作成します。回転メタデータにはデフォルト値の.topLeft
を使用する必要があるため、値を指定しないでください。Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
CMSampleBufferRef
を使用するには:-
VisionImageMetadata
オブジェクトを作成し、CMSampleBufferRef
バッファに格納されている画像データの向きを指定します。画像の向きは次のように取得します。
Swift
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; } }
次に、メタデータ オブジェクトを作成します。
Swift
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];
VisionImage
オブジェクトと回転メタデータを使用してCMSampleBufferRef
オブジェクトを作成します。Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- 必要に応じて、
-
次に、画像を
detect(in:)
メソッドに渡します。Swift
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
オブジェクトは画像内で検出されたバーコードを表します。バーコードごとに、入力画像の境界座標と、バーコードによってエンコードされた元データを取得できます。また、バーコード検出器がバーコードによってエンコードされたデータのタイプを判別できた場合は、解析されたデータを含むオブジェクトも取得できます。
例:
Swift
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 メガピクセル以下です。
指定されたキャプチャ セッション プリセット(
AVCaptureSessionPresetDefault
、AVCaptureSessionPresetLow
、AVCaptureSessionPresetMedium
など)はおすすめできませんが、一部のデバイスで、不適切な解像度に割り当てられることがあります。代わりに、AVCaptureSessionPreset1280x720
などの特定のプリセットを使用してください。スキャン速度が重要な場合は、画像キャプチャの解像度をさらに下げることができます。ただし、上記の最小バーコード サイズの要件に注意してください。
- 検出器の呼び出しのスロットル調整を行います。検出器の実行中に新しい動画フレームが使用可能になった場合は、そのフレームをドロップします。
- 検出器の出力を使用して入力画像の上にグラフィックスをオーバーレイする場合は、まず ML Kit から検出結果を取得し、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、ディスプレイ サーフェスへのレンダリングは入力フレームごとに 1 回で済みます。例については、ショーケース サンプルアプリの previewOverlayView クラスと FIRDetectionOverlayView クラスをご覧ください。