Panduan deteksi penanda pose untuk iOS

Tugas Pose Landmarker memungkinkan Anda mendeteksi tolok ukur tubuh manusia dalam gambar atau video Anda. Anda dapat menggunakan tugas ini untuk mengidentifikasi lokasi utama, menganalisis postur tubuh, dan mengkategorikan gerakan. Tugas ini menggunakan model machine learning (ML) yang bekerja dengan satu gambar atau video. Tugas menghasilkan penanda body pose dalam gambar dan koordinat dunia 3 dimensi.

Petunjuk ini menunjukkan cara menggunakan Pose Landmarker dengan aplikasi iOS. Kode contoh yang dijelaskan dalam petunjuk ini tersedia di GitHub.

Anda dapat melihat cara kerja tugas ini dengan membuka Web demo. Untuk mengetahui informasi selengkapnya terkait kemampuan, model, dan opsi konfigurasi. tugas ini, lihat Ringkasan.

Contoh kode

Kode contoh Tugas MediaPipe adalah implementasi dasar dari Pose Landmarker untuk iOS. Contoh ini menggunakan kamera perangkat iOS fisik untuk mendeteksi mendeteksi pose dalam streaming video berkelanjutan. Aplikasi ini juga dapat mendeteksi pose di gambar dan video dari galeri perangkat.

Anda dapat menggunakan aplikasi ini sebagai titik awal untuk aplikasi iOS Anda sendiri, atau merujuk ke sana saat memodifikasi aplikasi yang ada. Kode contoh Pose Landmarker dihosting di GitHub.

Mendownload kode

Petunjuk berikut menunjukkan cara membuat salinan lokal dari contoh kode menggunakan alat command line git.

Untuk mendownload kode contoh:

  1. Clone repositori git menggunakan perintah berikut:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Secara opsional, konfigurasikan instance git Anda untuk menggunakan checkout sparse, sehingga Anda memiliki hanya file untuk aplikasi contoh Pose Landmarker:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/pose_landmarker/ios/
    

Setelah membuat versi lokal dari kode contoh, Anda dapat menginstal Library tugas MediaPipe, buka project menggunakan Xcode dan jalankan aplikasi. Sebagai lihat Panduan Penyiapan untuk iOS.

Komponen utama

File berikut berisi kode penting untuk contoh Pose Landmarker aplikasi:

Penyiapan

Bagian ini menjelaskan langkah-langkah utama untuk menyiapkan lingkungan pengembangan dan kode project untuk menggunakan Pose Landmarker. Untuk informasi umum tentang penyiapan lingkungan pengembangan untuk menggunakan tugas MediaPipe, termasuk versi platform persyaratan, lihat Panduan penyiapan untuk iOS.

Dependensi

Pose Landmarker menggunakan library MediaPipeTasksVision, yang harus diinstal menggunakan CocoaPods. Library ini kompatibel dengan aplikasi Swift dan Objective-C dan tidak memerlukan penyiapan tambahan khusus bahasa.

Untuk petunjuk menginstal CocoaPods di macOS, lihat CocoaPods panduan pemasangan kami. Untuk mendapatkan petunjuk cara membuat Podfile dengan pod yang diperlukan untuk aplikasi, lihat Menggunakan CocoaPods.

Tambahkan pod MediaPipeTasksVision di Podfile menggunakan kode berikut:

target 'MyPoseLandmarkerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Jika aplikasi Anda menyertakan target pengujian unit, lihat Panduan Penyiapan untuk iOS untuk informasi tambahan terkait penyiapan Podfile Anda.

Model

Tugas MediaPipe Pose Landmarker memerlukan paket terlatih yang kompatibel dengan tugas ini. Untuk informasi selengkapnya tentang model terlatih yang tersedia Pose Landmarker, lihat ringkasan tugas Model bagian.

Gunakan download_models.sh skrip untuk mengunduh model dan menambahkannya ke direktori proyek Anda menggunakan Xcode. Sebagai instruksi tentang cara menambahkan file ke proyek Xcode Anda, lihat Mengelola file dan folder di Xcode Anda project Anda.

Gunakan properti BaseOptions.modelAssetPath untuk menentukan jalur ke model dalam app bundle Anda. Untuk contoh kode, lihat bagian berikutnya.

Membuat tugas

Anda dapat membuat tugas Pose Landmarker dengan memanggil salah satu penginisialisasinya. Tujuan Penginisialisasi PoseLandmarker(options:) menerima nilai untuk konfigurasi lainnya.

Jika Anda tidak memerlukan Pose Landmarker yang diinisialisasi dengan konfigurasi yang disesuaikan Anda dapat menggunakan penginisialisasi PoseLandmarker(modelPath:) untuk membuat Pose Landmarker dengan opsi default. Untuk informasi selengkapnya tentang konfigurasi opsi, lihat Ringkasan Konfigurasi.

Tugas Pose Landmarker mendukung 3 jenis data input: file video dan gambar diam dan streaming video live. Secara default, PoseLandmarker(modelPath:) menginisialisasi untuk gambar diam. Jika Anda ingin tugas Anda diinisialisasi untuk memproses video file atau streaming video live, gunakan PoseLandmarker(options:) untuk menentukan video atau livestream berjalan. Mode livestream juga memerlukan opsi konfigurasi poseLandmarkerLiveStreamDelegate, yang memungkinkan Pose Landmarker untuk mengirimkan hasil deteksi penanda pose kepada delegasi secara asinkron.

Pilih tab yang sesuai dengan mode lari Anda untuk melihat cara membuat tugas dan menjalankan inferensi.

Swift

Gambar

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Video

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Livestream

import MediaPipeTasksVision

// Class that conforms to the `PoseLandmarkerLiveStreamDelegate` protocol and
// implements the method that the pose landmarker calls once it finishes
// performing pose landmark detection in each input frame.
class PoseLandmarkerResultProcessor: NSObject, PoseLandmarkerLiveStreamDelegate {

  func poseLandmarker(
    _ poseLandmarker: PoseLandmarker,
    didFinishDetection result: PoseLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the pose landmarker result or errors here.

  }
}

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

// Assign an object of the class to the `poseLandmarkerLiveStreamDelegate`
// property.
let processor = PoseLandmarkerResultProcessor()
options.poseLandmarkerLiveStreamDelegate = processor

let poseLandmarker = try PoseLandmarker(options: options)
    

Objective-C

Gambar

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Video

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Livestream

@import MediaPipeTasksVision;

// Class that conforms to the `MPPPoseLandmarkerLiveStreamDelegate` protocol
// and implements the method that the pose landmarker calls once it finishes
// performing pose landmarks= detection in each input frame.

@interface APPPoseLandmarkerResultProcessor : NSObject 

@end

@implementation APPPoseLandmarkerResultProcessor

-   (void)poseLandmarker:(MPPPoseLandmarker *)poseLandmarker
    didFinishDetectionWithResult:(MPPPoseLandmarkerResult *)poseLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the pose landmarker result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

// Assign an object of the class to the `poseLandmarkerLiveStreamDelegate`
// property.
APPPoseLandmarkerResultProcessor *processor =
  [APPPoseLandmarkerResultProcessor new];
options.poseLandmarkerLiveStreamDelegate = processor;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Catatan: Jika Anda menggunakan mode video atau mode livestream, Pose Landmarker menggunakan pelacakan untuk menghindari pemicuan model deteksi telapak tangan pada setiap bingkai, yang membantu mengurangi latensi.

Opsi konfigurasi

Tugas ini memiliki opsi konfigurasi berikut untuk aplikasi iOS:

Nama Opsi Deskripsi Rentang Nilai Nilai Default
running_mode Menetapkan mode berjalan untuk tugas. Ada tiga moda:

IMAGE: Mode untuk input gambar tunggal.

VIDEO: Mode untuk frame video yang didekode.

LIVE_STREAM: Mode untuk live stream input besar, seperti dari kamera. Dalam mode ini, poseLandmarkerLiveStreamDelegate harus ditetapkan ke instance class yang mengimplementasikan PoseLandmarkerLiveStreamDelegate untuk menerima hasil melakukan deteksi penanda pose secara asinkron.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_poses Jumlah maksimum pose yang bisa dideteksi oleh Pose Landmarker. Integer > 0 1
min_pose_detection_confidence Skor keyakinan minimum untuk deteksi pose dianggap berhasil. Float [0.0,1.0] 0.5
min_pose_presence_confidence Skor keyakinan minimum dari kehadiran pose skor dalam deteksi penanda pose. Float [0.0,1.0] 0.5
min_tracking_confidence Skor keyakinan minimum untuk pelacakan pose untuk dianggap berhasil. Float [0.0,1.0] 0.5
output_segmentation_masks Apakah Pose Landmarker menghasilkan mask segmentasi untuk objek yang terdeteksi berpose. Boolean False
result_callback Menetapkan pemroses hasil untuk menerima hasil landmark secara asinkron saat Pose Landmarker berada dalam mode live stream. Hanya dapat digunakan saat mode lari disetel ke LIVE_STREAM ResultListener N/A

Konfigurasi livestream

Ketika mode lari diatur ke live stream, Pose Landmarker memerlukan opsi konfigurasi poseLandmarkerLiveStreamDelegate tambahan, yang memungkinkan Pose Landmarker memberikan hasil deteksi penanda pose secara asinkron. Delegasi harus mengimplementasikan Metode poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), yang dipanggil Pose Landmarker setelah memproses hasil melakukan pose deteksi penanda di setiap {i>frame<i}.

Nama opsi Deskripsi Rentang Nilai Nilai Default
poseLandmarkerLiveStreamDelegate Mengaktifkan Penanda Pose untuk menerima hasil melakukan pose deteksi landmark secara asinkron dalam mode livestream. Class yang yang ditetapkan ke properti ini, instance harus menerapkan poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) . Tidak berlaku Tidak ditetapkan

Menyiapkan data

Anda harus mengonversi gambar atau bingkai input menjadi objek MPImage sebelum meneruskannya ke Pose Landmarker. MPImage mendukung berbagai jenis image iOS format, dan dapat menggunakannya dalam mode berjalan apa pun untuk inferensi. Untuk selengkapnya informasi tentang MPImage, lihat MPImage API

Pilih format gambar iOS berdasarkan kasus penggunaan dan mode lari yang aplikasi diperlukan.MPImage menerima UIImage, CVPixelBuffer, dan CMSampleBuffer Format gambar iOS.

UIImage

Format UIImage sangat cocok untuk mode berjalan berikut:

  • Gambar: gambar dari app bundle, galeri pengguna, atau sistem file yang diformat sebagai Gambar UIImage dapat dikonversi menjadi objek MPImage.

  • Video: menggunakan AVAssetImageGenerator untuk mengekstrak frame video ke CGImage baru, lalu konversikan menjadi gambar UIImage.

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Contoh ini menginisialisasi MPImage dengan UIImage.Orientation.Up orientasi. Anda dapat menginisialisasi MPImage dengan metode UIImage.Orientation masing-masing. Pose Landmarker tidak mendukung orientasi yang dicerminkan seperti .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

Untuk informasi selengkapnya tentang UIImage, lihat UIImage Apple Developer Dokumentasi.

CVPixelBuffer

Format CVPixelBuffer sangat cocok untuk aplikasi yang membuat frame dan menggunakan CoreImage iOS untuk pemrosesan.

Format CVPixelBuffer sangat cocok untuk mode berjalan berikut:

  • Gambar: aplikasi yang membuat gambar CVPixelBuffer setelah beberapa pemrosesan yang menggunakan framework CoreImage iOS dapat dikirim ke Pose Landmarker di mode image running.

  • Video: frame video dapat dikonversi ke format CVPixelBuffer untuk diproses, lalu dikirim ke Pose Landmarker dalam mode video.

  • livestream: aplikasi yang menggunakan kamera iOS untuk membuat frame dapat dikonversi ke dalam format CVPixelBuffer untuk diproses sebelum dikirim ke Tampilkan Tolok Ukur dalam mode livestream.

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Untuk informasi selengkapnya tentang CVPixelBuffer, lihat CVPixelBuffer Apple Pengembang Dokumentasi.

CMSampleBuffer

Format CMSampleBuffer menyimpan sampel media dari jenis media yang seragam, dan sangat cocok untuk mode livestream yang sedang berjalan. {i>Live frame<i} dari kamera iOS dikirim secara asinkron dalam format CMSampleBuffer oleh iOS AVCaptureVideoDataOutput.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

Untuk informasi selengkapnya tentang CMSampleBuffer, lihat CMSampleBuffer Apple Pengembang Dokumentasi.

Menjalankan tugas

Untuk menjalankan Pose Landmarker, gunakan metode detect() khusus untuk penanda mode lari:

  • Gambar diam: detect(image:)
  • Video: detect(videoFrame:timestampInMilliseconds:)
  • Livestream: detectAsync(image:timestampInMilliseconds:)

Contoh kode berikut menunjukkan contoh sederhana tentang cara menjalankan Pose Landmarker di mode lari yang berbeda:

Swift

Gambar

let result = try poseLandmarker.detect(image: image)
    

Video

let result = try poseLandmarker.detect(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

Livestream

try poseLandmarker.detectAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

Gambar

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectImage:image error:nil];
    

Video

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

Livestream

BOOL success =
  [poseLandmarker detectAsyncImage:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

Contoh kode Pose Landmarker menunjukkan implementasi dari setiap mode ini secara lebih detail detect(image:), detect(videoFrame:timestampInMilliseconds:), dan detectAsync(image:timestampInMilliseconds:). Kode contoh memungkinkan pengguna untuk beralih di antara mode pemrosesan yang mungkin tidak diperlukan untuk penggunaan Anda ini masalahnya atau bukan.

Perhatikan hal berikut:

  • Saat berjalan dalam mode video atau mode livestream, Anda juga harus menyediakan stempel waktu {i>frame<i} input ke tugas Pose Landmarker.

  • Saat berjalan dalam mode gambar atau video, tugas Pose Landmarker memblokir thread saat ini hingga selesai memproses gambar atau bingkai input. Kepada menghindari pemblokiran thread saat ini, jalankan pemrosesan di latar belakang thread menggunakan iOS Dispatch atau NSOperation framework.

  • Saat berjalan dalam mode livestream, tugas Pose Landmarker akan langsung ditampilkan dan tidak memblokir thread saat ini. Fungsi ini memanggil poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) metode dengan hasil pose landmarker setelah memproses setiap {i>frame<i} input. Tujuan Pose Landmarker memanggil metode ini secara asinkron pada rangkaian khusus antrean pengiriman. Untuk menampilkan hasil pada antarmuka pengguna, kirim hasil ke antrean utama setelah memproses hasilnya. Jika detectAsync dipanggil saat tugas Pose Landmarker sedang sibuk memproses {i>frame<i} tersebut, maka Pose Landmarker akan mengabaikan {i>frame<i} input baru.

Menangani dan menampilkan hasil

Setelah menjalankan inferensi, tugas Pose Landmarker akan menampilkan PoseLandmarkerResult yang berisi koordinat untuk setiap penanda pose.

Berikut ini contoh data output dari tugas ini:

PoseLandmarkerResult:
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : 0.129959
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
      visibility   : 0.999909
      presence     : 0.999958
    ... (33 landmarks per pose)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
      visibility   : 0.999976
      presence     : 0.999998
    ... (33 world landmarks per pose)
  SegmentationMasks:
    ... (pictured below)

Output berisi koordinat yang dinormalkan (Landmarks) dan dunia koordinat (WorldLandmarks) untuk setiap penanda.

Output berisi koordinat yang dinormalkan berikut (Landmarks):

  • x dan y: Koordinat tempat terkenal dinormalisasi antara 0,0 dan 1,0 dengan lebar gambar (x) dan tinggi (y).

  • z: Kedalaman tempat terkenal, dengan kedalaman di titik tengah pinggul sebagai tempat asal. Makin kecil nilainya, makin dekat tempat terkenal tersebut ke kamera. Tujuan magnitudo z menggunakan skala yang kurang lebih sama dengan x.

  • visibility: Kemungkinan tempat terkenal terlihat dalam gambar.

Output berisi koordinat dunia berikut (WorldLandmarks):

  • x, y, dan z: Koordinat 3 dimensi dunia nyata dalam meter, dengan tengah pinggul sebagai asalnya.

  • visibility: Kemungkinan tempat terkenal terlihat dalam gambar.

Gambar berikut menunjukkan visualisasi output tugas:

Masker segmentasi opsional mewakili kemungkinan setiap piksel yang termasuk dalam ke orang yang terdeteksi. Gambar berikut adalah mask segmentasi dari output tugas:

Kode contoh Pose Landmarker menunjukkan cara menampilkan Penanda Pose hasil pengujian tersebut.