ML Kit を使用してポーズを検出する(iOS)

<ph type="x-smartling-placeholder">

ML Kit には、姿勢検出用に最適化された 2 つの SDK が用意されています。

SDK 名PoseDetectionPoseDetectionAccurate
実装基本検出機能のアセットは、ビルド時にアプリに静的にリンクされます。正確な検出機能用のアセットは、ビルド時にアプリに静的にリンクされます。
アプリのサイズ最大 29.6 MB最大 33.2 MB
パフォーマンスiPhone X: ~ 45 FPSiPhone X: ~ 29 FPS

試してみる

始める前に

  1. Podfile に次の ML Kit Pod を追加します。

    # 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. プロジェクトの Pod をインストールまたは更新したら、xcworkspace を使用して Xcode プロジェクトを開きます。ML Kit は Xcode バージョン 13.2.1 以降でサポートされています。

1. PoseDetector のインスタンスを作成する

画像内のポーズを検出するには、まず PoseDetector のインスタンスを作成し、 (省略可)検出項目の設定を指定します。

PoseDetectorのオプション

検出モード

PoseDetector は、2 つの検出モードで動作します。必ず一致するものを選択してください 選択できます。

stream(デフォルト)
姿勢検出機能は、まず最も大きい 使用して姿勢検出を実行します。後続のフレームでは 人物検知ステップは、その人物が 検出されなくなったり、高い信頼度で検出されなくなったりした場合です。姿勢検出機能が 最も目立つ人物を追跡し、それぞれのポーズでポーズをとって 説明します。これにより遅延が減少し、検出がスムーズになります。このモードは、 検出したい場合に使用します。
singleImage
姿勢検出器が人物を検出し、ポーズを実行します できます。人物検出ステップは画像ごとに実行されるため、レイテンシは 人物の追跡も行われませんポーズの使用時にこのモードを使用します 静的画像やトラッキングが不要な場合に 検出できます

姿勢検出器のオプションを指定します。

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;

最後に、PoseDetector のインスタンスを取得します。指定したオプションを渡します。

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. 入力画像を準備する

ポーズを検出するには、動画の画像またはフレームごとに次の操作を行います。 ストリーム モードを有効にした場合は、VisionImage オブジェクトを作成する必要があります。 CMSampleBuffer 秒。

VisionImageオブジェクトを作成するには、UIImage または CMSampleBuffer

UIImage を使用する場合は、次の手順を行います。

  • UIImage を使用して VisionImage オブジェクトを作成します。正しい .orientation を指定してください。

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

CMSampleBuffer を使用する場合は、次の手順を行います。

  • 格納されている画像データの向きを指定します。 CMSampleBuffer

    画像の向きを取得するには:

    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;
      }
    }
          
  • 次のコマンドを使用して、VisionImage オブジェクトを作成します。 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. 画像を処理する

VisionImage を姿勢検出器の画像処理メソッドのいずれかに渡します。非同期の process(image:) メソッドまたは同期の results() メソッドを使用できます。

オブジェクトを同期的に検出するには:

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.

オブジェクトを非同期で検出するには:

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. 検出された姿勢に関する情報を取得する

画像内で人物が検出されると、ポーズ検出 API は Pose オブジェクトの配列を完了ハンドラに渡すか、この配列を返します。 非同期メソッドと同期メソッドのどちらを呼び出したかによって、

人物が画像に完全に収まっていない場合、モデルは 足りないランドマークの座標がフレームの外側に InFrameConfidence 値。

人が検出されなかった場合、この配列は空になります。

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

パフォーマンスを向上させるためのヒント

結果の品質は入力画像の品質に依存します。

  • ML Kit で姿勢を正確に検出するには、画像に写っている人物が 十分なピクセルデータで表される。サブジェクトを 256x256 ピクセル以上
  • リアルタイム アプリケーションでポーズを検出する場合は、 入力画像の全体的なサイズ。小さい画像も処理できます より高速になります。レイテンシを短縮するには、画像を低解像度でキャプチャしますが、 上記の解決要件に留意し、 できるだけ大きな部分を占めるようにします
  • 画像のピントが悪い場合も精度に影響することがあります。満足のいく結果が得られない場合は 画像をキャプチャし直すようお客様に伝えます。

リアルタイムのアプリケーションで姿勢検出を使用する場合は、以下のガイドラインに沿って最適なフレームレートを使用してください。

  • ベースの PoseDetection SDK と stream 検出モードを使用します。
  • 解像度を下げて画像をキャプチャすることを検討してください。ただし、この API の画像サイズの要件にも留意してください。
  • 動画フレームの処理には、検出機能の results(in:) 同期 API を使用します。このメソッドは、AVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput(_, didOutput:from:) 関数を使用して、指定された動画フレームから結果を同期的に取得します。検出機能の呼び出しをスロットリングするには、AVCaptureVideoDataOutputalwaysDiscardsLateVideoFrames を true のままにします。検出機能の実行中に新しい動画フレームが使用可能になると、そのフレームはドロップされます。
  • 検出機能の出力を使用して入力画像にグラフィックをオーバーレイする場合は、まず ML Kit から結果を取得してから、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、処理された入力フレームごとに 1 回だけディスプレイ サーフェスにレンダリングします。詳しくは、 previewOverlayViewMLKDetectionOverlayView クラスをご覧ください。

次のステップ