Memindai Kode Batang dengan ML Kit di iOS

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

Lihat aplikasi showcase Desain Material ML Kit dan sampel panduan memulai ML Kit di GitHub untuk mengetahui contoh penggunaan API ini.

Sebelum memulai

  1. Jika Anda belum menambahkan Firebase ke aplikasi, lakukan dengan mengikuti langkah-langkahnya di panduan memulai.
  2. Sertakan library ML Kit di Podfile Anda:
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    Setelah Anda menginstal atau mengupdate Pod project, pastikan untuk membuka project Xcode menggunakan .xcworkspace-nya.
  3. Di aplikasi Anda, impor Firebase:

    Swift

    import Firebase

    Objective-C

    @import Firebase;

Input panduan gambar

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

    Persyaratan data piksel tertentu bergantung pada jenis kode batang dan jumlah data yang dienkode di dalamnya (karena sebagian besar kode batang mendukung payload panjang variabel). Secara umum, unit terkecil yang bermakna dari kode batang harus memiliki 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 setidaknya memiliki lebar 190 piksel.

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

  • Fokus gambar yang buruk dapat merusak akurasi pemindaian. Jika Anda tidak memperoleh hasil yang dapat diterima, coba minta pengguna untuk mengambil ulang gambar.

  • Untuk aplikasi biasa, sebaiknya sediakan gambar dengan resolusi lebih tinggi (misalnya 1280x720 atau 1920x1080), yang membuat kode batang dapat dideteksi dari jarak yang lebih jauh dari kamera.

    Namun, dalam aplikasi yang sangat mementingkan latensi, Anda dapat meningkatkan performa dengan mengambil gambar pada resolusi yang lebih rendah, tetapi mewajibkan kode batang menjadi bagian terbesar dari gambar input. Lihat juga Tips untuk meningkatkan performa real-time.

1. Mengonfigurasi detektor kode batang

Jika mengetahui format kode batang yang ingin dibaca, Anda dapat meningkatkan kecepatan detektor kode batang dengan mengonfigurasinya untuk mendeteksi format tersebut.

Misalnya, untuk mendeteksi kode Aztec dan kode QR saja, buat objek VisionBarcodeDetectorOptions seperti pada contoh berikut:

Swift

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

Format berikut didukung:

  • Kode 128
  • Kode 39
  • Kode 93
  • CodaBar
  • EAN13
  • EAN8
  • ITF
  • UPCA
  • UPCE
  • Kode QR
  • PDF417
  • Aztec
  • Matriks Data

Objective-C

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

Format berikut didukung:

  • Kode 128 (FIRVisionBarcodeFormatCode128)
  • Kode 39 (FIRVisionBarcodeFormatCode39)
  • Kode 93 (FIRVisionBarcodeFormatCode93)
  • Codabar (FIRVisionBarcodeFormatCodaBar)
  • EAN-13 (FIRVisionBarcodeFormatEAN13)
  • EAN-8 (FIRVisionBarcodeFormatEAN8)
  • ITF (FIRVisionBarcodeFormatITF)
  • UPC-A (FIRVisionBarcodeFormatUPCA)
  • UPC-E (FIRVisionBarcodeFormatUPCE)
  • Kode QR (FIRVisionBarcodeFormatQRCode)
  • PDF417 (FIRVisionBarcodeFormatPDF417)
  • Aztec (FIRVisionBarcodeFormatAztec)
  • Matriks Data (FIRVisionBarcodeFormatDataMatrix)

2. Menjalankan detektor kode batang

Untuk memindai kode batang dalam gambar, teruskan gambar tersebut sebagai UIImage atau CMSampleBufferRef ke metode detect(in:) VisionBarcodeDetector:

  1. Dapatkan instance 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];
    
  2. Buat objek VisionImage menggunakan UIImage atau CMSampleBufferRef.

    Untuk menggunakan UIImage:

    1. Jika perlu, putar gambar sehingga properti imageOrientation-nya adalah .up.
    2. Buat objek VisionImage menggunakan UIImage yang diputar dengan benar. Jangan tentukan metadata rotasi apa pun—nilai default, .topLeft, harus digunakan.

      Swift

      let image = VisionImage(image: uiImage)

      Objective-C

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

    Untuk menggunakan CMSampleBufferRef:

    1. Buat objek VisionImageMetadata yang menentukan orientasi data gambar yang terdapat dalam buffer CMSampleBufferRef.

      Untuk mendapatkan orientasi gambar:

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

      Kemudian, buat objek metadata:

      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];
    2. Buat objek VisionImage menggunakan objek CMSampleBufferRef dan metadata rotasi:

      Swift

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

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Lalu, teruskan gambar ke metode 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. Mendapatkan informasi dari kode batang

Jika operasi pengenalan kode batang berhasil, detektor akan menampilkan array objek VisionBarcode. Setiap objek VisionBarcode 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 detektor kode batang dapat menentukan jenis data yang dienkode oleh kode batang, Anda bisa mendapatkan objek yang berisi data yang telah terurai.

Misalnya:

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

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 menghasilkan gambar yang sangat besar (10+ megapiksel). Ini akan menyebabkan latensi yang sangat buruk tanpa meningkatkan akurasi. Sebagai gantinya, hanya minta ukuran dari kamera yang diperlukan untuk deteksi kode batang: biasanya tidak lebih dari 2 megapiksel.

    Preset sesi pengambilan bernama (AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium, dan sebagainya) tidak disarankan, karena dapat memetakan 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 minimum yang diuraikan di atas.

  • Batasi panggilan ke detektor. Jika bingkai video baru tersedia saat detektor sedang berjalan, hapus bingkai tersebut.
  • 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. Lihat class previewOverlayView dan FIRDetectionOverlayView dalam aplikasi sampel showcase sebagai contoh.

Langkah berikutnya

Lihat aplikasi showcase Desain Material ML Kit dan sampel panduan memulai ML Kit di GitHub untuk mengetahui contoh penggunaan API ini.