Mendeteksi dan melacak objek dengan ML Kit di iOS

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

Saat Anda meneruskan gambar ke ML Kit, ML Kit akan mendeteksi hingga lima objek dalam gambar beserta posisi setiap objek dalam gambar. Saat mendeteksi objek dalam streaming video, setiap objek memiliki ID unik yang dapat digunakan untuk melacak objek dari frame ke frame. Anda juga dapat mengaktifkan klasifikasi objek mentah secara opsional, yang memberi label objek dengan deskripsi kategori yang luas.

Cobalah

Sebelum memulai

  1. Sertakan pod ML Kit berikut di Podfile Anda:
    pod 'GoogleMLKit/ObjectDetection', '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.

1. Mengonfigurasi detektor objek

Untuk mendeteksi dan melacak objek, pertama-tama buat instance ObjectDetector dan tentukan setelan detektor yang ingin Anda ubah dari setelan default terlebih dahulu.

  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 membuahkan 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 di seluruh frame. Gunakan mode ini saat Anda ingin melacak objek, atau ketika latensi rendah lebih diutamakan, seperti saat memproses streaming video secara real time.

    Dalam mode gambar tunggal, detektor objek menampilkan hasilnya setelah kotak pembatas objek ditentukan. Jika Anda juga mengaktifkan klasifikasi, hasil akan ditampilkan 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 mendapatkan hasil parsial.

    Mendeteksi dan melacak beberapa objek false (default) | true

    Mendeteksi dan melacak hingga lima objek atau hanya objek yang paling terlihat (default).

    Mengklasifikasikan objek false (default) | true

    Apakah akan mengklasifikasikan objek yang terdeteksi ke dalam kategori kasar atau tidak. Jika diaktifkan, detektor objek akan mengklasifikasikan objek ke dalam kategori berikut: barang mode, makanan, perlengkapan rumah, tempat, dan tanaman.

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

    • Deteksi langsung dan pelacakan objek paling terlihat di jendela bidik kamera.
    • Deteksi banyak objek dalam gambar statis.

    Untuk mengonfigurasi API untuk 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. Siapkan 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 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. Memproses gambar

Teruskan VisionImage ke salah satu metode pemrosesan gambar detektor objek. Anda dapat menggunakan metode process(image:) 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 pemroses gambar berhasil, panggilan tersebut akan meneruskan daftar Object ke pengendali penyelesaian atau menampilkan daftar, bergantung pada apakah Anda memanggil metode asinkron atau sinkron.

Setiap Object berisi properti berikut:

frame CGRect yang menunjukkan posisi objek dalam gambar.
trackingID Bilangan bulat yang mengidentifikasi objek di seluruh gambar, atau `nil` dalam mode gambar tunggal.
labels Kumpulan label yang menjelaskan objek yang ditampilkan oleh detektor. Properti ini kosong jika opsi detektor 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 pengalaman pengguna terbaik, ikuti panduan berikut di aplikasi Anda:

  • Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Agar dapat dideteksi, objek dengan sejumlah kecil fitur visual mungkin perlu mengambil bagian yang lebih besar dari gambar. Anda harus memberikan panduan kepada pengguna tentang cara menangkap input yang berfungsi baik dengan jenis objek yang ingin dideteksi.
  • Saat menggunakan klasifikasi, jika Anda ingin mendeteksi objek yang tidak secara mudah 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 Anda menggunakan mode streaming dalam aplikasi real-time, ikuti panduan ini untuk mencapai kecepatan frame terbaik:

  • Jangan gunakan deteksi banyak objek dalam mode streaming, karena sebagian besar perangkat tidak akan dapat menghasilkan frekuensi gambar 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 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.