ML Kit を使用して画像内のオブジェクトを検出する: Android

1. 始める前に

ML Kit は、Google のオンデバイス機械学習の専門知識を Android および iOS アプリで利用できるようにするモバイル SDK です。Vision API と Natural Language API の強力かつシンプルを使用して、アプリの一般的な課題を解決したり、まったく新しいユーザー エクスペリエンスを作成したりできます。これらはすべて Google の最高水準の ML モデルを活用したものであり、無料で提供されています。

ML Kit の API はすべてデバイス上で実行されるため、たとえばライブカメラ ストリームをリアルタイムで処理できます。これは、その機能がオフラインで利用できることも意味します。

この Codelab では、既存の画像のオブジェクト検出とトラッキング(ODT)を既存の Android アプリに追加する簡単な手順について説明します。この Codelab では、ML Kit の ODT を使用する際のショートカットをご紹介します。

作成するアプリの概要

この Codelab では、ML Kit を使用して Android アプリを作成します。アプリでは、ML Kit Object Detection API と Tracking API を使用して特定の画像内のオブジェクトを検出します。最終的に、右側の画像のようなものが表示されます。

学習内容

  • ML Kit SDK を Android アプリに統合する方法
  • ML Kit オブジェクトの検出とトラッキング API

必要なもの

  • 最新バージョンの Android Studio(v4.1.2 以降)
  • Android Studio エミュレータまたは物理 Android デバイス
  • サンプルコード
  • Kotlin による Android 開発の基本的な知識

この Codelab では、主に ML Kit を使用します。直接関係のない概念やコードは便宜的な内容であり、そのままコピー&ペーストすれば問題ないようになっています。

2. 設定する

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

次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。

ダウンロードした zip ファイルを解凍すると、ルートフォルダ(mlkit-android-main)が展開され、必要なリソースがすべて揃います。この Codelab では、object-detection サブディレクトリ内のソースのみが必要です。

mlkit-android リポジトリの object-detection サブディレクトリには 2 つのディレクトリがあります。

  • android_studio_folder.pngstarter: この Codelab で土台として使うコードを元に、
  • android_studio_folder.pngfinal: 完成したサンプルアプリの完成したコードです。

3. ML Kit Object Detection and Tracking API をプロジェクトに追加する

Android Studio にアプリをインポートする

まず、スターター アプリを Android Studio にインポートしましょう。

Android Studio を開き、[Import Project (Gradle, Eclipse ADT, etc.)] を選択して、前にダウンロードしたソースコードから starter フォルダを選択します。

7c0f27882a2698ac.png

ML Kit のオブジェクト検出とトラッキングの依存関係を追加する

ML Kit の依存関係を使用すると、ML Kit ODT SDK をアプリに統合できます。プロジェクトの app/build.gradle ファイルの末尾に次の行を追加します。

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

プロジェクトと Gradle ファイルを同期する

すべての依存関係をアプリで使用できるようにするには、この時点でプロジェクトを Gradle ファイルと同期する必要があります。

Android Studio のツールバーで [Sync Project with Gradle Files](b451ab2d04d835f9.png)を選択します。

(このボタンが無効になっている場合は、リポジトリ全体ではなくstarter/app/build.gradle のみをインポートしてください)。

4.スターター アプリを実行する

これでプロジェクトを Android Studio にインポートし、ML Kit のオブジェクト検出とトラッキングの依存関係を追加できました。これで、アプリを初めて実行できるようになりました。

USB 経由で Android デバイスをホストに接続するか、Android Studio エミュレータを起動して、Android Studio ツールバーの [Run](execute.png)をクリックします。

アプリを実行して実行する

アプリが Android デバイスで起動します。このライブラリにはボイラープレート コードが含まれています。このコードを使用して、写真撮影やプリセット画像の選択を行い、この Codelab で作成するオブジェクト検出およびトラッキング パイプラインにフィードできます。コードを記述する前に、アプリについて少し見てみましょう。

まず、下部にボタンc6d965d639c3646.png)が表示されます。

  • デバイスまたはエミュレータにカメラ機能が統合されている
  • カメラアプリで写真を撮影する
  • キャプチャした画像をスターター アプリ受信する
  • 画像を表示する

[写真を撮る] ボタンをお試しください。画面の指示に沿って写真を撮影し、承諾すると、スターター アプリ内に表示されます。をご覧ください。

何度か繰り返して、仕組みを確認します。

9ec541980dbe2d31.png Google fa8492bfc1914ff0.png

次に、3 つのプリセット画像から選択できます。Android Emulator で実行している場合は、後でこれらの画像を使用してオブジェクト検出コードをテストできます。

3 つのプリセット画像から画像を選択します。画像が大きな画像で表示されます。

1dd41b3ec978f1d9.png

5. デバイス上のオブジェクト検出を追加する

このステップでは、スターター アプリに画像内のオブジェクトを検出する機能を追加します。前のステップで説明したように、スターター アプリには、デバイスのカメラアプリで写真を撮るためのボイラープレート コードが含まれています。アプリには、Android Emulator で Codelab を実行している場合にオブジェクト検出を試行できる 3 つのプリセット画像もあります。

プリセット画像から、またはカメラアプリで写真を撮影すると、ボイラープレート コードがその画像を Bitmap インスタンスにデコードし、画面に表示します。その際、runObjectDetection メソッドを。

このステップでは、runObjectDetection メソッドにオブジェクトを追加してオブジェクト検出を行います。

画像上のオンデバイス オブジェクト検出を設定して実行する

ML Kit ODT を設定する 3 つの API の簡単なステップは 3 つだけです。

  • 画像の準備: InputImage
  • 検出オブジェクトを作成する: ObjectDetection.getClient(options)
  • 上の 2 つのオブジェクト process(image) を接続します。

これはファイル MainActivity.kt の関数 runObjectDetection(bitmap: Bitmap) 内で行います。

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

現在、関数は空です。次のステップに進み、ML Kit ODT を実装します。 その間、Android Studio は必要なインポートを追加するよう求められます。

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

ステップ 1: InputImage を作成する

ML Kit には、Bitmap から InputImage を作成するためのシンプルな API が用意されています。その後、InputImage を ML Kit API にフィードします。

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

runObjectDetection(bitmap:Bitmap) の先頭に上記のコードを追加します。

ステップ 2: 検出用インスタンスを作成する

ML Kit はビルダー設計パターンに準拠しています。構成をビルダーに渡してから、そこから検出器を取得します。構成方法は 3 つあります(この Codelab では、太字のオプションを使用します)。

  • 検出モード(単一の画像 またはストリーミング)の手続き
  • 検出モード(単一または 複数 オブジェクト検出)の手続き
  • 分類モード(オン またはオフ

この Codelab は、単一のオブジェクト(複数のオブジェクトの検出と分類)を対象としています。今すぐ追加:

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

ステップ 3: 検出器に画像をフィードする

オブジェクトの検出と分類は非同期処理で行われます。

  • 検出器に画像を送信します(process() を使用)。
  • 検出器はかなり頑張っています。
  • 検出機能はコールバックを介して結果を返します。

次のコードは、まさにこれを行います(コピーして fun runObjectDetection(bitmap:Bitmap)): 内の既存のコードに追加します)。

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

完了すると、以下が通知されます。

  • 検出されたオブジェクトの総数。検出されたオブジェクトは次のように記述されます。
  • trackingId: クロスフレームのトラッキングに使用する整数(この Codelab では使用しません)。
  • boundingBox: オブジェクトの境界ボックス。
  • labels: 検出されたオブジェクトのラベルのリスト(分類が有効な場合のみ)。
  • index(このラベルのインデックスの取得)
  • text(「ファッション グッズ」、「食品」、「家庭用品」、「場所」、「植物」などのラベルを含む)
  • confidence(0.0 ~ 1.0 の範囲の浮動小数点数。1.0 は 100% を意味します)

このコードでは、debugPrint() で検出された結果の printf のような処理を行っていることにお気づきでしょうか。

MainActivity クラスに追加します。

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

これで、検出対象の画像を受け入れる準備が整いました。

Android Studio のツールバーで [Run](execute.png)をクリックして、Codelab を実行します。プリセットの画像を選択するか、写真を撮影してから、IDE 内の logcat ウィンドウ(16bd6ea224cf8cf1.pngを確認します。

次のように表示されます。

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

これは、検出項目が 3 つのオブジェクトを参照したことを意味します。

  • カテゴリは「食品」と「家庭用品」です。
  • 2 つ目のカテゴリは不明なクラスであるため、返されるカテゴリがありません。
  • trackingId なし(単一画像検出モードであるため)。
  • boundingBox 長方形内の位置(例: (481、2021)~(2426、3376))
  • 最初の検出項目が [食品] であると確信できます(90% の信頼度。サラダです)。

技術的には、ML Kit のオブジェクト検出を動作させるために必要なのはこれだけです。 お疲れさまでした。

UI 側では、まだ作業はまだ開始段階ですが、より良い結果を得るには、UI で検出された結果(境界ボックスの描画など)を利用できます。次のステップ、後処理に進みます。検出された結果です。

6. 検出結果の後処理

前の手順では、検出された結果を logcat(シンプルかつ高速)に出力します。

このセクションでは、結果を利用して画像を作成します。

  • 画像に境界ボックスを描画する
  • カテゴリ名と信頼度を境界ボックス内に描画する

可視化ユーティリティを理解する

Codelab 内には、検出結果を可視化するためのボイラープレート コードがあります。次のユーティリティを活用して、可視化コードをシンプルにします。

  • data class BoxWithText(val box: Rect, val text: String): 可視化のためにオブジェクト検出の結果を格納するデータクラスです。box は、オブジェクトが配置されている境界ボックスです。text は、オブジェクトの境界ボックスと一緒に表示する検出結果の文字列です。
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmapこのメソッドは、オブジェクト検出の結果をdetectionResults入力bitmap変更後のコピーを返します。

drawDetectionResult ユーティリティ メソッドの出力例を次に示します。

58C6F1D4DBB00dfa.PNG

ML Kit の検出結果を可視化する

可視化ユーティリティを使用して、入力画像の上に ML Kit のオブジェクト検出結果を描画します。

debugPrint() を呼び出し、その下に次のコード スニペットを追加します。

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • まず、ML Kit の DetectedObject を解析し、可視化結果を表示する BoxWithText オブジェクトのリストを作成します。
  • 次に、drawDetectionResult ユーティリティ メソッドを使用して、入力画像の上に検出結果を描画し、画面に表示します。

実行

Android Studio のツールバーで [Run](execute.png)をクリックします。

アプリが読み込まれたら、カメラアイコン付きのボタンを押す、カメラを被写体に向ける、写真を撮影する、写真を撮影する(カメラアプリで)など、プリセットの画像を簡単にタップできます。検出結果が表示されます。最新の ML Kit の ODT を体験するには、もう一度ボタンを押すか、別の画像を何回か繰り返します。

a03109cb30d5014d.png

7. 完了

ML Kit を使用して、アプリにオブジェクト検出機能を追加しました。

  • 3 つの API で 3 つのステップ
  • 入力画像の作成
  • 検出項目を作成
  • 検出機能に画像を送信

セットアップは完了です。

モデルを拡張していくと、デフォルト モデルは 5 つのカテゴリしか認識できないことがわかります。ご覧のように、モデルはナイフ、フォーク、ボトルすら認識していません。カスタムモデルのトレーニング方法については、「オンデバイス機械学習 - オブジェクト検出学習プログラム」にある他の Codelab をご覧ください。

学習した内容

  • ML Kit のオブジェクト検出とトラッキングを Android アプリに追加する方法
  • ML Kit でデバイスのオブジェクト検出とトラッキングを使用して画像内のオブジェクトを検出する方法

次のステップ

  • ML Kit の ODT でさらに多くの画像とライブ動画を使用して、検出と分類の精度とパフォーマンスをご確認ください
  • カスタムモデルのトレーニング方法については、「デバイス上の機械学習 - オブジェクト検出の学習プログラム」をご確認ください。
  • ML Kit の ODT を独自の Android アプリに適用

詳細