1. 始める前に
スマートフォンのカメラを物体に向けると、その物体をオンラインで購入できる場所を検索できる Google レンズのデモをご覧になったことはありますか?同じ機能をアプリに追加する方法について学習したい場合は、この Codelab がおすすめです。これは、商品画像検索機能をモバイルアプリに組み込む方法を学ぶ学習パスウェイの一部です。
この Codelab では、商品画像検索機能の作成の最初のステップとして、画像内のオブジェクトを検出し、ユーザーが検索するオブジェクトを選択できるようにする方法を学びます。この機能は、ML Kit のオブジェクト検出とトラッキングを使用して構築します。
Vision API Product Search を使用して商品検索バックエンドを構築する方法など、残りの手順については、学習パスウェイをご覧ください。
作成するアプリの概要
|
学習内容
- ML Kit SDK を Android アプリに統合する方法
- ML Kit オブジェクト検出とトラッキング API
必要なもの
- 最新バージョンの Android Studio(v4.1.2 以降)
- Android Studio Emulator または物理的な Android デバイス
- サンプルコード
- Kotlin による Android 開発に関する基本的な知識
この Codelab では、ML Kit を中心に説明します。その他のコンセプトやコードブロックについては学習しませんが、そのままコピーして貼り付けられるようにしています。
2. セットアップする
コードをダウンロードする
次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。
ダウンロードした zip ファイルを解凍すると、ルートフォルダ(odml-pathways-main
)が展開されます。このフォルダには、必要なすべてのリソースが含まれています。この Codelab では、product-search/codelab1/android
サブディレクトリ内のソースのみを使用します。
mlkit-android リポジトリの object-detection サブディレクトリには、次の 2 つのディレクトリが含まれています。
- starter - この Codelab で作成する開始コード。
- final - 完成したサンプルアプリの完全なコード。
3. ML Kit オブジェクト検出とトラッキング API をプロジェクトに追加する
アプリを Android Studio にインポートする
まず、starter アプリを Android Studio にインポートします。
Android Studio に移動し、[Import Project (Gradle, Eclipse ADT, etc.)] を選択して、先ほどダウンロードしたソースコードから starter フォルダを選択します。
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]()を選択します。
(このボタンが無効になっている場合は、リポジトリ全体ではなく、starter/app/build.gradle のみをインポートしてください)。
4. スターター アプリを実行する
プロジェクトを Android Studio にインポートし、ML Kit のオブジェクト検出とトラッキング用の依存関係を追加したので、アプリを初めて実行する準備が整いました。
Android デバイスを USB 経由でホストに接続するか、Android Studio エミュレータを起動し、Android Studio ツールバーの実行アイコン()をクリックします。
アプリを実行して操作する
Android デバイスでアプリが起動するはずです。このファイルには、写真をキャプチャしたり、プリセット画像を選択したりして、この Codelab で作成するオブジェクト検出とトラッキング パイプラインにフィードするためのボイラープレート コードが含まれています。コードを記述する前に、アプリを少し確認します。
まず、下部にボタン()があり、
- デバイス/エミュレータに統合されているカメラアプリを起動する
- カメラアプリで写真を撮影する
- スターター アプリでキャプチャした画像を受信する
- 画像を表示する
[写真を撮る] ボタンを試してみてください。画面の指示に沿って写真を撮影し、写真を承認して、スターター アプリに表示されるかどうかを確認します。
次に、選択できる 3 つのプリセット画像があります。Android エミュレータで実行している場合は、これらの画像を使用して、後でオブジェクト検出コードをテストできます。
- 3 つのプリセット画像から画像を選択します。
- 画像が拡大表示されていることを確認します。
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 では、1 つの画像内の複数のオブジェクトの検出と分類を行います。手順は次のとおりです。
// 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()
で Logcat に出力されていることに気づいたことでしょう。これを 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 のツールバーで [実行]()をクリックして、Codelab を実行します。プリセット画像を選択するか、写真を撮影して、IDE 内の logcat ウィンドウ()を確認します。次のように表示されます。
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: Fashion good
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 には、検出結果を可視化するためのボイラープレート コードが含まれています。これらのユーティリティを利用して、ビジュアリゼーション コードを簡素化します。
class ImageClickableView
検出結果の可視化と操作に便利なユーティリティを提供する画像ビュー クラスです。fun drawDetectionResults(results: List<DetectedObject>)
このメソッドは、検出された各オブジェクトの中心に白い円を描画します。fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit))
ユーザーがタップしたオブジェクトのみを含む切り抜き画像を受け取るコールバックです。後続の Codelab では、この切り抜かれた画像を画像検索バックエンドに送信して、視覚的に類似した結果を取得します。この Codelab では、このメソッドはまだ使用しません。
ML Kit の検出結果を表示する
可視化ユーティリティを使用して、ML Kit のオブジェクト検出結果を入力画像の上に表示します。
debugPrint()
を呼び出す場所に移動し、その下に次のコード スニペットを追加します。
runOnUiThread {
viewBinding.ivPreview.drawDetectionResults(it)
}
実行する
Android Studio のツールバーで [実行]()をクリックします。
アプリが読み込まれたら、カメラアイコン付きのボタンを押してカメラを被写体に向け、写真を撮影します。撮影した写真を(カメラアプリで)承認するか、プリセットの画像を簡単にタップします。検出結果が表示されます。ボタンをもう一度押すか、別の画像を選択して数回繰り返すと、最新の ML Kit ODT を体験できます。
7. 完了
ML Kit を使用して、アプリにオブジェクト検出機能を追加しました。
- 3 つの API による 3 つのステップ
- 入力画像を作成する
- 検出項目を作成する
- 検出機能に画像を送信する
これで、使い始めることができます。
学習した内容
- ML Kit のオブジェクト検出とトラッキングを Android アプリに追加する方法
- ML Kit のデバイス上のオブジェクト検出とトラッキングを使用して画像内のオブジェクトを検出する方法
次のステップ
- 検出されたオブジェクトを商品検索バックエンドに送信して検索結果を表示する方法については、こちらの Codelab をご覧ください。
- ML Kit ODT でより多くの画像やライブ動画を探索し、検出と分類の精度とパフォーマンスを体験する
- オブジェクト検出についてさらに学習する学習パスウェイで、カスタムモデルをトレーニングする方法をご確認ください。
- オブジェクト検出の live-camera と static-image に関するマテリアル デザインの推奨事項を確認する
- 独自の Android アプリに ML Kit ODT を適用する