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ı için kullanılan öğeler, derleme sırasında uygulamanıza statik olarak bağlıdır.
Uygulama boyutuEn fazla 29,6 MBEn fazla 33,2 MB
PerformansiPhone X: ~45FPSiPhone X: Yaklaşık 29 FPS

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 xcworkspace öğesini kullanarak Xcode projenizi açın. Makine Öğrenimi Kiti, Xcode 13.2.1 veya üzeri sürümlerde desteklenir.

1. PoseDetector örneği oluşturun

Bir resimdeki 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çenek

Algılama Modu

PoseDetector, iki algılama modunda çalışır. Eşleşen etiketi seçtiğinizden emin olun en iyi uygulamaları görelim.

stream (varsayılan)
Poz dedektörü öncelikle en yüksek değeri algılar ve ardından poz algılamayı çalıştırmalısınız. Sonraki karelerde kullanıcı algılama adımını, artık yüksek güvenilirlikle algılanmaz. Poz algılayıcı, en belirgin kişiyi takip etmeye çalışmak ve her oturumda çıkarım. Bu, gecikmeyi azaltır ve algılamayı sorunsuz hale getirir. Bu modu şu durumlarda kullanın: video akışı sırasında pozu algılamak isteyen kullanıcılar yararlanabilir.
singleImage
Poz dedektörü birini algılayıp poz verir tespit edebilir. Kişi algılama adımı her görüntü için uygulanır. Bu nedenle gecikme daha yüksek olduğunu fark edeceksiniz. Poz kullanırken bu modu kullan statik resimlerde veya izlemenin istenmediği yerlerde

Poz algılayıcısı 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 öğesinin bir örneğini alın. Belirttiğiniz seçenekleri iletin:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Giriş resmini hazırlama

Pozları algılamak için her resim veya video karesinde aşağıdakileri yapın. Akış modunu etkinleştirdiyseniz şuradan VisionImage nesne oluşturmanız gerekir: CMSampleBuffer sn.

Bir VisionImage nesnesi oluşturmak için UIImage veya CMSampleBuffer.

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:

  • Belgenin CMSampleBuffer

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

    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şleyin

VisionImage öğesini, poz algılayıcının görüntü 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

Görüntüde bir kişi algılanırsa poz algılama API'si tamamlama işleyiciye Pose nesne dizisi veya diziyi döndürür, eşzamansız yöntemi mi yoksa eşzamanlı yöntemi mi çağırdığınıza bağlı olarak değişir.

Kişi resmin içinde tamamen yoksa model, eksik yer işaretlerinin çerçevenin dışında kalan koordinatlarını verir ve bunları, InFrameConfidence değerlerine ait değerler.

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ş resminin kalitesine bağlıdır:

  • Makine Öğrenimi Kiti'nin duruşu doğru şekilde algılayabilmesi için resimdeki kişinin yeterli piksel verisiyle temsil edilir; en iyi performansa ulaşmak için en az 256x256 piksel olmalıdır.
  • Pozu gerçek zamanlı bir uygulamada tespit ederseniz, giriş resimlerinin genel boyutları. Daha küçük resimler işlenebilir. daha hızlıdır. Bu nedenle, gecikmeyi azaltmak için görüntüleri daha düşük çözünürlükte çekin. yukarıdaki çözüm gereksinimlerine dikkat edin ve büyük bir kısmını kaplayacak şekilde yerleştirin.
  • Kötü bir resim odağı, doğruluğu da etkileyebilir. Kabul edilebilir sonuçlar elde etmezseniz kullanıcıdan görüntüyü yeniden çekmesini isteyin.

Poz algılamayı gerçek zamanlı bir uygulamada kullanmak istiyorsanız en iyi kare hızlarına ulaşmak için şu yönergeleri uygulayın:

  • Temel PoseDetection SDK'sını ve stream algılama modunu kullanın.
  • Görüntüleri daha düşük çözünürlükte çekmeyi düşünün. Ancak bu API'nin resim boyutu şartları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. Bu yöntemi AVCaptureVideoDataOutputSampleBufferDelegate'in Belirli bir video karesinden eşzamanlı olarak sonuç almak için captureOutput(_, didOutput:from:) fonksiyonunu kullanabilirsiniz. Algılayıcıya yapılan çağrıları kısmak için AVCaptureVideoDataOutput özelliğinin alwaysDiscardsLateVideoFrames değerini doğru olarak bırakın. Algılayıcı çalışırken yeni bir video karesi kullanılabilir hale gelirse bu kare atlanır.
  • Dedektörün çıkışını giriş görüntüsüne grafik yerleştirmek için kullanıyorsanız önce ML Kit'ten sonucu alın, ardından tek bir adımda görüntüyü oluşturun ve bindirme kullanın. Böylece, işlenen her giriş karesi için görüntü yüzeyinde yalnızca bir kez oluşturma yaparsınız. Bkz. previewOverlayView ve MLKDetectionOverlayView sınıfları inceleyelim.

Sonraki adımlar