Memindai kode batang dengan ML Kit di iOS

Anda dapat menggunakan ML Kit untuk mengenali dan mendekode kode batang.

Cobalah

Sebelum memulai

  1. Sertakan pod ML Kit berikut di Podfile Anda:
    pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
    
  2. Setelah Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan .xcworkspace. ML Kit didukung di Xcode versi 12.4 atau yang lebih baru.

Panduan gambar input

  • Agar ML Kit dapat membaca kode batang secara akurat, gambar input harus berisi kode batang yang diwakili oleh data piksel yang memadai.

    Persyaratan data piksel yang spesifik tergantung pada jenis kode batang dan jumlah data yang dikodekan di dalamnya, karena banyak kode batang mendukung payload ukuran variabel. Secara umum, nilai terkecil yang unit kode batang harus setidaknya selebar 2 piksel, dan untuk kode 2 dimensi, tinggi 2 piksel.

    Misalnya, kode batang EAN-13 terdiri dari batang dan spasi yang bernilai 1, Lebarnya 2, 3, atau 4 unit, sehingga gambar kode batang EAN-13 idealnya memiliki batang dan spasi minimal berukuran 2, 4, 6, dan 8 piksel. Karena EAN-13 kode batang memiliki lebar total 95 unit, kode batang minimal harus 190 selebar piksel.

    Format yang lebih padat, seperti PDF417, membutuhkan dimensi piksel yang lebih besar untuk ML Kit untuk membacanya dengan andal. Misalnya, kode PDF417 dapat memiliki hingga 34 "kata-kata" lebar 17 unit dalam satu baris, yang idealnya akan berukuran minimal Lebar 1156 piksel.

  • Fokus gambar yang buruk dapat memengaruhi akurasi pemindaian. Jika aplikasi Anda tidak mendapatkan akan memberikan hasil yang dapat diterima, meminta pengguna untuk mengambil ulang gambar.

  • Untuk aplikasi biasa, sebaiknya berikan akses gambar beresolusi, seperti 1280x720 atau 1920x1080, yang akan membuat kode batang dapat dipindai dari jarak jauh dari kamera.

    Namun, pada aplikasi yang sangat membutuhkan latensi, Anda dapat meningkatkan performa tinggi dengan mengambil gambar pada resolusi yang lebih rendah, tetapi memerlukan kode batang membentuk mayoritas gambar input. Lihat juga Tips untuk meningkatkan performa real-time.

1. Mengonfigurasi pemindai kode batang

Jika mengetahui format kode batang yang ingin dibaca, Anda dapat meningkatkan kecepatan pemindai kode batang dengan mengkonfigurasinya agar hanya memindai format tersebut.

Misalnya, untuk memindai kode Aztec dan kode QR saja, buat BarcodeScannerOptions seperti dalam contoh berikut:

Swift

let format = .all
let barcodeOptions = BarcodeScannerOptions(formats: format)
  

Format berikut ini didukung:

  • code128
  • code39
  • code93
  • codaBar
  • dataMatrix
  • EAN13
  • EAN8
  • ITF
  • qrCode
  • UPCA
  • UPCE
  • PDF417
  • Aztec

Objective-C

MLKBarcodeScannerOptions *options =
  [[MLKBarcodeScannerOptions alloc]
   initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];

Format berikut ini didukung:

  • Kode-128 (MLKBarcodeFormatCode128)
  • Kode-39 (MLKBarcodeFormatCode39)
  • Kode-93 (MLKBarcodeFormatCode93)
  • Codabar (MLKBarcodeFormatCodaBar)
  • Matriks Data (MLKBarcodeFormatDataMatrix)
  • EAN-13 (MLKBarcodeFormatEAN13)
  • EAN-8 (MLKBarcodeFormatEAN8)
  • ITF (MLKBarcodeFormatITF)
  • Kode QR (MLKBarcodeFormatQRCode)
  • UPC-A (MLKBarcodeFormatUPCA)
  • UPC-E (MLKBarcodeFormatUPCE)
  • PDF-417 (MLKBarcodeFormatPDF417)
  • Kode Aztec (MLKBarcodeFormatAztec)

2. Menyiapkan gambar input

Untuk memindai kode batang dalam gambar, teruskan gambar sebagai UIImage atau CMSampleBufferRef ke process() atau results(in:) BarcodeScanner berikut:

Buat objek VisionImage menggunakan UIImage atau objek CMSampleBuffer.

Jika Anda menggunakan UIImage, ikuti langkah-langkah berikut:

  • Buat objek VisionImage dengan UIImage. Pastikan untuk menentukan .orientation yang benar.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Jika Anda menggunakan CMSampleBuffer, ikuti langkah-langkah berikut:

  • Tentukan orientasi data gambar yang terdapat dalam CMSampleBuffer.

    Untuk mendapatkan orientasi gambar:

    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;
      }
    }
          
  • Buat objek VisionImage menggunakan Objek dan orientasi CMSampleBuffer:

    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. Mendapatkan instance BarcodeScanner

Dapatkan instance 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. Memproses gambar

Lalu, teruskan gambar ke metode 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. Mendapatkan informasi dari kode batang

Jika operasi pemindaian kode batang berhasil, pemindai akan mengembalikan array Objek Barcode. Setiap objek Barcode mewakili kode batang yang terdeteksi dalam gambar. Untuk setiap kode batang, Anda bisa mendapatkan koordinat pembatas pada gambar input, serta data mentah yang dienkode oleh kode batang. Juga, jika pemindai kode batang mampu menentukan jenis data yang dienkode oleh kode batang, Anda bisa mendapatkan objek yang berisi data yang diuraikan.

Contoh:

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;
   }
 }

Tips untuk meningkatkan performa real-time

Jika Anda ingin memindai kode batang dalam aplikasi real-time, ikuti panduan untuk mencapai kecepatan frame terbaik:

  • Jangan mengambil input pada resolusi native kamera. Pada beberapa perangkat, menangkap input dengan resolusi native menghasilkan output yang sangat besar (10+ megapiksel), yang menghasilkan latensi yang sangat buruk tanpa manfaat untuk tingkat akurasi. Sebagai gantinya, hanya minta ukuran dari kamera yang diperlukan untuk pemindaian kode batang, yang biasanya berukuran tidak lebih dari 2 megapiksel.

    Preset sesi pengambilan bernama—AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium, dan seterusnya)—tidak disarankan, karena dapat dipetakan ke resolusi yang tidak sesuai pada beberapa perangkat. Sebagai gantinya, gunakan preset spesifik misalnya AVCaptureSessionPreset1280x720.

    Jika kecepatan pemindaian penting, Anda dapat menurunkan pengambilan gambar resolusi. Namun, perhatikan persyaratan ukuran kode batang minimum yang diuraikan di atas.

    Jika Anda mencoba mengenali kode batang dari urutan streaming {i>frame<i} video, pengenal mungkin menghasilkan hasil yang berbeda dari {i>frame<i} ke {i>frame<i} {i>frame<i}. Anda harus menunggu sampai Anda mendapatkan rangkaian nilai untuk yakin bahwa Anda memberikan hasil yang baik.

    Digit Checksum tidak didukung untuk ITF dan CODE-39.

  • Untuk memproses frame video, gunakan API sinkron results(in:) dari detektor. Telepon metode ini dari class AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) untuk mendapatkan hasil dari video yang diberikan secara sinkron {i>frame<i}. Simpan AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames sebagai true untuk men-throttle panggilan ke detektor. Jika frame video tersedia saat detektor sedang berjalan, dan frame tersebut akan dihapus.
  • Jika Anda menggunakan output detektor untuk menempatkan grafik gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan overlay dalam satu langkah. Dengan demikian, Anda merender ke permukaan tampilan hanya sekali untuk setiap {i> frame<i} input yang diproses. Lihat updatePreviewOverlayViewWithLastFrame dalam contoh panduan memulai ML Kit sebagai contoh.