ML Kit を使用すると、バーコードを認識してデコードできます。
試してみる
- サンプルアプリを試してみると、この API の使用例を確認できます。
始める前に
- Podfile に次の ML Kit Pod を含めます。
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- プロジェクトの Pod をインストールまたは更新したら、
.xcworkspace
を使用して Xcode プロジェクトを開きます。ML Kit は Xcode バージョン 12.4 以降でサポートされています。
入力画像に関するガイドライン
-
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 ピクセル以上です。
-
画像のフォーカスが弱いと、スキャンの精度に影響が出ることがあります。アプリで許容される結果が得られない場合は、ユーザーに画像を再キャプチャするよう依頼してください。
-
一般的なアプリケーションでは、バーコードをカメラから離れたところからスキャンできるように、1280x720 や 1920x1080 などの高解像度の画像を提供することをおすすめします。
ただし、レイテンシが重要なアプリケーションでは、低解像度で画像をキャプチャすることでパフォーマンスを向上させることができます。ただし、入力画像の大部分をバーコードが占めている必要があります。リアルタイムのパフォーマンスを改善するためのヒントもご覧ください。
1. バーコード スキャナを設定する
読み取るバーコード形式がわかっている場合は、その形式だけをスキャンするように構成することで、バーコード スキャナの速度を向上させることができます。たとえば、Aztec コードと QR コードのみをスキャンするには、次の例のように BarcodeScannerOptions
オブジェクトをビルドします。
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
次の形式がサポートされています。
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- ユーザー認証
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
次の形式がサポートされています。
- Code-128(
MLKBarcodeFormatCode128
) - Code-39(
MLKBarcodeFormatCode39
) - Code-93(
MLKBarcodeFormatCode93
) - Codabar(
MLKBarcodeFormatCodaBar
) - データ マトリックス(
MLKBarcodeFormatDataMatrix
) - EAN-13(
MLKBarcodeFormatEAN13
) - EAN-8(
MLKBarcodeFormatEAN8
) - ITF(
MLKBarcodeFormatITF
) - QR コード(
MLKBarcodeFormatQRCode
) - UPC-A(
MLKBarcodeFormatUPCA
) - UPC-E(
MLKBarcodeFormatUPCE
) - PDF-417(
MLKBarcodeFormatPDF417
) - Aztec Code(
MLKBarcodeFormatAztec
)
2. 入力画像を準備する
画像内のバーコードをスキャンするには、画像をUIImage
または CMSampleBufferRef
として BarcodeScanner
の process()
メソッドまたは results(in:)
メソッドに渡します。
UIImage
または CMSampleBuffer
を使用して VisionImage
オブジェクトを作成します。
UIImage
を使用する場合は、次の操作を行います。
UIImage
を使用してVisionImage
オブジェクトを作成します。正しい.orientation
を指定してください。Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
CMSampleBuffer
を使用する場合は、次の操作を行います。
-
CMSampleBuffer
に含まれる画像データの向きを指定します。画像の向きを取得するには:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
CMSampleBuffer
オブジェクトと画面の向きを使用して、VisionImage
オブジェクトを作成します。Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. BarcodeScanner のインスタンスを取得する
BarcodeScanner
のインスタンスを取得します。Swift
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
Objective-C
MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner]; // Or, to change the default settings: // MLKBarcodeScanner *barcodeScanner = // [MLKBarcodeScanner barcodeScannerWithOptions:options];
4. 画像を処理する
次に、画像をprocess()
メソッドに渡します。
Swift
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
Objective-C
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
5. バーコードから情報を取得する
バーコード スキャン処理が成功すると、スキャナはBarcode
オブジェクトの配列を返します。各 Barcode
オブジェクトは画像内で検出されたバーコードを表します。バーコードごとに、入力画像の境界座標と、バーコードによってエンコードされた元データを取得できます。また、バーコード スキャナがバーコードでエンコードされたデータの種類を特定できた場合は、解析されたデータを含むオブジェクトを取得できます。
例:
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 (MLKBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; MLKBarcodeValueType valueType = barcode.valueType; switch (valueType) { case MLKBarcodeValueTypeWiFi: ssid = barcode.wifi.ssid; password = barcode.wifi.password; encryptionType = barcode.wifi.type; break; case MLKBarcodeValueTypeURL: url = barcode.URL.url; title = barcode.URL.title; break; // ... default: break; } }
リアルタイムのパフォーマンスを改善するためのヒント
リアルタイムのアプリケーションでバーコードをスキャンする場合は、最適なフレームレートを得るために次のガイドラインに従ってください。
-
カメラのネイティブ解像度で入力をキャプチャしないでください。一部のデバイスでは、ネイティブ解像度で入力をキャプチャすると、非常に大きな画像(10 メガピクセル以上)が生成されますが、レイテンシが非常に低く、精度には何のメリットもありません。代わりに、バーコード スキャンに必要なサイズ(通常は 2 メガピクセル以下)のみをカメラにリクエストしてください。
ただし、名前が付いたキャプチャ セッション プリセット(
AVCaptureSessionPresetDefault
、AVCaptureSessionPresetLow
、AVCaptureSessionPresetMedium
など)は、一部のデバイスで不適切な解像度にマッピングされる可能性があるため、おすすめしません。代わりに、AVCaptureSessionPreset1280x720
などの特定のプリセットを使用してください。スキャン速度が重要な場合は、画像キャプチャの解像度をさらに下げることができます。ただし、上記のバーコード サイズの最小要件に注意してください。
一連のストリーミング動画フレームからバーコードを認識する場合、認識機能でフレームごとに異なる結果が生成されることがあります。適切な結果を確実に返すには、同じ値が連続して得られるまで待つ必要があります。
チェックサム ディジットは、ITF と CODE-39 ではサポートされていません。
- 動画フレームの処理には、検出機能の
results(in:)
同期 API を使用します。このメソッドをAVCaptureVideoDataOutputSampleBufferDelegate
のcaptureOutput(_, didOutput:from:)
関数から呼び出して、指定された動画フレームから同期的に結果を取得します。AVCaptureVideoDataOutput
のalwaysDiscardsLateVideoFrames
をtrue
のままにして、検出機能の呼び出しをスロットリングします。検出機能の実行中に新しい動画フレームが使用可能になると、そのフレームは破棄されます。 - 検出機能の出力を使用して入力画像にグラフィックをオーバーレイする場合は、まず ML Kit から結果を取得してから、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、ディスプレイ サーフェスへのレンダリングは、処理された入力フレームごとに 1 回だけ行います。例については、ML Kit クイックスタート サンプルの updatePreviewOverlayViewWithLastFrame をご覧ください。