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 and Tracking API を使用して、指定された画像からオブジェクトを検出します。最終的に、右側の画像のようなものが表示されます。

学習内容

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

必要なもの

  • Android Studio の最新バージョン(v4.1.2 以降)
  • Android Studio Emulator または 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 のオブジェクト検出とトラッキングの依存関係を追加できました。これで、アプリを初めて実行する準備ができました。

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

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

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

まず、下部に次のボタンc6d965d639c3646.png)があります。

  • デバイス/エミュレータに組み込まれているカメラアプリを起動する
  • カメラアプリで写真を撮影する
  • スターター アプリでキャプチャした画像を受信する
  • 画像を表示する

[写真を撮る] ボタンを試します。画面の指示に沿って写真を撮影し、写真を承認して、スターター アプリ内に表示されるのを確認します。

これを数回繰り返して、効果を確認します。

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

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

3 つのプリセット画像から画像を選択します。大きなビューに画像が表示されることを確認します。

1dd41b3ec978f1d9.png

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

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

プリセット画像から画像を選択するか、カメラアプリで写真を撮影すると、ボイラープレート コードがその画像を 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 を実装する手順に進みましょう。途中で、必要なインポートを追加するように求められます。

  • 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 は Builder デザイン パターンに準拠しています。構成をビルダーに渡して、そこから検出項目を取得します。構成するオプションは 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() を使用)。
  • 検出機能は相当な役割を担っています。
  • Detector はコールバックを介して結果を報告します。

次のコードではこれを行います(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 ツールバーの実行アイコン(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))
  • 検出項目は、1 番目のものが Food(信頼度 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 このメソッドは、入力 bitmap に対してオブジェクト検出の結果を detectionResults に描画し、変更されたコピーを返します。

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

58c6f1d4ddb00dfa.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 ツールバーの実行アイコン(execute.png)をクリックします。

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

a03109cb30d5014d.png

7. 完了

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

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

これだけで運用を開始できます。

次に進むにつれて、モデルを強化できます。デフォルトのモデルは 5 つのカテゴリしか認識できないことがわかります。つまり、モデルはナイフ、フォーク、ボトルさえ認識していません。カスタムモデルをトレーニングする方法については、オンデバイス ML - オブジェクト検出の学習プログラムにある別の Codelab をご確認ください。

学習した内容

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

次のステップ

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

詳細