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 オブジェクト検出とトラッキング 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 エミュレータで実行している場合は、これらの画像を使用して、後でオブジェクト検出コードをテストできます。

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

1dd41b3ec978f1d9.png

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

このステップでは、画像内のオブジェクトを検出する機能をスターターアプリに追加します。前の手順で確認したように、スターターアプリには、デバイスのカメラアプリで写真を撮るためのボイラープレート コードが含まれています。また、アプリには 3 つのプリセット画像があり、Android エミュレータで 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 はビルダーの設計パターンに従います。構成をビルダーに渡し、ビルダーから検出機能を取得します。構成するオプションは 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 つのオブジェクトを検出しました。

  • カテゴリは [食品] と [家庭用品] です。
  • 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 このメソッドは、入力 bitmapdetectionResults のオブジェクト検出結果を描画し、その変更されたコピーを返します。

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 でより多くの画像やライブ動画を探索し、検出と分類の精度とパフォーマンスを体験する
  • オンデバイス ML - オブジェクト検出の学習パスウェイで、カスタムモデルをトレーニングする方法をご確認ください。
  • 独自の Android アプリに ML Kit ODT を適用する

詳細