iOS'te ML Kiti ile pozları algılama

ML Kit, poz algılama için optimize edilmiş iki SDK sunar.

SDK AdıPoseDetectionPoseDetectionAccurate
UygulamaTemel algılayıcının öğeleri, derleme sırasında uygulamanıza statik olarak bağlıdır.Doğru algılayıcıya yönelik öğeler, derleme sırasında statik olarak uygulamanıza bağlanır.
Uygulama boyutuEn fazla 29,6 MBEn fazla 33,2 MB
PerformansiPhone X: ~45FPSiPhone X: ~29FPS

Deneyin

Başlamadan önce

  1. Aşağıdaki ML Kit kapsüllerini Podfile'ınıza ekleyin:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '3.2.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '3.2.0'
    
  2. Projenizin kapsüllerini yükledikten veya güncelledikten sonra Xcode projenizi, xcworkspace ile açın. ML Kit, Xcode 13.2.1 veya üzeri sürümlerde desteklenir.

1. PoseDetector örneği oluşturun

Bir görüntüdeki pozu algılamak için önce PoseDetector örneği oluşturun ve isteğe bağlı olarak algılayıcı ayarlarını belirtin.

PoseDetector seçeneği

Algılama Modu

PoseDetector, iki algılama modunda çalışır. Kullanım alanınıza uygun olanı seçtiğinizden emin olun.

stream (varsayılan)
Poz algılayıcısı, önce resimdeki en belirgin kişiyi algılar ve ardından poz algılamayı çalıştırır. Sonraki çerçevelerde, kişinin kimliği belirsiz olmadığı veya artık yüksek güvenilirlikle algılanmadığı sürece kişi algılama adımı gerçekleştirilmez. Poz algılayıcı, en belirgin kişiyi izlemeye ve her çıkarımda pozisyonunu geri döndürmeye çalışır. Bu, gecikmeyi azaltır ve algılama sürecini kolaylaştırır. Video akışında pozu algılamak istediğinizde bu modu kullanın.
singleImage
Poz dedektörü kişi algılayıp poz algılamayı çalıştırır. Kişi algılama adımı her resim için çalışır. Bu nedenle gecikme daha yüksek olur ve kişi izleme yapılmaz. Statik resimlerde poz algılama özelliğini kullanırken veya izlemenin istenmediği durumlarda bu modu kullanın.

Poz algılayıcı seçeneklerini belirtin:

Swift

// Base pose detector with streaming, when depending on the PoseDetection SDK
let options = PoseDetectorOptions()
options.detectorMode = .stream

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
let options = AccuratePoseDetectorOptions()
options.detectorMode = .singleImage

Objective-C

// Base pose detector with streaming, when depending on the PoseDetection SDK
MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeStream;

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
MLKAccuratePoseDetectorOptions *options =
    [[MLKAccuratePoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeSingleImage;

Son olarak, PoseDetector örneği alın. Belirttiğiniz seçenekleri iletin:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Giriş görüntüsünü hazırlama

Pozları algılamak için her bir resim veya video 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 şu 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 şu adımları uygulayın:

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

    Resmin yönünü belirlemek 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, poz algılayıcının resim işleme yöntemlerinden birine iletin. Eşzamansız process(image:) yöntemini veya eşzamanlı results() yöntemini kullanabilirsiniz.

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

Swift

var results: [Pose]
do {
  results = try poseDetector.results(in: image)
} catch let error {
  print("Failed to detect pose with error: \(error.localizedDescription).")
  return
}
guard let detectedPoses = results, !detectedPoses.isEmpty else {
  print("Pose detector returned no results.")
  return
}

// Success. Get pose landmarks here.

Objective-C

NSError *error;
NSArray *poses = [poseDetector resultsInImage:image error:&error];
if (error != nil) {
  // Error.
  return;
}
if (poses.count == 0) {
  // No pose detected.
  return;
}

// Success. Get pose landmarks here.

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

Swift

poseDetector.process(image) { detectedPoses, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !detectedPoses.isEmpty else {
    // No pose detected.
    return
  }

  // Success. Get pose landmarks here.
}

Objective-C

[poseDetector processImage:image
                completion:^(NSArray * _Nullable poses,
                             NSError * _Nullable error) {
                    if (error != nil) {
                      // Error.
                      return;
                    }
                    if (poses.count == 0) {
                      // No pose detected.
                      return;
                    }

                    // Success. Get pose landmarks here.
                  }];

4. Algılanan poz hakkında bilgi alma

Resimde bir kişi algılanırsa poz algılama API'si, eşzamansız veya eşzamanlı yöntemi çağırmanıza bağlı olarak tamamlama işleyicisine Pose nesnelerinden oluşan bir diziyi iletir ya da diziyi döndürür.

Kişi resmin içinde tam olarak yer almıyorsa model, eksik önemli nokta koordinatlarını çerçevenin dışına atar ve bunlara düşük InFrameConfidence değerleri verir.

Hiç kimse algılanmazsa dizi boş olur.

Swift

for pose in detectedPoses {
  let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle)
  if leftAnkleLandmark.inFrameLikelihood > 0.5 {
    let position = leftAnkleLandmark.position
  }
}

Objective-C

for (MLKPose *pose in detectedPoses) {
  MLKPoseLandmark *leftAnkleLandmark =
      [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle];
  if (leftAnkleLandmark.inFrameLikelihood > 0.5) {
    MLKVision3DPoint *position = leftAnkleLandmark.position;
  }
}

Performansı artırmaya yönelik ipuçları

Sonuçlarınızın kalitesi, giriş görüntüsünün kalitesine bağlıdır:

  • ML Kit'in pozu doğru bir şekilde algılayabilmesi için resimdeki kişi yeterli piksel verisiyle temsil edilmelidir. En iyi performans için ise özne en az 256x256 piksel olmalıdır.
  • Pozu gerçek zamanlı bir uygulamada tespit ederseniz giriş resimlerinin genel boyutlarını da hesaba katmak isteyebilirsiniz. Daha küçük resimler daha hızlı işlenebilir, bu nedenle gecikmeyi azaltmak için düşük çözünürlüklerde görüntü yakalayın ancak yukarıdaki çözünürlük gereksinimlerini göz önünde bulundurun ve öznenin resmi olabildiğince kapladığından emin olun.
  • Kötü resim odağı, doğruluğu da etkileyebilir. Kabul edilebilir sonuçlar alamazsanız kullanıcıdan resmi tekrar çekmesini isteyin.

Gerçek zamanlı bir uygulamada poz algılamayı kullanmak istiyorsanız en iyi kare hızlarını elde etmek için aşağıdaki yönergeleri uygulayın:

  • Temel PoseDetection SDK'sını ve stream algılama modunu kullanın.
  • Daha düşük çözünürlükte resimler çekmeyi deneyin. Ancak, bu API'nin resim boyutu koşullarını da göz önünde bulundurun.
  • Video karelerini işlemek için algılayıcının results(in:) eşzamanlı API'sini kullanın. Belirli bir video karesinden eşzamanlı olarak sonuçlar almak için AVCaptureVideoDataOutputSampleBufferDelegate öğesinin captureOutput(_, didOutput:from:) işlevinden bu yöntemi çağırın. Algılayıcıya yapılan çağrıları sınırlandırmak için AVCaptureVideoDataOutput öğesinin alwaysDiscardsLateVideoFrames öğelerini doğru tutun. 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ü ve yer paylaşımını tek bir adımda oluşturun. Böylece, işlenen her giriş çerçevesi için görüntü yüzeyinde yalnızca bir kez görüntü oluşturursunuz. Örnek için vitrin örnek uygulamasındaki previewOverlayView ve MLKDetectionOverlayView sınıflarını inceleyebilirsiniz.

Sonraki adımlar