Memindai kode batang dengan ML Kit di iOS

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

Cobalah

  • Silakan coba aplikasi contoh ini untuk melihat contoh penggunaan API ini.

Sebelum memulai

  1. Sertakan pod ML Kit berikut di Podfile Anda:
    pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
    
  2. Setelah menginstal atau mengupdate Pod project, buka project Xcode menggunakan .xcworkspace-nya. 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 tertentu bergantung pada jenis kode batang dan jumlah data yang dienkode di dalamnya, karena banyak kode batang mendukung payload ukuran variabel. Secara umum, unit terkecil yang bermakna pada kode batang harus berukuran lebar minimal 2 piksel, dan untuk kode 2 dimensi, tingginya minimal 2 piksel.

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

    Format yang lebih padat, seperti PDF417, memerlukan dimensi piksel yang lebih besar agar ML Kit dapat membacanya dengan andal. Misalnya, kode PDF417 dapat memiliki hingga 34 "kata" dengan lebar unit 17 dalam satu baris, yang idealnya memiliki lebar minimal 1.156 piksel.

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

  • Untuk aplikasi standar, sebaiknya sediakan gambar beresolusi lebih tinggi, seperti 1280x720 atau 1920x1080, agar kode batang dapat dipindai dari jarak yang lebih jauh dari kamera.

    Namun, dalam aplikasi yang sangat mementingkan latensi, Anda dapat meningkatkan performa dengan mengambil gambar pada resolusi lebih rendah, tetapi mengharuskan kode batang menjadi bagian utama gambar input. Baca 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 mengonfigurasinya agar hanya memindai format tersebut.

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

Swift

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

Format berikut ini didukung:

  • code128
  • code39
  • code93
  • codaBar
  • dataMatrix
  • EAN13
  • EAN8
  • ITF
  • qrCode
  • {i>UPCA<i}
  • 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. Siapkan gambar input

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

Buat objek VisionImage menggunakan UIImage atau 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 dimuat 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 menampilkan array objek Barcode. Setiap objek Barcode mewakili kode batang yang terdeteksi di dalam gambar. Untuk setiap kode batang, Anda bisa mendapatkan koordinat pembatasnya di gambar input, serta data mentah yang dienkode oleh kode batang. Selain itu, jika pemindai kode batang dapat menentukan jenis data yang dienkode oleh kode batang, Anda bisa mendapatkan objek yang berisi data yang telah 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 ini untuk mencapai frekuensi gambar terbaik:

  • Jangan ambil input pada resolusi native kamera. Di beberapa perangkat, pengambilan input pada resolusi native akan menghasilkan gambar yang sangat besar (10+ megapiksel), sehingga menghasilkan latensi yang sangat buruk tanpa berpengaruh pada akurasi. Sebagai gantinya, hanya minta ukuran dari kamera yang diperlukan untuk pemindaian kode batang, yang biasanya tidak lebih dari 2 megapiksel.

    Namun, sebaiknya jangan gunakan preset sesi pengambilan nama yang bernama—AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium, dan seterusnya, karena dapat dipetakan ke resolusi yang tidak sesuai di beberapa perangkat. Sebagai gantinya, gunakan preset spesifik seperti AVCaptureSessionPreset1280x720.

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

    Jika Anda mencoba mengenali kode batang dari urutan frame video streaming, pengenal mungkin akan memberikan hasil yang berbeda dari satu frame ke frame lainnya. Anda harus menunggu sampai mendapatkan rangkaian berturut-turut dengan nilai yang sama untuk yakin bahwa Anda menampilkan hasil yang baik.

    Digit Checksum tidak didukung untuk ITF dan CODE-39.

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