オブジェクト検出タスクを使用すると、複数のクラスのオブジェクトの存在と位置を検出できます。たとえば、オブジェクト検出で画像内の犬を検出できます。ここでは、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 の設定ガイドをご覧ください。
主要コンポーネント
次のファイルには、オブジェクト検出サンプル アプリケーションの重要なコードが含まれています。
- ObjectDetectorHelper.kt - オブジェクト検出を初期化し、モデルを処理して選択を委任します。
- MainActivity.kt - アプリを実装し、ユーザー インターフェース コンポーネントを組み立てます。
- OverlayView.kt - 結果を処理して表示します。
セットアップ
このセクションでは、Object Detector を使用するための開発環境とコード プロジェクトを設定する際の主な手順について説明します。プラットフォームのバージョン要件など、MediaPipe タスクを使用するための開発環境の設定に関する一般的な情報については、Android の設定ガイドをご覧ください。
依存関係
Object Detector は 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: 単一の画像入力のモード。 VIDEO: 動画のデコードされたフレームのモード。 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 に設定した場合にのみ使用できます。 | 該当なし | 未設定 |
データの準備
入力の画像またはフレームは、Object Detector に渡す前に 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()
を使用します。動画ストリームに対して検出を実行する場合は、ユーザー インターフェース スレッドがブロックされないように、検出を別のスレッドで実行してください。
次のコードサンプルは、さまざまなデータモードで Object Detector を実行する簡単な例を示しています。
画像
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()
)。サンプルコードを使用すると、ユースケースでは不要な処理モードを切り替えることができます。
次の点にご留意ください。
- 動画モードまたはライブ ストリーム モードで実行する場合は、入力フレームのタイムスタンプもオブジェクト検出タスクに渡す必要があります。
- 画像モードまたは動画モードで実行されている場合、オブジェクト検出タスクは入力画像またはフレームの処理を完了するまで現在のスレッドをブロックします。現在のスレッドがブロックされないように、処理はバックグラウンド スレッドで実行します。
- ライブ ストリーム モードで実行する場合、オブジェクト検出タスクは現在のスレッドをブロックせず、すぐに結果を返します。入力フレームの処理が完了するたびに、検出結果とともに結果リスナーを呼び出します。オブジェクト検出タスクが別のフレームの処理でビジー状態のときに検出関数が呼び出された場合、新しい入力フレームは無視されます。
結果を処理して表示する
推論を実行すると、オブジェクト検出タスクは、入力画像で検出されたオブジェクトを記述する 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
クラスをご覧ください。