Android 画像分類ガイド

MediaPipe 画像分類タスクを使用すると、画像の分類を実行できます。このタスクを使用して、トレーニング時に定義された一連のカテゴリの中から画像が何を表しているかを特定できます。ここでは、画像分類器を使用する方法について説明します。 Android アプリと一緒です。ここで説明するコードサンプルは、 オン GitHub

このタスクの実例は、ウェブデモで確認できます。 機能、モデル、構成オプションの詳細については、 概要をご覧ください。

サンプルコード

MediaPipe Tasks のサンプルコードは、画像分類器の単純な実装です。 アプリこの例では、物理的な Android デバイスのカメラを使用して、 オブジェクトを連続的に分類できます。また、画像と動画を使用して 静的にオブジェクトを分類できます。

独自の Android アプリの出発点としてアプリを使用することも、アプリ自体に言及することもできます。 変更する際の注意点があります。画像分類器のサンプルコードは GitHub

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

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

<ph type="x-smartling-placeholder">

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

  1. 次のコマンドを使用して Git リポジトリのクローンを作成します。
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成します。 そのため、Image Classifier サンプルアプリのファイルのみになります。
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/android
    

サンプルコードのローカル バージョンを作成したら、プロジェクトをインポートできます。 アプリを実行します。手順については、次をご覧ください: Android 向けセットアップ ガイド

主要コンポーネント

次のファイルには、この画像に不可欠なコードが含まれています。 分類のサンプル アプリケーション:

セットアップ

このセクションでは、開発環境をセットアップする主な手順と 画像分類器を使用するコード プロジェクトです一般的な情報については、 MediaPipe タスクを使用するための開発環境の設定 プラットフォーム バージョンの要件については、 Android の設定ガイド

<ph type="x-smartling-placeholder">

依存関係

画像分類器は com.google.mediapipe:tasks-vision ライブラリを使用します。こちらの build.gradle ファイルに依存関係を追加して、 Android アプリ開発プロジェクト。必要な依存関係をインポートする 次のコードを使用します。

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

モデル

MediaPipe 画像分類器タスクには、これと互換性のあるトレーニング済みモデルが必要です。 タスクを実行します。画像分類器で使用可能なトレーニング済みモデルについて詳しくは、以下をご覧ください。 タスクの概要のモデル セクションをご覧ください。

モデルを選択してダウンロードし、プロジェクト ディレクトリに保存します。

<dev-project-root>/src/main/assets

BaseOptions.Builder.setModelAssetPath() メソッドを使用してパスを指定する 使用されます。このメソッドは、次のコードサンプルで参照されています。 。

画像分類器のサンプルコード モデルは ImageClassifierHelper.kt で定義されています。 表示されます。

タスクを作成する

タスクを作成するには、createFromOptions 関数を使用します。「 createFromOptions 関数は、実行などの構成オプションを受け入れます。 モード、表示名のロケール、結果の最大数、信頼度のしきい値、 カテゴリの許可リストまたは拒否リストが含まれますリソースの構成について 構成の概要をご覧ください。

画像分類タスクは、静止画像、動画ファイル、 ストリーミング動画にも対応しています対応する実行モードを指定する必要があります。 入力データ型を指定します。対応するタブを選択してください タスクの作成方法と推論の実行方法を確認できます。

画像

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

動画

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

ライブ配信

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

画像分類器のコード実装例では、 処理モードを選択できますこのアプローチでは、タスク作成コードが複雑になり、 ユースケースに適さない場合がありますこのコードは 次の setupImageClassifier() 関数: ImageClassifierHelper.kt 表示されます。

構成オプション

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

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

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

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

LIVE_STREAM: 入力のライブ配信のモード カメラからのデータなどです。このモードでは、resultListener は 結果を受け取るリスナーを設定するために呼び出されます。 使用できます。
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocale 指定された表示名に使うラベルの言語を設定します。 タスクのモデルのメタデータ(利用可能な場合)。デフォルトは en です。 英語。カスタムモデルのメタデータにローカライズされたラベルを追加できます。 TensorFlow Lite Metadata Writer API を使用 言語 / 地域コード en
maxResults オプションの上位スコアの分類結果の最大数を設定します。 戻ります。<0 の場合、利用可能な結果がすべて返されます。 正の数 -1
scoreThreshold 予測スコアのしきい値を設定します。このしきい値は、 モデル メタデータ(存在する場合)この値を下回る結果は拒否されます。 任意の浮動小数点数 未設定
categoryAllowlist 許可するカテゴリ名のオプション リストを設定します。空でない場合、 カテゴリ名がこのセットにない分類結果は、 フィルタで除外されます重複または不明なカテゴリ名は無視されます。 このオプションは categoryDenylist とは相互に排他的であり、 どちらの結果もエラーになります 任意の文字列 未設定
categoryDenylist 許可されていないカテゴリ名のオプション リストを設定します。条件 空でない場合、カテゴリ名がこのセットに含まれている分類結果はフィルタされます できます。重複または不明なカテゴリ名は無視されます。このオプションは categoryAllowlist と排他的であり、両方を使用するとエラーになります。 任意の文字列 未設定
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 users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes 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 videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. Youll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

ライブ配信

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames 
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis, 
// extract the encapsulated Androids Image object and convert it to 
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

画像分類器のサンプル コードです。データの準備は、 ImageClassifierHelper.kt 表示されます。

タスクを実行する

実行モードに対応する classify 関数を呼び出して、推論をトリガーできます。Image Classifier API は、入力画像またはフレーム内のオブジェクトの可能なカテゴリを返します。

画像

ImageClassifierResult classifierResult = imageClassifier.classify(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.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

ライブ配信

// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(image, frameTimestampMs);
    

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

  • 動画モードまたはライブ配信モードで実行する場合は、 入力フレームのタイムスタンプを画像分類タスクに渡します。
  • 画像モードまたは動画モードで実行している場合、画像分類タスクは 入力画像の処理が完了するまで、現在のスレッドをブロックします。 クリックします。ユーザー インターフェースがブロックされないように、 使用します。
  • ライブ ストリーム モードで実行している場合、画像分類タスクはブロックしない すぐに戻ります。このメソッドは、 完了するたびに、その検出結果が 表示されます。画像分類器の実行時に classifyAsync 関数が呼び出された場合 タスクが別のフレームの処理でビジー状態の場合、タスクは新しい入力フレームを無視します。

画像分類器のサンプルコード。classify 関数は、 ImageClassifierHelper.kt 表示されます。

結果の処理と表示

推論を実行すると、画像分類タスクは、入力画像またはフレーム内のオブジェクトの可能なカテゴリのリストを含む ImageClassifierResult オブジェクトを返します。

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

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

この結果は、Bird Classifier を実行して取得されました。 日付:

画像分類器のサンプル コードであるClassificationResultsAdapter ClassificationResultsAdapter.kt 結果を処理:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}