ML Kit には、ポーズ検出用に最適化された 2 つの SDK が用意されています。
SDK の名前 | PoseDetection | PoseDetectionAccurate |
---|---|---|
実装 | ベース検出機能のアセットは、ビルド時にアプリに静的にリンクされます。 | 正確な検出機能のアセットは、ビルド時にアプリに静的にリンクされます。 |
アプリのサイズ | 最大 29.6 MB | 最大 33.2 MB |
パフォーマンス | iPhone X: 約 45 fps | iPhone X: 約 29 FPS |
試してみる
- サンプルアプリを試して、この API の使用例を確認してください。
始める前に
Podfile に次の ML Kit Pod を含めます。
# If you want to use the base implementation: pod 'GoogleMLKit/PoseDetection', '7.0.0' # If you want to use the accurate implementation: pod 'GoogleMLKit/PoseDetectionAccurate', '7.0.0'
プロジェクトの 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. 入力画像を準備する
ポーズを検出するには、各画像または動画フレームに対して次の手順を行います。ストリーム モードを有効にした場合は、CMSampleBuffer
から VisionImage
オブジェクトを作成する必要があります。
UIImage
または CMSampleBuffer
を使用して VisionImage
オブジェクトを作成します。
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; } }
CMSampleBuffer
オブジェクトと向きを使用してVisionImage
オブジェクトを作成します。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 でポーズを正確に検出するには、画像内の人物が十分なピクセルデータによって表現されている必要があります。パフォーマンスを最大限に高めるには、被写体が 256 x 256 ピクセル以上である必要があります。
- リアルタイム アプリケーションでポーズを検出する場合は、入力画像の全体サイズも考慮する必要があります。サイズが小さいほど処理は高速になるため、レイテンシを短くするには画像を低い解像度でキャプチャし(上記の解像度要件に留意)、被写体が画像のできるだけ多くの部分を占めるようにします。
- 画像がぼやけていると、認識精度が低下する可能性があります。満足のいく結果が得られない場合は、ユーザーに画像をキャプチャし直すよう依頼します。
リアルタイムのアプリケーションでポーズ検出を使用する場合は、適切なフレームレートを得るために次のガイドラインに従ってください。
- ベースの PoseDetection SDK と
stream
検出モードを使用します。 - より低い解像度で画像をキャプチャすることを検討してください。ただし、この API の画像サイズに関する要件にも留意してください。
- 動画フレームを処理するには、検出機能の
results(in:)
同期 API を使用します。AVCaptureVideoDataOutputSampleBufferDelegate の captureOutput(_, didOutput:from:) 関数からこのメソッドを呼び出して、指定された動画フレームから結果を同期的に取得します。検出器の呼び出しをスロットルするには、AVCaptureVideoDataOutput の alwaysDiscardsLateVideoFrames を true のままにします。検出器の実行中に新しい動画フレームが使用可能になった場合は、そのフレームは破棄されます。 - 検出器の出力を使用して入力画像の上にグラフィックスをオーバーレイする場合は、まず ML Kit から検出結果を取得し、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、ディスプレイ サーフェスへのレンダリングは、処理された入力フレームごとに 1 回で済みます。例については、ショーケース サンプルアプリの previewOverlayView クラスと MLKDetectionOverlayView クラスをご覧ください。
次のステップ
- ポーズ ランドマークを使用してポーズを分類する方法については、ポーズ分類のヒントをご覧ください。
- この API の使用例については、GitHub の ML Kit クイックスタート サンプルをご覧ください。