iOS 向けの顔のランドマーク検出ガイド

MediaPipe Face Landmarker タスクを使用すると、画像や動画内の顔のランドマークと顔の表情を検出できます。このタスクでは、人間の顔の表情の識別、顔のフィルタとエフェクトの適用、仮想アバターの作成を行えます。このタスクでは、単一の画像、動画、または連続した画像ストリームを処理できる ML モデルを使用します。このタスクは、3 次元の顔のランドマーク、詳細な顔面をリアルタイムで推定するブレンドシェイプ スコア(表情を表す係数)、エフェクトのレンダリングに必要な変換を実行する変換行列を出力します。

これらの手順で説明するコードサンプルは GitHub で入手できます。このタスクの動作を確認するには、こちらのウェブデモをご覧ください。このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。

サンプルコード

MediaPipe Tasks のサンプルコードは、iOS 向けの Face Landmarker アプリの基本的な実装です。この例では、物理的な iOS デバイスのカメラを使用して、連続した動画ストリーム内の顔の特徴を検出します。このアプリは、デバイスのギャラリーにある画像や動画内の顔のランドマークも検出できます。

このアプリは、独自の iOS アプリの開始点として使用できます。また、既存のアプリを変更する際にも参照できます。Face Landmarker のサンプルコードは GitHub でホストされています。

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

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

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

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

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

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

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

主要コンポーネント

次のファイルには、顔認識用ランドマーク サンプル アプリケーション用の重要なコードが含まれています。

セットアップ

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

依存関係

Face Landmarker は MediaPipeTasksVision ライブラリを使用します。このライブラリは CocoaPods を使用してインストールする必要があります。このライブラリは Swift アプリと Objective-C アプリの両方に対応しており、言語固有の追加設定は必要ありません。

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

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

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

アプリに単体テスト ターゲットがある場合は、Podfile の設定の詳細については、iOS 用セットアップ ガイドをご覧ください。

モデル

MediaPipe フェイス ランドマーカー タスクには、このタスクと互換性のあるトレーニング済みモデルバンドルが必要です。顔認識用ランドマークで使用可能なトレーニング済みモデルについて詳しくは、タスクの概要のモデル セクションをご覧ください。

モデルを選択してダウンロードし、Xcode を使用してプロジェクト ディレクトリに追加します。Xcode プロジェクトにファイルを追加する方法については、Xcode プロジェクト内のファイルとフォルダの管理をご覧ください。

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

タスクを作成する

Face Landmarker タスクは、いずれかのイニシャライザを呼び出すことで作成できます。FaceLandmarker(options:) イニシャライザは、構成オプションの値を受け入れます。

カスタマイズされた構成オプションで初期化されたフェイス ランドマークが不要な場合は、FaceLandmarker(modelPath:) イニシャライザを使用して、デフォルト オプションでフェイス ランドマークを作成できます。構成オプションの詳細については、構成の概要をご覧ください。

顔認識地マーカータスクは、静止画像、動画ファイル、ライブ動画ストリームの 3 つの入力データタイプをサポートします。デフォルトでは、FaceLandmarker(modelPath:) は静止画像のタスクを初期化します。動画ファイルやライブ動画ストリームを処理するためにタスクを初期化する場合は、FaceLandmarker(options:) を使用して動画またはライブ配信の実行モードを指定します。ライブ配信モードでは、Face Landmarker が顔の特徴点を非同期でデリゲートに配信できるようにする faceLandmarkerLiveStreamDelegate 構成オプションも必要です。

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

Swift

画像

import MediaPipeTasksVision

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

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

let faceLandmarker = try FaceLandmarker(options: options)
    

動画

import MediaPipeTasksVision

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

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

let faceLandmarker = try FaceLandmarker(options: options)
    

ライブ配信

import MediaPipeTasksVision

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

  func faceLandmarker(
    _ faceLandmarker: FaceLandmarker,
    didFinishDetection result: FaceLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the face landmarker result or errors here.

  }
}

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

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

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

let faceLandmarker = try FaceLandmarker(options: options)
    

Objective-C

画像

@import MediaPipeTasksVision;

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

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

動画

@import MediaPipeTasksVision;

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

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

ライブ配信

@import MediaPipeTasksVision;

// Class that conforms to the `MPPFaceLandmarkerLiveStreamDelegate` protocol
// and implements the method that the face landmarker calls once it finishes
// performing face landmark detection in each input frame.
@interface APPFaceLandmarkerResultProcessor : NSObject 

@end

@implementation APPFaceLandmarkerResultProcessor

-   (void)faceLandmarker:(MPPFaceLandmarker *)faceLandmarker
    didFinishDetectionWithResult:(MPPFaceLandmarkerResult *)faceLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the face landmarker result or errors here.

}

@end

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

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

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

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

注: 動画モードまたはライブ配信モードを使用している場合、Face Landmarker はトラッキングを使用して、フレームごとに検出モデルをトリガーしないようにします。これにより、レイテンシを短縮できます。

設定オプション

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

オプション名 説明 値の範囲 デフォルト値
runningMode タスクの実行モードを設定します。Face Landmarker には 3 つのモードがあります。

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

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

LIVE_STREAM: カメラなどからの入力データのライブ配信モード。このモードでは、顔ランドマーク検出の実行結果を非同期で受信するには、faceLandmarkerLiveStreamDelegate を FaceLandmarkerLiveStreamDelegate を実装するクラスのインスタンスに設定する必要があります。
{RunningMode.image, RunningMode.video, RunningMode.liveStream} {RunningMode.image}
numFaces Face Landmarker で検出できる顔の最大数。スムージングは、numFaces が 1 に設定されている場合にのみ適用されます。 0 より大きい整数 1
minFaceDetectionConfidence 顔検出が成功と見なされるための最小信頼スコア。 浮動小数点数 [0.0,1.0] 0.5
minFacePresenceConfidence 顔ランドマーク検出における顔存在スコアの最小信頼スコア。 浮動小数点数 [0.0,1.0] 0.5
minTrackingConfidence 顔トラッキングが成功と見なされるための最小信頼スコア。 浮動小数点数 [0.0,1.0] 0.5
outputFaceBlendshapes FaceLandmarker が顔のブレンドシェイプを出力するかどうか。顔のブレンドシェイプは、3D 顔モデルのレンダリングに使用されます。 Bool false
outputFacialTransformationMatrixes FaceLandmarker が顔の変換行列を出力するかどうか。FaceLandmarker は、マトリックスを使用して顔ランドマークを標準の顔モデルから検出された顔に変換します。これにより、ユーザーは検出されたランドマークにエフェクトを適用できます。 Bool false

実行モードが LIVE_STREAM に設定されている場合、顔のランドマークは追加の faceLandmarkerLiveStreamDelegate 設定オプションを必要とします。これにより、顔のランドマークの検出結果を非同期で配信できるようになります。デリゲートは faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッドを実装する必要があります。このメソッドは、各フレームで顔のランドマーク検出の結果を処理した後に、顔のランドマーク マーカーによって呼び出されます。

オプション名 説明 値の範囲 デフォルト値
faceLandmarkerLiveStreamDelegate ライブ配信モードで顔のランドマーク検出を非同期で実行した結果を Face Landmarker が受け取れるようにします。このプロパティにインスタンスが設定されているクラスは、faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッドを実装する必要があります。 該当なし 未設定

データの準備

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

ユースケースとアプリケーションに必要な実行モードに基づいて、iOS 画像形式を選択します。MPImage は、UIImageCVPixelBufferCMSampleBuffer の iOS 画像形式を受け入れます。

UIImage

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

  • 画像: アプリバンドル、ユーザー ギャラリー、または 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 値のいずれかで初期化できます。Face Landmarker は、.upMirrored.downMirrored.leftMirrored.rightMirrored などのミラーリングされた向きをサポートしていません。

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

CVPixelBuffer

CVPixelBuffer 形式は、フレームを生成し、iOS の CoreImage フレームワークを使用して処理するアプリに適しています。

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

  • 画像: iOS の CoreImage フレームワークを使用して処理を行った後に CVPixelBuffer 画像を生成するアプリは、画像実行モードで Face Landmarker に送信できます。

  • 動画: 動画フレームは処理用に CVPixelBuffer 形式に変換し、動画モードで Face Landmarker に送信できます。

  • ライブ配信: 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 の AVCaptureVideoDataOutput によって CMSampleBuffer 形式で非同期的に配信されます。

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 デベロッパー ドキュメントをご覧ください。

タスクを実行する

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

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

次のコードサンプルは、これらのさまざまな実行モードで Face Landmarker を実行する方法の基本的な例を示しています。

Swift

画像

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

動画

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

ライブ配信

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

Objective-C

画像

MPPFaceLandmarkerResult *result =
  [faceLandmarker detectImage:image error:nil];
    

動画

MPPFaceLandmarkerResult *result =
  [faceLandmarker detectVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

ライブ配信

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

顔認識地マーカーのコード例では、これらの各モードの実装を detect(image:)detect(videoFrame:timestampInMilliseconds:)detectAsync(image:timestampInMilliseconds:) で詳しく示しています。サンプルコードでは、ユーザーが処理モードを切り替えることができますが、ユースケースで必要でない場合があります。

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

  • 動画モードまたはライブ配信モードで実行する場合は、入力フレームのタイムスタンプを Face Landmarker タスクに指定する必要があります。

  • 画像モードまたは動画モードで実行している場合、顔認識地マーカータスクは、入力画像またはフレームの処理が完了するまで現在のスレッドをブロックします。現在のスレッドをブロックしないようにするには、iOS の Dispatch または NSOperation フレームワークを使用して、バックグラウンド スレッドで処理を実行します。アプリが Swift を使用して作成されている場合は、バックグラウンド スレッドの実行に Swift の同時実行を使用することもできます。

  • ライブ ストリーム モードで実行した場合、顔認識地マーカータスクはすぐに結果を返し、現在のスレッドをブロックしません。各入力フレームを処理した後、顔ランドマーク検出結果を指定して faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) メソッドを呼び出します。Face Landmarker は、専用のシリアル ディスパッチ キューでこのメソッドを非同期で呼び出します。結果をユーザー インターフェースに表示するには、結果を処理した後に結果をメインキューにディスパッチします。

結果の処理と表示

推論を実行すると、Face Landmarker は、検出された各顔の顔メッシュと、各顔ランドマークの座標を含む FaceLandmarkerResult を返します。必要に応じて、結果オブジェクトに、顔の表情を表すブレンドシェイプと、検出されたランドマークに顔エフェクトを適用する顔変換マトリクスを含めることもできます。

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

FaceLandmarkerResult:
  face_landmarks:
    NormalizedLandmark #0:
      x: 0.5971359014511108
      y: 0.485361784696579
      z: -0.038440968841314316
    NormalizedLandmark #1:
      x: 0.3302789330482483
      y: 0.29289937019348145
      z: -0.09489090740680695
    ... (478 landmarks for each face)
  face_blendshapes:
    browDownLeft: 0.8296722769737244
    browDownRight: 0.8096957206726074
    browInnerUp: 0.00035583582939580083
    browOuterUpLeft: 0.00035752105759456754
    ... (52 blendshapes for each face)
  facial_transformation_matrixes:
    [9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
    [1.66496094e-02,  9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
    ...

次の画像は、タスク出力の可視化を示しています。

Face Landmarker のサンプルコードは、タスクから返された結果を表示する方法を示しています。詳細については、FaceOverlay.swift をご覧ください。