Mendeteksi dan melacak objek dengan ML Kit di iOS

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Anda dapat menggunakan ML Kit untuk mendeteksi dan melacak objek dalam frame video berturut-turut.

Saat Anda meneruskan gambar ke ML Kit, fitur ini akan mendeteksi hingga lima objek dalam gambar bersama dengan posisi setiap objek dalam gambar. Saat mendeteksi objek dalam streaming video, setiap objek memiliki ID unik yang dapat Anda gunakan untuk melacak objek dari frame ke frame. Anda juga dapat mengaktifkan klasifikasi objek mentah secara opsional, yang menandai objek dengan deskripsi umum kategori.

Sebelum memulai

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

1. Mengonfigurasi detektor objek

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

  1. Konfigurasikan detektor objek untuk kasus penggunaan Anda dengan objek ObjectDetectorOptions. 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 menampilkan hasil setelah kotak pembatas objek ditentukan. Jika Anda juga mengaktifkan klasifikasi, klasifikasi tersebut akan menampilkan hasil setelah kotak pembatas dan label kategori tersedia. 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 menggunakan 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, dan tanaman.

    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 = ObjectDetectorOptions()
options.shouldEnableClassification = true

// Multiple object detection in static images
let options = ObjectDetectorOptions()
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true

Objective-C

// Live detection and tracking
MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init];
options.shouldEnableClassification = YES;

// Multiple object detection in static images
MLKObjectDetectorOptions *options = [[MLKOptions alloc] init];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
  1. Dapatkan instance ObjectDetector:

Swift

let objectDetector = ObjectDetector.objectDetector()

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

Objective-C

MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector];

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

2. Menyiapkan gambar input

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

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

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) { objects, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !objects.isEmpty else {
    // No objects detected.
    return
  }

  // Success. Get object info here.
  // ...
}

Objective-C

[objectDetector processImage:image
                  completion:^(NSArray * _Nullable objects,
                               NSError * _Nullable error) {
                    if (error == nil) {
                      return;
                    }
                    if (objects.count == 0) {
                      // No objects detected.
                      return;
                    }

                    // Success. Get object info here.
                  }];

Untuk mendeteksi objek secara sinkron:

Swift

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

// Success. Get object info here.

Objective-C

NSError *error;
NSArray *objects = [objectDetector resultsInImage:image error:&error];
if (error == nil) {
  return;
}
if (objects.count == 0) {
  // No objects detected.
  return;
}

// Success. Get object info here.

4. Mendapatkan informasi tentang objek yang terdeteksi

Jika panggilan ke prosesor gambar berhasil, panggilan tersebut akan meneruskan daftar Object ke pengendali penyelesaian atau menampilkan daftar, bergantung pada metode yang digunakan, yaitu asinkron atau sinkron.

Setiap Object berisi properti berikut:

frame CGRect yang menunjukkan posisi objek dalam gambar.
trackingID Bilangan bulat yang mengidentifikasi objek lintas gambar, atau `nil` dalam mode gambar tunggal.
labels Array label yang menjelaskan objek yang ditampilkan oleh detektor. Properti kosong jika opsi pendeteksi shouldEnableClassification ditetapkan ke false.

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID

  // If classification was enabled:
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence)"
    }.joined(separator:"\n")

}

Objective-C

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu",
      label.text, label.confidence, (unsigned long)label.index];
    ...
  }
}

Meningkatkan kegunaan dan performa

Untuk mendapatkan pengalaman pengguna terbaik, ikuti panduan berikut di aplikasi Anda:

  • Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Agar terdeteksi, objek dengan sedikit fitur visual mungkin perlu mengambil sebagian besar gambar. Anda sebaiknya memberikan panduan kepada pengguna tentang menangkap input yang berfungsi baik dengan jenis objek yang ingin Anda deteksi.
  • Saat Anda 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 koleksi Pola Desain Material untuk fitur yang didukung machine learning.

Saat menggunakan mode streaming dalam aplikasi real-time, ikuti pedoman ini untuk mencapai frekuensi 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.
  • 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 tertentu secara sinkron. Simpan alwaysDiscardsLateVideoFrames AVCaptureVideoDataOutput sebagai true untuk membatasi panggilan ke detektor. Jika frame video baru tersedia saat detektor sedang berjalan, frame akan dihapus.
  • Jika menggunakan output detektor untuk menempatkan grafis pada gambar input, pertama-tama dapatkan hasil 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 contoh panduan memulai ML Kit untuk mengetahui contohnya.