MediaPipe 画像セグメンテーション タスクを使用すると、事前定義されたカテゴリに基づいて画像を領域に分割し、背景のぼかしなどの視覚効果を適用できます。ここでは、Android アプリで画像セグメンテーションを使用する方法について説明します。この手順で説明するサンプルコードは、GitHub で入手できます。このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。
サンプルコード
MediaPipe Tasks のコード例には、Android 用の画像セグメンタ アプリの 2 つの簡単な実装が含まれています。
この例では、実際の Android デバイスのカメラを使用して、ライブカメラフィードで画像セグメンテーションを実行します。また、デバイス ギャラリーから画像や動画を選択することもできます。これらのアプリは、独自の Android アプリの出発点として使用できます。また、既存のアプリを変更するときに参照することもできます。画像セグメンテーションのサンプルコードは GitHub でホストされています。
以降のセクションでは、カテゴリマスクを使用した画像セグメンテーション アプリについて説明します。
コードをダウンロードする
次の手順では、git コマンドライン ツールを使用してサンプルコードのローカルコピーを作成する方法を示します。
サンプルコードをダウンロードするには:
- 次のコマンドを使用して、git リポジトリのクローンを作成します。
git clone https://github.com/google-ai-edge/mediapipe-samples
- 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成し、Image Segmenter サンプルアプリのファイルのみが含まれるようにします。
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/image_segmentation/android
サンプルコードのローカル バージョンを作成したら、Android Studio にプロジェクトをインポートしてアプリを実行できます。手順については、Android の設定ガイドをご覧ください。
主要コンポーネント
次のファイルには、この画像セグメンテーションのサンプル アプリケーションの重要なコードが含まれています。
- ImageSegmenterHelper.kt - 画像セグメンテーション タスクを初期化し、モデルを処理して選択を委任します。
- CameraFragment.kt - カメラのユーザー インターフェースとコントロール コードを提供します。
- GalleryFragment.kt - 画像ファイルや動画ファイルを選択するためのユーザー インターフェースと制御コードを提供します。
- OverlayView.kt - セグメンテーション結果を処理し、書式設定します。
セットアップ
このセクションでは、イメージ セグメンテーションを使用するための開発環境とコード プロジェクトを設定する際の主な手順について説明します。プラットフォームのバージョン要件など、MediaPipe タスクを使用するための開発環境の設定に関する一般的な情報については、Android の設定ガイドをご覧ください。
依存関係
画像セグメンテーションでは com.google.mediapipe:tasks-vision
ライブラリを使用します。この依存関係を Android アプリ開発プロジェクトの build.gradle
ファイルに追加します。次のコードを使用して、必要な依存関係をインポートします。
dependencies {
...
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
モデル
MediaPipe Image Segmenter タスクには、このタスクと互換性のあるトレーニング済みモデルが必要です。画像セグメンテーションで使用可能なトレーニング済みモデルの詳細については、タスクの概要のモデル セクションをご覧ください。
モデルを選択してダウンロードし、プロジェクト ディレクトリに保存します。
<dev-project-root>/src/main/assets
BaseOptions.Builder.setModelAssetPath()
メソッドを使用して、モデルで使用するパスを指定します。このメソッドは、次のセクションのコードサンプルで参照しています。
画像セグメンテーションのサンプルコードでは、setupImageSegmenter()
関数の ImageSegmenterHelper.kt
クラスでモデルが定義されています。
タスクを作成する
createFromOptions
関数を使用してタスクを作成できます。createFromOptions
関数は、マスク出力タイプなどの構成オプションを受け入れます。タスク構成の詳細については、構成オプションをご覧ください。
画像セグメンテーション タスクは、静止画像、動画ファイル、ライブ動画ストリームの入力データ型をサポートしています。タスクの作成時に、入力データ型に対応する実行モードを指定する必要があります。入力データ型のタブを選択して、そのタスクの作成方法を確認してください。
画像
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.IMAGE) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .build(); imagesegmenter = ImageSegmenter.createFromOptions(context, options);
動画
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.VIDEO) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .build(); imagesegmenter = ImageSegmenter.createFromOptions(context, options);
ライブ配信
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.LIVE_STREAM) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .setResultListener((result, inputImage) -> { // Process the segmentation result here. }) .setErrorListener((result, inputImage) -> { // Process the segmentation errors here. }) .build() imagesegmenter = ImageSegmenter.createFromOptions(context, options)
画像セグメンテーションのサンプルコードを実装すると、ユーザーは処理モードを切り替えることができます。このアプローチでは、タスク作成コードが複雑になり、実際のユースケースには適さない可能性があります。このコードは、setupImageSegmenter()
関数による ImageSegmenterHelper
クラスで確認できます。
構成オプション
このタスクには、Android アプリ用に次の構成オプションがあります。
オプション名 | 説明 | 値の範囲 | デフォルト値 |
---|---|---|---|
runningMode |
タスクの実行モードを設定します。モードは 3 つあります。 IMAGE: 単一の画像入力のモード。 VIDEO: 動画のデコードされたフレームのモード。 LIVE_STREAM: カメラからのデータなど、入力データのライブストリームのモード。このモードでは、resultListener を呼び出して、結果を非同期で受け取るリスナーをセットアップする必要があります。 |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
outputCategoryMask |
True に設定すると、出力には、uint8 画像としてセグメンテーション マスクが含まれ、各ピクセル値は最も成功したカテゴリ値を示します。 |
{True, False } |
False |
outputConfidenceMasks |
True に設定すると、出力には浮動小数点値の画像としてセグメンテーション マスクが含まれ、各浮動小数点値はカテゴリの信頼スコアマップを表します。 |
{True, False } |
True |
displayNamesLocale |
タスクのモデルのメタデータで提供される表示名に使用するラベルの言語を設定します(利用可能な場合)。英語の場合、デフォルトは en です。TensorFlow Lite Metadata Writer API を使用して、カスタムモデルのメタデータにローカライズされたラベルを追加できます。 | 言語 / 地域コード | en |
resultListener |
画像セグメンタがライブ ストリーム モードのときにセグメンテーション結果を非同期で受け取るように結果リスナーを設定します。実行モードが LIVE_STREAM に設定されている場合にのみ使用できます |
なし | なし |
errorListener |
オプションのエラーリスナーを設定します。 | なし | 未設定 |
データの準備
画像セグメントツールは、画像、動画ファイル、ライブ ストリーム動画に対応しています。このタスクは、サイズ変更、回転、値の正規化などのデータ入力の前処理を処理します。
入力画像またはフレームを画像セグメンタに渡す前に、com.google.mediapipe.framework.image.MPImage
オブジェクトに変換する必要があります。
画像
import com.google.mediapipe.framework.image.BitmapImageBuilder; import com.google.mediapipe.framework.image.MPImage; // Load an image on the user’s device as a Bitmap object using BitmapFactory. // Convert an Android’s Bitmap object to a MediaPipe’s Image object. Image mpImage = new BitmapImageBuilder(bitmap).build();
動画
import com.google.mediapipe.framework.image.BitmapImageBuilder; import com.google.mediapipe.framework.image.MPImage; // Load a video file on the user's device using MediaMetadataRetriever // From the video’s metadata, load the METADATA_KEY_DURATION and // METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them // to calculate the timestamp of each frame later. // Loop through the video and load each frame as a Bitmap object. // Convert the Android’s Bitmap object to a MediaPipe’s Image object. Image mpImage = new BitmapImageBuilder(frame).build();
ライブ配信
import com.google.mediapipe.framework.image.MediaImageBuilder; import com.google.mediapipe.framework.image.MPImage; // Create a CameraX’s ImageAnalysis to continuously receive frames // from the device’s camera. Configure it to output frames in RGBA_8888 // format to match with what is required by the model. // For each Android’s ImageProxy object received from the ImageAnalysis, // extract the encapsulated Android’s Image object and convert it to // a MediaPipe’s Image object. android.media.Image mediaImage = imageProxy.getImage() Image mpImage = new MediaImageBuilder(mediaImage).build();
画像セグメンテーションのサンプルコードでは、データの準備は ImageSegmenterHelper
クラスで segmentLiveStreamFrame()
関数によって処理されます。
タスクを実行する
使用している実行モードに応じて、異なる segment
関数を呼び出します。画像セグメンテーション関数は、入力画像またはフレーム内で識別されたセグメント領域を返します。
画像
ImageSegmenterResult segmenterResult = imagesegmenter.segment(image);
動画
// Calculate the timestamp in milliseconds of the current frame. long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count; // Run inference on the frame. ImageSegmenterResult segmenterResult = imagesegmenter.segmentForVideo(image, frameTimestampMs);
ライブ配信
// Run inference on the frame. The segmentations results will be available via // the `resultListener` provided in the `ImageSegmenterOptions` when the image // segmenter was created. imagesegmenter.segmentAsync(image, frameTimestampMs);
次の点にご留意ください。
- 動画モードまたはライブ ストリーム モードで実行する場合は、入力フレームのタイムスタンプも画像セグメンテーション タスクに渡す必要があります。
- 画像モードまたは動画モードで実行されている場合、画像セグメンテーション タスクは入力画像またはフレームの処理を完了するまで現在のスレッドをブロックします。ユーザー インターフェースがブロックされないように、処理はバックグラウンド スレッドで実行します。
- ライブ ストリーム モードで実行されている場合、画像セグメンテーション タスクは現在のスレッドをブロックせず、すぐに結果を返します。入力フレームの処理が完了するたびに、検出結果とともに結果リスナーを呼び出します。画像セグメンテーション タスクが別のフレームの処理でビジー状態のときに
segmentAsync
関数が呼び出された場合、このタスクは新しい入力フレームを無視します。
画像セグメンテーションのサンプルコードでは、segment
関数が ImageSegmenterHelper.kt
ファイルで定義されています。
結果を処理して表示する
推論を実行すると、画像セグメンテーション タスクはセグメンテーション タスクの結果を含む ImageSegmenterResult
オブジェクトを返します。出力の内容は、タスクを構成したときに設定した outputType
によって異なります。
次のセクションでは、このタスクからの出力データの例を示します。
カテゴリの信頼度
次の図は、カテゴリの信頼マスクのタスク出力を可視化したものです。信頼度マスクの出力には、[0, 1]
間の浮動小数点値が含まれます。
元の画像とカテゴリの信頼度マスクの出力。Pascal VOC 2012 データセットのソース画像。
カテゴリの値
次の画像は、カテゴリ値のマスクのタスク出力を可視化したものです。カテゴリマスクの範囲は [0, 255]
で、各ピクセル値は、モデル出力で最も優れたカテゴリ インデックスを表します。優先カテゴリ インデックスは、モデルが認識できるカテゴリの中で最も高いスコアを持ちます。
元の画像とカテゴリマスクの出力。Pascal VOC 2012 データセットのソース画像。