iOS'te ML Kiti ile nesneleri algılama ve izleme

Ardışık video karelerindeki nesneleri algılayıp takip etmek için ML Kiti'ni kullanabilirsiniz.

Bir görüntüyü ML Kit'e ilettiğinizde bu cihaz, görüntüdeki her bir nesnenin konumuyla birlikte en fazla beş nesne tespit eder. Video akışlarında nesneler algılanırken her nesnenin benzersiz bir kimliği vardır. Bu kimliği, nesneyi kareden kareye izlemek için kullanabilirsiniz. İsteğe bağlı olarak, nesneleri geniş kategori açıklamalarıyla etiketleyen genel nesne sınıflandırmasını da etkinleştirebilirsiniz.

Deneyin

Başlamadan önce

  1. Aşağıdaki ML Kiti kapsüllerini Podfile'ınıza ekleyin:
    pod 'GoogleMLKit/ObjectDetection', '3.2.0'
    
  2. Projenizin Kapsüllerini yükledikten veya güncelledikten sonra Xcode projenizi, .xcworkspace ile açın. ML Kit, Xcode 12.4 veya üzeri sürümlerde desteklenir.

1. Nesne algılayıcısını yapılandırın

Nesneleri algılamak ve izlemek için önce ObjectDetector örneği oluşturun ve isteğe bağlı olarak varsayılandan değiştirmek istediğiniz algılayıcı ayarlarını belirtin.

  1. Kullanım alanınıza yönelik nesne algılayıcıyı bir ObjectDetectorOptions nesnesiyle yapılandırın. Aşağıdaki ayarları değiştirebilirsiniz:

    Nesne Algılayıcı Ayarları
    Algılama modu .stream (varsayılan) | .singleImage

    Nesne algılayıcı, akış modunda (varsayılan) çok düşük gecikmeyle çalışır ancak algılayıcının ilk birkaç çağrısında eksik sonuçlar (belirtilmemiş sınırlayıcı kutular veya kategoriler gibi) üretebilir. Ayrıca algılayıcı, akış modunda nesnelere izleme kimlikleri atar. Bu kimlikleri kareler genelinde nesneleri izlemek için kullanabilirsiniz. Nesneleri izlemek istediğinizde veya düşük gecikmenin önemli olduğu durumlarda (ör. video akışlarını gerçek zamanlı olarak işlerken) bu modu kullanın.

    Tekli görüntü modunda nesne algılayıcı, nesnenin sınırlayıcı kutusu belirlendikten sonra sonucu döndürür. Sınıflandırmayı da etkinleştirirseniz sonucu, sınırlayıcı kutu ve kategori etiketi kullanılabilir hale geldikten sonra döndürür. Sonuç olarak, algılama gecikmesi potansiyel olarak daha yüksek olur. Ayrıca, tekli resim modunda izleme kimlikleri atanmaz. Gecikme kritik değilse ve kısmi sonuçlarla uğraşmak istemiyorsanız bu modu kullanın.

    Birden fazla nesneyi algılama ve izleme false (varsayılan) | true

    En fazla beş nesnenin mı yoksa yalnızca en belirgin nesnenin mı (varsayılan) algılanacağını ve izleneceğini belirtir.

    Nesneleri sınıflandırma false (varsayılan) | true

    Algılanan nesnelerin yaklaşık kategorilere ayrılıp sınıflandırılmayacağını belirtir. Nesne algılayıcı etkinleştirildiğinde nesneleri şu kategorilere ayırır: moda ürünleri, yiyecekler, ev eşyaları, yerler ve bitkiler.

    Nesne algılama ve izleme API'si aşağıdaki iki temel kullanım alanı için optimize edilmiştir:

    • Kamera vizöründeki en belirgin nesnenin canlı olarak algılanması ve izlenmesi.
    • Statik bir görüntüde birden fazla nesnenin algılanması.

    API'yi bu kullanım alanlarına göre yapılandırmak için:

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. ObjectDetector örneği alın:

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. Giriş görüntüsünü hazırlama

Nesneleri algılamak ve izlemek için her bir video görüntüsü veya karesinde aşağıdakileri yapın. Akış modunu etkinleştirdiyseniz CMSampleBuffer kaynağından VisionImage nesne oluşturmanız gerekir.

UIImage veya CMSampleBuffer kullanarak VisionImage nesnesi oluşturun.

UIImage kullanıyorsanız aşağıdaki adımları uygulayın:

  • UIImage ile bir VisionImage nesnesi oluşturun. Doğru .orientation değerini belirttiğinizden emin olun.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

CMSampleBuffer kullanıyorsanız aşağıdaki adımları uygulayın:

  • CMSampleBuffer içinde yer alan resim verilerinin yönünü belirtin.

    Resmin yönünü öğrenmek için:

    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;
      }
    }
          
  • CMSampleBuffer nesnesini ve yönünü kullanarak bir VisionImage nesnesi oluşturun:

    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. Resmi işle

VisionImage öğesini, nesne dedektörünün görüntü işleme yöntemlerinden birine geçirin. Eşzamansız process(image:) yöntemini veya eşzamanlı results() yöntemini kullanabilirsiniz.

Nesneleri eşzamansız olarak algılamak için:

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

Nesneleri eşzamanlı olarak algılamak için:

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. Algılanan nesneler hakkında bilgi alma

Görüntü işlemciye yapılan çağrı başarılı olursa tamamlama işleyicisine bir Object listesi iletir ya da eşzamansız veya eşzamanlı yöntemi çağırdığınıza bağlı olarak listeyi döndürür.

Her Object aşağıdaki özellikleri içerir:

frame Resimdeki nesnenin konumunu belirten bir CGRect.
trackingID Nesneyi görüntülerde tanımlayan bir tam sayı veya tek resim modunda "nil" değeri.
labels Algılayıcı tarafından döndürülen nesneyi açıklayan bir etiket dizisi. shouldEnableClassification algılayıcı seçeneği false olarak ayarlandıysa özellik boş olur.

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

Kullanılabilirliği ve performansı iyileştirme

En iyi kullanıcı deneyimi için uygulamanızda aşağıdaki yönergeleri uygulayın:

  • Nesnenin başarılı bir şekilde algılanması, nesnenin görsel karmaşıklığına bağlıdır. Az sayıda görsel özelliğe sahip nesnelerin algılanmaları için resmin daha büyük bir bölümünü kaplamaları gerekebilir. Kullanıcılara, algılamak istediğiniz nesne türlerinde iyi çalışan girdileri yakalama konusunda yol göstermeniz gerekir.
  • Sınıflandırma kullanırken, desteklenen kategorilere düzgün bir şekilde girmeyen nesneleri algılamak isterseniz bilinmeyen nesneler için özel işlem uygulayın.

Ayrıca, Materyal Tasarım Makine öğrenimi destekli özellikler için kalıplar koleksiyonuna da göz atın.

Gerçek zamanlı bir uygulamada yayın modunu kullandığınızda en iyi kare hızlarına ulaşmak için aşağıdaki yönergeleri uygulayın:

  • Çoğu cihaz yeterli kare hızı üretemeyeceğinden akış modunda birden fazla nesne algılama özelliğini kullanmayın.
  • İhtiyacınız yoksa sınıflandırmayı devre dışı bırakın.
  • Video karelerini işlemek için algılayıcının results(in:) eşzamanlı API'sini kullanın. Belirtilen video karesinden sonuçları eşzamanlı olarak almak için bu yöntemi AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) işlevinden çağırın. Çağrıları algılayıcıya kısıtlamak için AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames özelliğini true olarak bırakın. Algılayıcı çalışırken yeni bir video karesi kullanılabilir hale gelirse atlanır.
  • Algılayıcının çıkışını giriş görüntüsünün üzerine grafik yerleştirmek için kullanırsanız önce sonucu ML Kit'ten alın, ardından görüntüyü tek bir adımda oluşturun ve yer paylaşımlı yapın. Bu şekilde, işlenen her giriş çerçevesi için görüntü yüzeyinde yalnızca bir kez görüntü oluşturursunuz. Örneği görmek için ML Kit hızlı başlangıç örneğindeki updatePreviewOverlayViewWithLastFrame) örneğine bakın.