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

1. 始める前に

ML Kit は、Google のオンデバイス機械学習の機能を Android アプリや iOS アプリとして提供するモバイル SDK です。強力でありながら使いやすい Vision API と Natural Language API を使用して、アプリの一般的な課題を解決したり、まったく新しいユーザー エクスペリエンスを作成したりできます。これらはすべて Google の最高水準の ML モデルを基盤としており、無料でご利用いただけます。

ML Kit の API はすべてデバイス上で実行されるため、ライブカメラ ストリームを処理するようなリアルタイムのユースケースで使用できます。つまり、この機能はオフラインでも利用できます。

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

作成するアプリの概要

この Codelab では、ML Kit を使用して Android アプリを作成します。アプリは ML Kit のオブジェクト検出とトラッキング 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 オブジェクトの検出とトラッキング 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 ツールバーの [実行](execute.png)をクリックします。

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

Android デバイスでアプリが起動するはずです。このファイルには、写真を撮影したり、プリセット画像を選択したりして、この Codelab で作成するオブジェクト検出とトラッキングのパイプラインに渡すためのボイラープレート コードが含まれています。コードを記述する前に、アプリを少し見てみましょう。

まず、下部に次の操作を行うためのボタンc6d965d639c3646.png)があります。

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

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

この操作を数回繰り返して、その仕組みを確認します。

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

2 つ目は、3 つのプリセット画像から選択できることです。これらの画像は、Android エミュレータで実行している場合に、後で物体検出コードをテストするために使用できます。

3 つのプリセット画像から画像を選択します。画像が拡大表示されていることを確認します。

1dd41b3ec978f1d9.png

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

このステップでは、画像内のオブジェクトを検出する機能をスターター アプリに追加します。前のステップで見たように、スターター アプリにはデバイスのカメラアプリで写真を撮るためのボイラープレート コードが含まれています。Android エミュレータで 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 のツールバーで [実行](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 つのオブジェクトを検出しました。

  • カテゴリは、[Food] と [Home good] です。
  • 2 番目のクラスは不明なため、カテゴリは返されません。
  • trackingId なし(シングル イメージ検出モードのため)。
  • boundingBox 長方形内の位置(例:(481, 2021)~(2426, 3376))
  • 1 つ目は食べ物である可能性が高い(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 ユーティリティ メソッドの出力例を次に示します。

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 つのカテゴリしか認識できません。ナイフ、フォーク、ボトルも認識できません。オンデバイスの機械学習 - オブジェクト検出の学習プログラムの他の Codelab で、カスタムモデルをトレーニングする方法をご確認ください。

学習した内容

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

次のステップ

  • ML Kit ODT を使用して、より多くの画像とライブ動画で検出と分類の精度とパフォーマンスを体験できます
  • オンデバイスの ML - オブジェクト検出の学習プログラムで、カスタムモデルをトレーニングする方法を確認する
  • 独自の Android アプリで ML Kit ODT を適用する

詳細