Mendeteksi dan Melacak Objek dengan ML Kit di iOS

Anda dapat menggunakan ML Kit untuk mendeteksi dan melacak objek di seluruh bingkai video.

Ketika Anda meneruskan gambar ke ML Kit, ML Kit akan menampilkan daftar hingga 5 objek yang terdeteksi untuk setiap gambar dan posisinya dalam gambar tersebut. Saat mendeteksi objek dalam streaming video, setiap objek memiliki ID yang dapat Anda gunakan untuk melacak objek di seluruh gambar. Anda juga dapat mengaktifkan klasifikasi objek mentah secara opsional, yang menandai objek dengan deskripsi umum kategori.

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', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    Setelah 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;

1. Mengonfigurasi detektor objek

Untuk mulai mendeteksi dan melacak objek, pertama-tama buat instance VisionObjectDetector, yang secara opsional menentukan setelan detektor yang ingin diubah dari setelan default.

  1. Konfigurasi detektor objek untuk kasus penggunaan Anda dengan objek VisionObjectDetectorOptions. Anda dapat mengubah setelan berikut:

    Setelan Detektor Objek
    Mode deteksi .stream (default) | .singleImage

    Pada mode streaming (default), detektor objek berjalan dengan latensi yang sangat rendah, tetapi dapat membuat hasil yang tidak lengkap (seperti kotak pembatas atau kategori yang belum ditetapkan) pada beberapa pemanggilan pertama detektor. Selain itu, pada mode streaming, detektor menetapkan ID pelacakan ke objek, yang dapat Anda gunakan untuk melacak objek lintas frame. Gunakan mode ini saat Anda ingin melacak objek, atau ketika latensi rendah lebih diutamakan, seperti saat memproses streaming video secara real time.

    Pada mode gambar tunggal, detektor objek menunggu hingga kotak pembatas objek yang terdeteksi dan kategori (jika Anda mengaktifkan klasifikasi) tersedia sebelum menampilkan hasil. Akibatnya, latensi deteksi berpotensi lebih tinggi. Selain itu, pada mode gambar tunggal, ID pelacakan tidak ditetapkan. Gunakan mode ini jika latensi tidak diutamakan dan Anda tidak ingin mendapatkan hasil parsial.

    Mendeteksi dan melacak beberapa objek false (default) | true

    Mendeteksi dan melacak hingga 5 objek atau hanya objek yang paling tampil beda (default).

    Mengklasifikasikan objek false (default) | true

    Mengklasifikasikan objek yang terdeteksi ke dalam kategori mentah atau tidak. Jika diaktifkan, detektor objek akan mengklasifikasikan objek ke dalam kategori berikut: benda mode, makanan, peralatan rumah tangga, tempat, tanaman, dan hal yang tidak diketahui.

    API deteksi dan pelacakan objek dioptimalkan untuk dua kasus penggunaan inti berikut ini:

    • Deteksi langsung dan pelacakan objek paling tampil beda di jendela bidik kamera
    • Deteksi banyak objek dalam gambar statis

    Untuk mengonfigurasi API bagi kasus penggunaan ini:

    Swift

    // Live detection and tracking
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .stream
    options.shouldEnableMultipleObjects = false
    options.shouldEnableClassification = true  // Optional
    
    // Multiple object detection in static images
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .singleImage
    options.shouldEnableMultipleObjects = true
    options.shouldEnableClassification = true  // Optional
    

    Objective-C

    // Live detection and tracking
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeStream;
    options.shouldEnableMultipleObjects = NO;
    options.shouldEnableClassification = YES;  // Optional
    
    // Multiple object detection in static images
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeSingleImage;
    options.shouldEnableMultipleObjects = YES;
    options.shouldEnableClassification = YES;  // Optional
    
  2. Dapatkan instance FirebaseVisionObjectDetector:

    Swift

    let objectDetector = Vision.vision().objectDetector()
    
    // Or, to change the default settings:
    let objectDetector = Vision.vision().objectDetector(options: options)
    

    Objective-C

    FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector];
    
    // Or, to change the default settings:
    FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
    

2. Menjalankan detektor objek

Untuk mendeteksi dan melacak objek, lakukan hal berikut untuk setiap gambar atau frame video. Jika mengaktifkan mode streaming, Anda harus membuat objek VisionImage dari CMSampleBufferRef.

  1. 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 sudah diputar dengan benar. Jangan tentukan metadata rotasi apa pun—yang harus digunakan adalah nilai default, yaitu .topLeft.

      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 buffering 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;
  2. Teruskan VisionImage ke salah satu metode pemrosesan gambar pada detektor objek. Anda dapat menggunakan metode process(image:) yang asinkron atau metode results() yang sinkron.

    Untuk mendeteksi objek secara asinkron:

    Swift

    objectDetector.process(image) { detectedObjects, error in
      guard error == nil else {
        // Error.
        return
      }
      guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else {
        // No objects detected.
        return
      }
    
      // Success. Get object info here.
      // ...
    }
    

    Objective-C

    [objectDetector processImage:image
                      completion:^(NSArray<FIRVisionObject *> * _Nullable objects,
                                   NSError * _Nullable error) {
                        if (error == nil) {
                          return;
                        }
                        if (objects == nil | objects.count == 0) {
                          // No objects detected.
                          return;
                        }
    
                        // Success. Get object info here.
                        // ...
                      }];
    

    Untuk mendeteksi objek secara sinkron:

    Swift

    var results: [VisionObject]? = nil
    do {
      results = try objectDetector.results(in: image)
    } catch let error {
      print("Failed to detect object with error: \(error.localizedDescription).")
      return
    }
    guard let detectedObjects = results, !detectedObjects.isEmpty else {
      print("Object detector returned no results.")
      return
    }
    
    // ...
    

    Objective-C

    NSError *error;
    NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image
                                                                   error:&error];
    if (error == nil) {
      return;
    }
    if (objects == nil | objects.count == 0) {
      // No objects detected.
      return;
    }
    
    // Success. Get object info here.
    // ...
    
  3. Jika panggilan ke prosesor gambar berhasil, panggilan tersebut akan meneruskan daftar VisionObject ke pengendali penyelesaian atau menampilkan daftar, bergantung pada metode yang digunakan, yaitu asinkron atau sinkron.

    Setiap VisionObject berisi properti berikut:

    frame CGRect yang menunjukkan posisi objek dalam gambar.
    trackingID Bilangan bulat yang mengidentifikasi objek lintas gambar. Bernilai nol dalam mode gambar tunggal.
    classificationCategory Kategori mentah suatu objek. Jika detektor objek belum mengaktifkan klasifikasi, nilainya selalu .unknown.
    confidence Tingkat keyakinan klasifikasi objek. Jika detektor objek belum mengaktifkan klasifikasi, atau objek diklasifikasikan sebagai tidak diketahui, tingkatnya adalah nil.

    Swift

    // detectedObjects contains one item if multiple object detection wasn't enabled.
    for obj in detectedObjects {
      let bounds = obj.frame
      let id = obj.trackingID
    
      // If classification was enabled:
      let category = obj.classificationCategory
      let confidence = obj.confidence
    }
    

    Objective-C

    // The list of detected objects contains one item if multiple
    // object detection wasn't enabled.
    for (FIRVisionObject *obj in objects) {
      CGRect bounds = obj.frame;
      if (obj.trackingID) {
        NSInteger id = obj.trackingID.integerValue;
      }
    
      // If classification was enabled:
      FIRVisionObjectCategory category = obj.classificationCategory;
      float confidence = obj.confidence.floatValue;
    }
    

Meningkatkan kegunaan dan performa

Untuk mendapatkan pengalaman pengguna terbaik, ikuti pedoman ini dalam aplikasi:

  • Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Objek yang memiliki sedikit fitur visual mungkin perlu menempati bagian yang lebih besar pada gambar agar terdeteksi. Anda sebaiknya memberikan panduan kepada pengguna tentang pengambilan input yang tepat bagi jenis objek yang ingin Anda deteksi.
  • Saat menggunakan klasifikasi, jika ingin mendeteksi objek yang tidak secara jelas termasuk dalam kategori yang didukung, terapkan penanganan khusus untuk objek yang tidak diketahui.

Selain itu, lihat [aplikasi contoh Desain Material ML Kit][showcase-link]{: .external} dan koleksi Pola Desain Material untuk fitur yang didukung machine learning.

Saat menggunakan mode streaming dalam aplikasi real-time, ikuti pedoman ini untuk mencapai kecepatan frame terbaik:

  • Jangan gunakan deteksi banyak objek dalam mode streaming, karena sebagian besar perangkat tidak akan dapat menghasilkan frekuensi frame yang memadai.

  • Nonaktifkan klasifikasi jika tidak diperlukan.

  • Batasi panggilan ke detektor. Jika frame video baru tersedia saat detektor sedang berjalan, hapus frame 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 contoh showcase untuk mengetahui contohnya.