Mendeteksi dan melacak objek dengan ML Kit di iOS

Anda dapat menggunakan ML Kit untuk mendeteksi dan melacak objek dalam frame video berurutan.

Saat Anda meneruskan gambar ke ML Kit, ML Kit akan mendeteksi hingga lima objek dalam gambar beserta posisi setiap objek dalam gambar. Ketika mendeteksi objek dalam streaming video. Setiap objek memiliki ID unik yang dapat Anda gunakan untuk melacak objek dari satu {i>frame<i} ke {i>frame<i}. Anda juga bisa mengaktifkan objek kasar klasifikasi, yang melabeli 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 Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan .xcworkspace. 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 secara opsional menentukan setelan pendeteksi yang ingin Anda ubah dari {i>default<i}.

  1. Konfigurasikan detektor objek untuk kasus penggunaan Anda dengan Objek ObjectDetectorOptions. Anda dapat mengubah pengaturan:

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

    Dalam mode streaming (default), detektor objek berjalan dengan latensi yang tinggi, tetapi mungkin memberikan hasil yang tidak lengkap (seperti permintaan kotak pembatas atau kategori) pada beberapa pemanggilan pertama dari detektor. Selain itu, pada mode streaming, detektor menetapkan pelacakan ID ke objek, yang dapat Anda gunakan untuk melacak objek lintas bingkai. Gunakan mode ini saat Anda ingin melacak objek, atau saat latensi rendah adalah hal penting, seperti saat memproses streaming video secara nyata baik.

    Dalam mode gambar tunggal, detektor objek menampilkan hasil setelah kotak pembatas objek ditentukan. Jika Anda juga mengaktifkan klasifikasi itu akan mengembalikan hasil setelah kotak pembatas dan kategori, keduanya tersedia. Akibatnya, deteksi latensinya berpotensi lebih tinggi. Selain itu, dalam mode gambar tunggal, pelacakan ID tidak ditetapkan. Gunakan mode ini jika latensi tidak diutamakan dan Anda tidak ingin berurusan dengan hasil parsial.

    Mendeteksi dan melacak beberapa objek false (default) | true

    Apakah akan mendeteksi dan melacak hingga lima objek atau hanya yang paling yang menonjol (default).

    Mengklasifikasikan objek false (default) | true

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

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

    • Deteksi langsung dan pelacakan objek paling terlihat di kamera jendela bidik.
    • Deteksi beberapa 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 dtk.

Buat objek VisionImage menggunakan UIImage atau objek 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 pemrosesan gambar detektor objek metode. Anda dapat menggunakan metode process(image:) asinkron atau results() 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 baik Anda memanggil metode asinkron atau sinkron.

Setiap Object berisi properti berikut:

frame CGRect yang menunjukkan posisi objek di gambar.
trackingID Bilangan bulat yang mengidentifikasi objek di seluruh gambar, atau `nil` dalam mode gambar tunggal.
labels Array label yang menjelaskan objek yang ditampilkan oleh detektor. Properti kosong jika opsi pendeteksi shouldEnableClassification disetel 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 ini di aplikasi Anda:

  • Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Di beberapa untuk dideteksi, objek dengan sedikit fitur visual mungkin memerlukan untuk mengambil bagian yang lebih besar dari gambar. Anda harus memberikan panduan kepada pengguna tentang menangkap input yang bekerja dengan baik dengan jenis objek yang ingin Anda deteksi.
  • Saat menggunakan klasifikasi, jika ingin mendeteksi objek yang tidak jatuh kategori yang didukung, terapkan penanganan khusus untuk objek terstruktur dalam jumlah besar.

Juga, lihat Desain Material Kumpulan Pola untuk fitur yang didukung machine learning.

Saat Anda menggunakan mode streaming dalam aplikasi real-time, ikuti panduan berikut untuk mencapai kecepatan frame terbaik:

  • Jangan gunakan deteksi beberapa objek dalam mode streaming, karena sebagian besar perangkat tidak akan dapat dapat menghasilkan kecepatan frame yang memadai.
  • Nonaktifkan klasifikasi jika tidak diperlukan.
  • Untuk memproses frame video, gunakan API sinkron results(in:) dari detektor. Telepon metode ini dari class AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) untuk mendapatkan hasil dari video yang diberikan secara sinkron {i>frame<i}. Simpan AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames sebagai true untuk men-throttle panggilan ke detektor. Jika frame video tersedia saat detektor sedang berjalan, dan frame tersebut akan dihapus.
  • Jika Anda menggunakan output detektor untuk menempatkan grafik gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan overlay dalam satu langkah. Dengan demikian, Anda merender ke permukaan tampilan hanya sekali untuk setiap {i> frame<i} input yang diproses. Lihat updatePreviewOverlayViewWithLastFrame dalam contoh panduan memulai ML Kit sebagai contoh.