Mendeteksi pose dengan ML Kit di iOS

ML Kit menyediakan dua SDK yang dioptimalkan untuk deteksi pose.

Nama SDKPoseDetectionPoseDetectionAccurate
PenerapanAset untuk detektor dasar ditautkan secara statis ke aplikasi Anda pada waktu build.Aset untuk detektor yang akurat ditautkan secara statis ke aplikasi Anda pada waktu build.
Ukuran aplikasiHingga 29,6 MBHingga 33,2 MB
PerformaiPhone X: ~45FPSiPhone X: ~29FPS

Cobalah

Sebelum memulai

  1. Sertakan pod ML Kit berikut di Podfile Anda:

    # 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. Setelah Anda menginstal atau mengupdate pod project, buka project Xcode menggunakan xcworkspace-nya. ML Kit didukung dalam Xcode versi 13.2.1 atau yang lebih tinggi.

1. Membuat instance PoseDetector

Untuk mendeteksi pose dalam gambar, pertama-tama buat instance PoseDetector dan secara opsional, menentukan setelan pendeteksi.

Opsi PoseDetector

Mode Deteksi

PoseDetector beroperasi dalam dua mode deteksi. Pastikan Anda memilih salah satu yang cocok kasus penggunaan Anda.

stream (default)
Detektor pose akan mendeteksi paling banyak orang yang menonjol dalam gambar, lalu menjalankan deteksi pose. Dalam {i>frame<i} berikutnya, langkah deteksi orang tidak akan dilakukan kecuali orang tersebut menjadi dikaburkan atau tidak lagi terdeteksi dengan tingkat keyakinan tinggi. Pendeteksi pose akan cobalah untuk melacak orang yang paling menonjol dan menampilkan pose mereka di masing-masing inferensi. Tindakan ini akan mengurangi latensi dan memperlancar deteksi. Gunakan mode ini saat Anda ingin mendeteksi pose dalam streaming video.
singleImage
Detektor pose akan mendeteksi seseorang, lalu menjalankan pose deteksi. Langkah deteksi orang akan dijalankan untuk setiap gambar, sehingga latensi akan menjadi lebih tinggi, dan tidak ada pelacakan orang. Gunakan mode ini saat menggunakan pose pada gambar statis atau jika pelacakan tidak diinginkan.

Tentukan opsi detektor pose:

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;

Terakhir, dapatkan instance PoseDetector. Teruskan opsi yang Anda tentukan:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Menyiapkan gambar input

Untuk mendeteksi pose, lakukan hal berikut untuk setiap gambar atau bingkai 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 metode pemrosesan gambar pada detektor pose. Anda dapat menggunakan metode process(image:) asinkron atau metode results() sinkron.

Untuk mendeteksi objek secara sinkron:

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.

Untuk mendeteksi objek secara asinkron:

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. Mendapatkan informasi tentang pose yang terdeteksi

Jika seseorang terdeteksi dalam gambar, API deteksi pose akan meneruskan array objek Pose ke pengendali penyelesaian atau menampilkan array, tergantung pada apakah Anda memanggil metode asinkron atau sinkron.

Jika orang tersebut tidak sepenuhnya ada dalam gambar, model akan menetapkan koordinat {i>landmark<i} yang hilang di luar {i>frame<i} dan memberinya nilai rendah InFrameConfidence.

Jika tidak ada orang yang terdeteksi, array akan kosong.

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

Tips untuk meningkatkan performa

Kualitas hasil bergantung pada kualitas gambar input:

  • Agar ML Kit dapat mendeteksi pose secara akurat, orang dalam gambar harus diwakili oleh data piksel yang memadai; untuk performa terbaik, subjek harus berukuran minimal 256x256 piksel.
  • Jika Anda mendeteksi pose dalam aplikasi {i>real-time<i}, Anda mungkin juga ingin mempertimbangkan dimensi keseluruhan gambar input. Gambar yang lebih kecil dapat diproses lebih cepat, jadi untuk mengurangi latensi, ambil gambar pada resolusi lebih rendah, tetapi tetap mengingat persyaratan resolusi di atas dan pastikan bahwa subjek menempati sebanyak mungkin gambar.
  • Fokus gambar yang buruk juga dapat memengaruhi akurasi. Jika Anda tidak mendapatkan hasil yang dapat diterima, meminta pengguna untuk mengambil ulang gambar.

Jika Anda ingin menggunakan deteksi pose dalam aplikasi real-time, ikuti panduan ini untuk mencapai kecepatan frame terbaik:

  • Gunakan SDK Posedetection dasar dan mode deteksi stream.
  • Sebaiknya ambil gambar dengan resolusi yang lebih rendah. Namun, perhatikan juga persyaratan dimensi gambar API ini.
  • Untuk memproses frame video, gunakan API sinkron results(in:) dari detektor. Panggil metode ini dari objek AVCaptureVideoDataOutputSampleBufferDelegate fungsi captureOutput(_, didOutput:from:) untuk mendapatkan hasil secara sinkron dari frame video yang diberikan. Pertahankan setelan alwaysDiscardsLateVideoFrames dari 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 previewOverlayView dan MLKDetectionOverlayView di aplikasi contoh Etalase sebagai contoh.

Langkah berikutnya