オブジェクト検出タスクを使用すると、複数のクラスのオブジェクトの存在と位置を検出できます。たとえば、オブジェクト検出機能は画像内の犬を見つけることができます。以下の手順では、Android でオブジェクト検出タスクを使用する方法について説明します。これらの手順で説明するコードサンプルは GitHub で入手できます。このタスクの動作を確認するには、ウェブデモをご覧ください。このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。
サンプルコード
MediaPipe Tasks のサンプルコードは、Android 向けのオブジェクト検出アプリのシンプルな実装です。この例では、物理的な Android デバイスのカメラを使用してオブジェクトを継続的に検出します。また、デバイスのギャラリーにある画像や動画を使用して、オブジェクトを静的に検出することもできます。
このアプリは、独自の Android アプリの開始点として使用できます。また、既存のアプリを変更する際にも参照できます。オブジェクト検出のサンプルコードは GitHub でホストされています。
コードをダウンロードする
次の手順では、git コマンドライン ツールを使用してサンプルコードのローカルコピーを作成する方法について説明します。
サンプルコードをダウンロードするには:
- 次のコマンドを使用して、Git リポジトリのクローンを作成します。
git clone https://github.com/google-ai-edge/mediapipe-samples
- 必要に応じて、オブジェクト検出の例アプリのファイルのみが存在するように、スパース チェックアウトを使用するように Git インスタンスを構成します。
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/object_detection/android
サンプルコードのローカル バージョンを作成したら、プロジェクトを Android Studio にインポートしてアプリを実行できます。手順については、Android 用セットアップ ガイドをご覧ください。
主要コンポーネント
次のファイルには、Object Detector サンプル アプリケーションの重要なコードが含まれています。
- ObjectDetectorHelper.kt - オブジェクト検出を初期化し、モデルとデリゲートの選択を処理します。
- MainActivity.kt - アプリを実装し、ユーザー インターフェース コンポーネントをアセンブルします。
- OverlayView.kt - 結果を処理して表示します。
セットアップ
このセクションでは、Object Detector を使用するように開発環境とコード プロジェクトを設定する主な手順について説明します。プラットフォーム バージョンの要件など、MediaPipe タスクを使用する開発環境の設定に関する一般的な情報については、Android の設定ガイドをご覧ください。
依存関係
オブジェクト検出は com.google.mediapipe:tasks-vision
ライブラリを使用します。この依存関係を Android アプリ開発プロジェクトの build.gradle
ファイルに追加します。次のコードを使用して、必要な依存関係をインポートします。
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
モデル
MediaPipe オブジェクト検出タスクには、このタスクに対応したトレーニング済みモデルが必要です。Object Detector で使用可能なトレーニング済みモデルの詳細については、タスクの概要のモデルのセクションをご覧ください。
モデルを選択してダウンロードし、プロジェクト ディレクトリに保存します。
<dev-project-root>/src/main/assets
BaseOptions.Builder.setModelAssetPath()
メソッドを使用して、モデルで使用するパスを指定します。コード例については、次のセクションをご覧ください。
タスクを作成する
タスクを作成するには、createFromOptions
関数を使用します。createFromOptions
関数は、実行モード、表示名のロケール、結果の最大数、信頼しきい値、カテゴリの許可リストと拒否リストなどの構成オプションを受け入れます。構成オプションが指定されていない場合は、デフォルト値が使用されます。構成オプションの詳細については、構成の概要をご覧ください。
オブジェクト検出タスクは、静止画像、動画ファイル、ライブ動画ストリームの 3 つの入力データ型をサポートしています。タスクを作成するときに、入力データ型に対応する実行モードを指定する必要があります。入力データ型に対応するタブを選択して、タスクの作成方法と推論の実行方法を確認します。
画像
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.IMAGE) .setMaxResults(5) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
動画
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.VIDEO) .setMaxResults(5) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
ライブ配信
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.LIVE_STREAM) .setMaxResults(5) .setResultListener((result, inputImage) -> { // Process the detection result here. }) .setErrorListener((result, inputImage) -> { // Process the classification errors here. }) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
オブジェクト検出器のサンプルコードの実装では、ユーザーが処理モードを切り替えることができます。この方法ではタスク作成コードが複雑になり、ユースケースに適さない場合があります。このコードは、ObjectDetectorHelper
クラスの setupObjectDetector()
関数で確認できます。
設定オプション
このタスクには、Android アプリ用の次の構成オプションがあります。
オプション名 | 説明 | 値の範囲 | デフォルト値 |
---|---|---|---|
runningMode |
タスクの実行モードを設定します。モードは次の 3 つです。 IMAGE: 単一画像入力のモード。 動画: 動画のデコードされたフレームのモード。 LIVE_STREAM: カメラなどからの入力データのライブ配信モード。このモードでは、resultListener を呼び出して、結果を非同期で受信するリスナーを設定する必要があります。 |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
displayNamesLocales |
タスクのモデルのメタデータで指定されている表示名に使用するラベルの言語を設定します(利用可能な場合)。デフォルトは英語で en です。TensorFlow Lite Metadata Writer API を使用して、カスタムモデルのメタデータにローカライズされたラベルを追加できます。 |
言語 / 地域コード | en |
maxResults |
返されるスコア上位の検出結果の最大数を設定します(省略可)。 | 任意の正の数 | -1(すべての結果が返されます) |
scoreThreshold |
モデル メタデータで指定された予測スコアしきい値(存在する場合)をオーバーライドする予測スコアしきい値を設定します。この値を下回る結果は拒否されます。 | 任意の浮動小数点数 | 未設定 |
categoryAllowlist |
許可されるカテゴリ名のリスト(省略可)。空でない場合、このセットにカテゴリ名が含まれていない検出結果は除外されます。重複するカテゴリ名または不明なカテゴリ名は無視されます。このオプションは categoryDenylist とは相互に排他的であり、両方を使用するとエラーが発生します。 |
任意の文字列 | 未設定 |
categoryDenylist |
許可されないカテゴリ名のリスト(省略可)。空でない場合、このセットにカテゴリ名が含まれている検出結果は除外されます。重複するカテゴリ名または不明なカテゴリ名は無視されます。このオプションは categoryAllowlist と相互排他的であり、両方を使用するとエラーが発生します。 |
任意の文字列 | 未設定 |
resultListener |
オブジェクト検出がライブ配信モードのときに検出結果を非同期で受信するように結果リスナーを設定します。このオプションは、runningMode を LIVE_STREAM に設定した場合にのみ使用できます。 | 該当なし | 未設定 |
データの準備
入力画像またはフレームをオブジェクト検出機能に渡す前に、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 values. Use these values // 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() MPImage mpImage = new MediaImageBuilder(mediaImage).build();
オブジェクト検出器のコードサンプルでは、データの準備は detectImage()
、detectVideoFile()
、detectLivestreamFrame()
関数の ObjectDetectorHelper
クラスで処理されます。
タスクを実行する
使用するデータの種類に応じて、そのデータ型に固有の ObjectDetector.detect...()
メソッドを使用します。個々の画像には detect()
、動画ファイル内のフレームには detectForVideo()
、動画ストリームには detectAsync()
を使用します。動画ストリームで検出を行う場合は、ユーザー インターフェース スレッドがブロックされないように、検出を別のスレッドで実行してください。
次のコードサンプルは、これらのさまざまなデータモードでオブジェクト検出を実行する方法の簡単な例を示しています。
画像
ObjectDetectorResult detectionResult = objectDetector.detect(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. ObjectDetectorResult detectionResult = objectDetector.detectForVideo(image, frameTimestampMs);
ライブ配信
// Run inference on the frame. The detection results will be available // via the `resultListener` provided in the `ObjectDetectorOptions` when // the object detector was created. objectDetector.detectAsync(image, frameTimestampMs);
オブジェクト検出器のコード例では、これらの各モードの実装について詳しく説明しています。detect()
、detectVideoFile()
、detectAsync()
サンプルコードでは、ユーザーが処理モードを切り替えることができますが、ユースケースでは不要な場合があります。
次の点にご注意ください。
- 動画モードまたはライブ配信モードで実行する場合は、入力フレームのタイムスタンプを Object Detector タスクに指定する必要があります。
- 画像モードまたは動画モードで実行する場合、オブジェクト検出タスクは、入力画像またはフレームの処理が完了するまで現在のスレッドをブロックします。現在のスレッドをブロックしないように、処理をバックグラウンド スレッドで実行します。
- ライブ配信モードで実行する場合、オブジェクト検出タスクは現在のスレッドをブロックせず、すぐに返します。入力フレームの処理が完了するたびに、検出結果とともに結果リスナーが呼び出されます。オブジェクト検出タスクが別のフレームの処理でビジー状態になっているときに detect 関数が呼び出されると、新しい入力フレームは無視されます。
結果を処理して表示する
推論を実行すると、オブジェクト検出タスクは、入力画像で検出されたオブジェクトを記述する ObjectDetectorResult
オブジェクトを返します。
このタスクの出力データの例を次に示します。
ObjectDetectorResult:
Detection #0:
Box: (x: 355, y: 133, w: 190, h: 206)
Categories:
index : 17
score : 0.73828
class name : dog
Detection #1:
Box: (x: 103, y: 15, w: 138, h: 369)
Categories:
index : 17
score : 0.73047
class name : dog
次の画像は、タスク出力の可視化を示しています。
オブジェクト検出のサンプルコードは、タスクから返された検出結果を表示する方法を示しています。詳細については、OverlayView
クラスをご覧ください。