iOS 向け姿勢ランドマーク検出ガイド

[Pose Landmarker] タスクでは、画像内の人体のランドマークを検出したり、 動画をご覧ください。このタスクを使用して、主な身体の位置の特定、姿勢の分析、 動きを分類できますこのタスクでは、適切な ML モデルを使用して、 単一の画像または動画を含めることができますこのタスクは、身体ポーズのランドマークを画像に出力します。 3 次元の世界座標で表します。

iOS アプリでのポーズのマーカーの使用方法を解説します。コード ここで説明するサンプルは、 GitHub

このタスクの動作を確認するには、こちらのウェブ デモをご覧ください。 機能、モデル、構成オプションの詳細については、 詳細については、 概要

サンプルコード

MediaPipe Tasks のサンプルコードは、Pose LandMarker の基本的な実装です。 アプリこの例では、物理的な iOS デバイスのカメラを使用して、 連続する動画ストリームでポーズを検出します。また、 デバイスのギャラリーから画像と動画を抽出できます。

独自の iOS アプリの出発点としてアプリを使用することも、アプリ自体に言及することもできます。 変更する際の注意点があります。「Pose Landmarker」サンプルコードは GitHub

コードをダウンロードする

次の手順では、サンプルのローカルコピーを作成する方法を示します。 git コマンドライン ツールを使用してコードを実行します。

サンプルコードをダウンロードするには:

  1. 次のコマンドを使用して Git リポジトリのクローンを作成します。

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成し、 次のサンプルは、Pose Landmarker サンプルアプリのファイルのみに対応しています。

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

ローカル バージョンのサンプルコードを作成したら、 MediaPipe タスク ライブラリで、Xcode を使用してプロジェクトを開き、アプリを実行します。対象 手順については、iOS の設定ガイドをご覧ください。

主要コンポーネント

次のファイルには、位置マーカーのサンプルで使用する重要なコードが含まれています。 アプリケーション:

  • PoseLandmarkerService.swift: ランドマークを初期化し、モデル選択を処理して推論を実行する 必要があります。
  • CameraViewController: ライブカメラフィード入力モードの UI を実装し、 使用できます。
  • MediaLibraryViewController.swift: 静止画像ファイルと動画ファイル入力モードの UI を実装します。 ランドマークを可視化します

セットアップ

このセクションでは、開発環境をセットアップする主な手順と Pose Landmarker を使用するコード プロジェクト。設定に関する一般的な情報については、 MediaPipe タスクを使用するための開発環境(プラットフォーム バージョンを含む) iOS の設定ガイドをご覧ください。

依存関係

姿勢のマーカーは、MediaPipeTasksVision ライブラリを使用します(このライブラリをインストールする必要があります)。 構築しましたこのライブラリは Swift アプリと Objective-C アプリの両方と互換性がある 言語固有の追加の設定は不要です

macOS に CocoaPods をインストールする手順については、CocoaPods インストール ガイドをご覧ください。 必要な Pod を使用して Podfile を作成する方法については、 詳しくは、 CocoaPods

次のコードを使用して、Podfile に MediaPipeTasksVision Pod を追加します。

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

アプリに単体テスト ターゲットが含まれている場合は、 iOS をご覧ください。 あなたのPodfile

モデル

MediaPipe Pose Landmarker タスクには、互換性のあるトレーニング済みバンドルが必要です 見ていきましょう。利用可能なトレーニング済みモデルについて詳しくは、 地勢マーカーのポーズについては、タスクの概要をご覧ください。モデル セクションをご覧ください

download_models.sh スクリプト Xcode を使用してモデルをダウンロードし、プロジェクト ディレクトリに追加します。対象 Xcode プロジェクトにファイルを追加する手順については、ファイルの管理 Xcode 内のフォルダと、 プロジェクトです。

BaseOptions.modelAssetPath プロパティを使用してモデルのパスを指定する 追加できますコード例については、次のセクションをご覧ください。

タスクを作成する

Pose Landmarker タスクを作成するには、そのイニシャライザのいずれかを呼び出します。「 PoseLandmarker(options:) イニシャライザが構成の値を受け入れる 。

カスタマイズされた設定で初期化されたポーズのランドマーク マーカーが不要な場合 PoseLandmarker(modelPath:) イニシャライザを使用して、 デフォルトのオプションを使用して地面マーカーのポーズを行います。リソースの構成について 構成の概要をご覧ください。

Pose Landmarker タスクは、静止画像と動画ファイルの 3 つの入力データタイプをサポートします。 ストリーミング動画にも対応していますデフォルトでは、PoseLandmarker(modelPath:) は 行います。動画を処理するためにタスクを初期化する場合は、 ファイルまたはライブ動画ストリームの場合は、PoseLandmarker(options:) を使用して動画を指定します 配信モードを選択できますライブ配信モードでは、 poseLandmarkerLiveStreamDelegate 構成オプションを使用すると、 ポーズ ランドマークの検出結果を委任者に提示するために、ランドマークの向きを調整します。 使用できます。

ランニングモードに対応するタブを選択すると、タスクの作成方法を確認できます 推論を実行できます

Swift

画像

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)
    

動画

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)
    

ライブ配信

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

画像

@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];
    

動画

@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];
    

ライブ配信

@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];
    

注: 動画モードまたはライブ配信モードを使用している場合、姿勢位置マーカーは フレームごとに手のひら検出モデルがトリガーされるのを回避し、 レイテンシを短縮できます

構成オプション

このタスクには、iOS アプリの場合、次の構成オプションがあります。

オプション名 説明 値の範囲 デフォルト値
running_mode タスクの実行モードを設定します。3 つの モード:

IMAGE: 単一画像入力のモード。

VIDEO: 動画のデコードされたフレームのモード。

LIVE_STREAM: 入力のライブ配信のモード カメラからのデータなどです。 このモードでは、poseLandmarkerLiveStreamDelegate を 実装するクラスのインスタンス PoseLandmarkerLiveStreamDelegate で次の結果を受け取る: 非同期で実行できます
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_poses 地面マーカーのポーズ。 Integer > 0 1
min_pose_detection_confidence 姿勢検出に必要な最小信頼スコア 成功したとみなされます。 Float [0.0,1.0] 0.5
min_pose_presence_confidence ポーズの有無に関する最小信頼スコア スコアを記録しました。 Float [0.0,1.0] 0.5
min_tracking_confidence ポーズ トラッキングの最小信頼スコア 成功とみなされます。 Float [0.0,1.0] 0.5
output_segmentation_masks 位置マーカーのセグメンテーション マスクが、検出された要素に対してセグメンテーション マスクを出力するかどうか ポーズを決めます。 Boolean False
result_callback ランドマークの結果を受け取るように結果リスナーを設定します。 Pose Landmarker がライブ ストリーム モードのときに非同期で配信されます。 実行モードが LIVE_STREAM に設定されている場合にのみ使用できます ResultListener N/A

ライブ配信の設定

ランニング モードが [ライブ配信] に設定されている場合は、 追加の poseLandmarkerLiveStreamDelegate 構成オプションがあり、 姿勢のランドマーク検出により、姿勢のランドマーク検出の結果を取得できます 使用できます。委譲は、 poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッド、 ポーズ実行の結果を処理した後に、ポーズ LandMarker が呼び出すものです。 ランドマーク検出を行います。

オプション名 説明 値の範囲 デフォルト値
poseLandmarkerLiveStreamDelegate ポーズの Landmarker がポーズの実行結果を受け取れるようにします ランドマーク検出の非同期モードです。クラスの このプロパティが設定されている場合は、 poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッドを呼び出します。 該当なし 未設定

データの準備

事前に入力画像またはフレームを MPImage オブジェクトに変換する必要があります。 ポーズマーカーに渡します。MPImage はさまざまな種類の iOS 画像をサポートしています 形式があり、任意の実行モードで推論に使用できます。詳細 MPImage の詳細については、 MPImage API

ユースケースと実行モードに基づいて、iOS 画像形式を選択してください MPImage は、UIImageCVPixelBuffer、および CMSampleBuffer 件の iOS 画像形式。

UIImage

UIImage 形式は、次の実行モードに適しています。

  • 画像: App Bundle、ユーザー ギャラリー、ファイル システムの UIImage の画像は MPImage オブジェクトに変換できます。

  • 動画: AVAssetImageGenerator を使用 動画フレームを抽出して CGImage 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];
    

この例では、MPImage をデフォルトの UIImage.Orientation.Up 方向です。MPImage は、サポートされているいずれかの方法で初期化できます。 UIImage.Orientation 使用できます。位置マーカーは、.upMirrored のように、向きの逆方向には対応していません。 .downMirrored.leftMirrored.rightMirrored

UIImage の詳細については、UIImage Apple Developer をご覧ください。 ドキュメントをご覧ください。

CVPixelBuffer

CVPixelBuffer 形式はフレームを生成するアプリに適している iOS の CoreImage を使用してください。 処理するためのフレームワークです。

CVPixelBuffer 形式は、次の実行モードに適しています。

  • 画像: なんらかの処理後に CVPixelBuffer の画像を生成するアプリ iOS の CoreImage フレームワークを使用すると、 構成されます

  • 動画: 動画フレームは CVPixelBuffer 形式に変換できます。 動画モードでポーズ マーカーに送信されます。

  • ライブ ストリーム: iOS カメラを使用してフレームを生成するアプリは、 送信する前に、CVPixelBuffer 形式に変換する ライブ配信モードで地面マーカーのポーズ。

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

CVPixelBuffer の詳細については、CVPixelBuffer Apple をご覧ください。 デベロッパー ドキュメントをご覧ください。

CMSampleBuffer

CMSampleBuffer 形式では、統一されたメディアタイプのメディア サンプルが保存されます。 ライブ配信の実行モードに適していますiOS カメラのライブフレームは、 iOS によって CMSampleBuffer 形式で非同期に配信されます。 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];
    

CMSampleBuffer の詳細については、CMSampleBuffer Apple をご覧ください。 デベロッパー ドキュメントをご覧ください。

タスクを実行する

ポーズのマーカーを実行するには、割り当てられたマーカーに固有の detect() メソッドを使用します。 実行モード:

  • 静止画像: detect(image:)
  • 動画: detect(videoFrame:timestampInMilliseconds:)
  • ライブ配信: detectAsync(image:timestampInMilliseconds:)

次のコードサンプルは、 実行モードが 3 つあります

Swift

画像

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

動画

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

ライブ配信

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

Objective-C

画像

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

動画

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

ライブ配信

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

ポーズの Landmarker のコード例は、これらの各モードの実装を示しています。 詳細: detect(image:)detect(videoFrame:timestampInMilliseconds:)、 および detectAsync(image:timestampInMilliseconds:)。サンプルコードでは ユーザーが不要な処理モードを切り替えられるようにする あります。

次の点にご留意ください。

  • 動画モードまたはライブ配信モードで実行する場合は、 Pose Landmarker タスクへの入力フレームのタイムスタンプ。

  • 画像モードまたは動画モードで [Pose Landmarker] タスクを実行すると、 入力画像やフレームの処理が完了するまで待機しません。宛先 現在のスレッドをブロックせずにバックグラウンドで処理を実行 使用すると、 Dispatch または NSOperation 説明します。

  • ライブストリーム モードで実行している場合、Pose Landmarker タスクがすぐに返されます。 現在のスレッドをブロックしません。このメソッドは、 poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッド 各入力フレームを処理した後に、ポーズ ランカマーの結果と比較します。「 Pose Landmarker が、このメソッドを専用シリアル通信で非同期的に呼び出します。 ディスパッチキューに格納されます。ユーザー インターフェースに結果を表示するには、 メインキューに送られます。detectAsync 関数は、Pose Landmarker タスクが他のタスクの処理でビジー状態になったときに呼び出されます ポーズ位置マーカーは、新しい入力フレームを無視します。

結果の処理と表示

推論を実行すると、Pose Landmarker タスクから PoseLandmarkerResult が返されます。 これには各ポーズ ランドマークの座標が含まれます。

このタスクからの出力データの例を次に示します。

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)

出力には、正規化された座標(Landmarks)と世界の両方が含まれます。 各ランドマークの座標(WorldLandmarks)があります。

出力には、次の正規化された座標(Landmarks)が含まれます。

  • xy: 0.0 ~ 1.0 の範囲で正規化されたランドマーク座標 画像の幅(x)と高さ(y)を指定します。

  • z: ランドマークの深さ。腰の中間点の深さが 含まれます。値が小さいほど、ランドマークがカメラに近づきます。「 z の大きさは x とほぼ同じスケールを使用します。

  • visibility: 画像内にランドマークが見える可能性。

出力には、次のワールド座標(WorldLandmarks)が含まれます。

  • xyz: 実世界の 3 次元座標(メートル単位)。 中間点を起点とします。

  • visibility: 画像内にランドマークが見える可能性。

次の図は、タスク出力を可視化したものです。

セグメンテーション マスク(省略可)は、各ピクセルが帰属する可能性を表します。 通知します。次の画像は、画像のセグメンテーション マスクです。 タスクの出力:

姿勢のランドマークを示すサンプルコードは、ポーズのマーカーを表示する方法を示しています。 表示されます。