1. 始める前に
この Codelab では、以下を含む一連のトレーニング画像を使用してカスタム オブジェクト検出モデルをトレーニングします。TFLite モデルメーカーを作成し、Android アプリにモデルをデプロイTFLite タスク ライブラリをご覧ください。このチュートリアルでは、次のことを行います。
- 食事の画像から材料を検出する Android アプリを作成します。
- TFLite の事前トレーニング済みオブジェクト検出モデルを統合し、モデルが検出できる制限を確認する。
- salad と TFLite Model Maker というカスタム データセットを使用して、食事の材料やコンポーネントを検出するカスタム オブジェクト検出モデルをトレーニングします。
- TFLite Task Library を使用してカスタムモデルを Android アプリにデプロイします。
最後に、以下の画像のようなものを作成します。
要件
この Codelab は、機械学習の経験がある経験豊富なモバイル デベロッパーを対象としています。以下について把握しておく必要があります。
- Kotlin と Android Studio を使用した Android 開発
- 基本的な Python 構文
学習内容
- TFLite Model Maker を使用してカスタム オブジェクト検出モデルをトレーニングする方法。
- TFLite Task Library を使用して TFLite オブジェクト検出モデルをデプロイする方法
必要なもの
- 最新バージョンの Android Studio(v4.2 以降)
- Android Studio エミュレータまたは物理 Android デバイス
- サンプルコード
- Kotlin による Android 開発の基本的な知識
2. オブジェクト検出
オブジェクト検出は、デジタル画像内のオブジェクトを検出して位置を特定できる一連のコンピュータ ビジョン タスクです。画像または動画ストリームが与えられると、オブジェクト検出モデルは、存在する可能性のある一連のオブジェクトを識別し、画像内のそれらの位置に関する情報を提供できます。
TensorFlow は、トレーニング済みのモバイル最適化モデルを提供し、自動車やオレンジなどの一般的な物体を検出します。事前トレーニング済みのモデルを、わずか数行のコードでモバイルアプリに統合できます。ただし、特徴的なカテゴリやユニークなカテゴリでオブジェクトを検出する必要がある場合もあります。それには、独自のトレーニング画像を収集し、独自のオブジェクト検出モデルをトレーニングしてデプロイする必要があります。
TensorFlow Lite
TensorFlow Lite は、Android や iOS モバイル デバイスなどのエッジデバイスで機械学習モデルを実行するために最適化されたクロス プラットフォームの機械学習ライブラリです。
TensorFlow Lite は、実際には ML Kit 内で機械学習モデルを実行するために使用されるコアエンジンです。TensorFlow Lite エコシステムには、モバイル デバイスでの機械学習モデルのトレーニングとデプロイを容易にする 2 つのコンポーネントがあります。
- Model Maker は数人のコードだけで独自のデータで TensorFlow Lite モデルを簡単にトレーニングできる Python ライブラリです。機械学習の専門知識は必要ありません。
- Task Library は、わずか数行のコードでモバイルアプリに TensorFlow Lite モデルを簡単にデプロイできる、クロス プラットフォーム ライブラリです。
この Codelab では、TFLite に焦点を当てます。TFLite とオブジェクト検出に関連しない概念やコードブロックについては説明せず、そのままコピーして貼り付けてください。
3. 設定する
コードをダウンロードする
次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。
ダウンロードした zip ファイルを解凍すると、ルートフォルダ(odml-pathways-main
)が展開され、必要なリソースがすべて揃います。この Codelab では、object-detection/codelab2/android
サブディレクトリ内のソースのみが必要です。
object-detection/codelab2/android
リポジトリの android
サブディレクトリには、次の 2 つのディレクトリがあります。
- starter: この Codelab で土台として使うコードを元に、
- final: 完成したサンプルアプリの完成したコードです。
スターター アプリをインポートする
まず、スターター アプリを Android Studio にインポートします。
- Android Studio を開き、[Import Project (Gradle, Eclipse ADT, etc.)] を選択します。
- 先ほどダウンロードしたソースコードから
starter
フォルダを開きます。
すべての依存関係をアプリで使用できるようにするには、インポート プロセスの完了後に、プロジェクトを Gradle ファイルと同期する必要があります。
- Android Studio のツールバーで [Sync Project with Gradle Files]()を選択します。starter/app/build.gradle をインポートする
スターター アプリを実行する
Android Studio にプロジェクトがインポートされたので、アプリを初めて実行する準備が整いました。
USB 経由で Android デバイスをパソコンに接続するか、Android Studio エミュレータを起動して、Android Studio ツールバーの [Run]()をクリックします。
4.スターター アプリを理解する
この Codelab では、シンプルに機械学習の焦点に集中できるように、いくつかのボイラープレート コードを使用します。
- デバイスのカメラを使用して写真を撮影できる。
- Android Emulator でオブジェクト検出を試すためのストック画像がいくつか含まれています。
- オブジェクト検出の結果を入力ビットマップに描画できる便利なメソッドがあります。
これらのメソッドのほとんどは、アプリのスケルトンで操作します。
fun runObjectDetection(bitmap: Bitmap)
このメソッドは、プリセットの画像を選択するか、写真を撮影するときに呼び出されます。bitmap
は、オブジェクト検出の入力画像です。後ほど、この Codelab でオブジェクト検出コードを追加します。data class DetectionResult(val boundingBoxes: Rect, val text: String)
: 可視化のためのオブジェクト検出の結果を表すデータクラスです。boundingBoxes
は、オブジェクトを配置する矩形です。text
は、オブジェクトの境界ボックスと一緒に表示する検出結果の文字列です。fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<DetectionResult>): Bitmap
このメソッドは、オブジェクト検出の結果をdetectionResults
入力bitmap
変更後のコピーを返します。
drawDetectionResult
ユーティリティ メソッドの出力例を次に示します。
5. デバイス上のオブジェクト検出を追加する
次に、一般的なオブジェクトを検知できる事前トレーニング済み TFLite モデルをスターター アプリに統合し、プロトタイプを作成します。
事前トレーニング済みの TFLite オブジェクト検出モデルをダウンロードする
TensorFlow Hub には、利用可能なオブジェクト検出モデルがいくつかあります。この Codelab では、COCO 2017 データセットでトレーニングされ、TFLite 用に最適化され、モバイル CPU、GPU でのパフォーマンスを考慮した EfficientDet-Lite オブジェクト検出モデルをダウンロードします。 、EdgeTPU があります。
次に、TFLite Task Library を使用して、事前トレーニング済みの TFLite モデルをスターター アプリに統合します。 TFLite Task Library を使用すると、モバイル向けに最適化された機械学習モデルをモバイルアプリに簡単に統合できます。オブジェクト検出、画像分類、テキスト分類など、一般的な多くの機械学習ユースケースに対応しています。TFLite モデルをロードして、数行のコードで実行できます。
モデルをスターター アプリに追加する
- ダウンロードしたモデルをスターター アプリの
assets
フォルダにコピーします。フォルダは、Android Studio の [Project] ナビゲーション パネルにあります。
- ファイル名を
model.tflite
とします。
Gradle ファイル タスク ライブラリの依存関係を更新する
app/build.gradle
ファイルに移動し、次の行を dependencies
構成に追加します。
implementation 'org.tensorflow:tensorflow-lite-task-vision:0.3.1'
プロジェクトと Gradle ファイルを同期する
すべての依存関係をアプリで使用できるようにするには、この時点でプロジェクトを Gradle ファイルと同期する必要があります。Android Studio のツールバーで [Sync Project with Gradle Files]()を選択します。
(このボタンが無効になっている場合は、リポジトリ全体ではなく starter/app/build.gradle のみをインポートしてください)。
画像上のオンデバイス オブジェクト検出を設定して実行する
次の 3 つの簡単なステップで、オブジェクト検出モデルを読み込んで実行するための 3 つの API を設定できます。
- 画像 / ストリームを準備する:
TensorImage
- 検出オブジェクトを作成する:
ObjectDetector
- 上の 2 つのオブジェクト
detect(image)
を接続します。
この処理は、ファイル MainActivity.kt
の関数 runObjectDetection(bitmap: Bitmap)
で行います。
/**
* TFLite Object Detection Function
*/
private fun runObjectDetection(bitmap: Bitmap) {
//TODO: Add object detection code here
}
現在、関数は空です。TFLite オブジェクト検出機能を実装するには、次の手順に進みます。途中で、Android Studio から必要なインポートを追加するよう求められます。
org.tensorflow.lite.support.image.TensorImage
org.tensorflow.lite.task.vision.detector.ObjectDetector
イメージ オブジェクトを作成する
この Codelab で使用する画像は、デバイス上のカメラから取得するか、アプリの UI で選択したプリセット画像から取得されます。入力画像は Bitmap
形式にデコードされ、runObjectDetection
メソッドに渡されます。
TFLite には、Bitmap
から TensorImage
を作成するためのシンプルな API が用意されています。runObjectDetection(bitmap:Bitmap)
の先頭に次のコードを追加します。
// Step 1: create TFLite's TensorImage object
val image = TensorImage.fromBitmap(bitmap)
Detector インスタンスを作成する
TFLite タスク ライブラリは、ビルダー設計パターンに従います。構成にビルダーを渡し、そこからビルダーを取得します。オブジェクト検出の感度を調整するなど、いくつかのオプションを構成できます。
- 最大結果(モデルが検出すべき最大オブジェクト数)
- スコアしきい値(検出されたオブジェクトを返すオブジェクト検出の信頼度)
- label label/denylist(事前定義されたリストでオブジェクトを許可または拒否)
TFLite モデルのファイル名と構成オプションを指定して、オブジェクト検出インスタンスを初期化します。
// Step 2: Initialize the detector object
val options = ObjectDetector.ObjectDetectorOptions.builder()
.setMaxResults(5)
.setScoreThreshold(0.5f)
.build()
val detector = ObjectDetector.createFromFileAndOptions(
this, // the application context
"model.tflite", // must be same as the filename in assets folder
options
)
検出機能に画像をフィードする
fun runObjectDetection(bitmap:Bitmap)
に次のコードを追加します。これにより、画像が検出器にフィードされます。
// Step 3: feed given image to the model and print the detection result
val results = detector.detect(image)
完了すると、Detection
のリストが返されます。各リストには、画像内でモデルが検出したオブジェクトに関する情報が含まれます。各オブジェクトは次のように記述されています。
boundingBox
: オブジェクトが存在することと、画像内でのその位置を宣言する長方形categories
: オブジェクトの種類と、検出結果に対するモデルの信頼度。このモデルは複数のカテゴリを返します。信頼度が最も高いカテゴリが最初に選ばれます。label
: オブジェクト カテゴリの名前。classificationConfidence
:0.0 ~ 1.0 の浮動小数点数。1.0 は 100% を表します。
検出結果を印刷する
fun runObjectDetection(bitmap:Bitmap)
に次のコードを追加します。これにより、オブジェクト検出の結果が Logcat に出力されます。
// Step 4: Parse the detection result and show it
debugPrint(results)
次に、次の debugPrint()
メソッドを MainActivity
クラスに追加します。
private fun debugPrint(results : List<Detection>) {
for ((i, obj) in results.withIndex()) {
val box = obj.boundingBox
Log.d(TAG, "Detected object: ${i} ")
Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
for ((j, category) in obj.categories.withIndex()) {
Log.d(TAG, " Label $j: ${category.label}")
val confidence: Int = category.score.times(100).toInt()
Log.d(TAG, " Confidence: ${confidence}%")
}
}
}
これでオブジェクト検出の準備ができました。 Android Studio のツールバーで [Run]()をクリックして、アプリをコンパイルして実行します。アプリがデバイスに表示されたら、プリセットの画像のいずれかをタップして、オブジェクト検出機能を起動します。IDE 内の [Logcat] ウィンドウ*(* *)* に、次のように表示されます。
D/TFLite-ODT: Detected object: 0
D/TFLite-ODT: boundingBox: (0.0, 15.0) - (2223.0,1645.0)
D/TFLite-ODT: Label 0: dining table
D/TFLite-ODT: Confidence: 77%
D/TFLite-ODT: Detected object: 1
D/TFLite-ODT: boundingBox: (702.0, 3.0) - (1234.0,797.0)
D/TFLite-ODT: Label 0: cup
D/TFLite-ODT: Confidence: 69%
これは、検出器が 2 つのオブジェクトを検出したことを示します。1 つ目は、
- オブジェクトは(0、15)~(2223、1645)の長方形の中にあります
- ラベルはダイニング テーブルです
- モデルは、1 つ目がダイニング テーブル(77%)であると確信しています
技術的には、TFLite Task ライブラリを動作させるために必要なのはこれだけです。 これで完了です。
ただし、UI 側には、まだ出発点があります。検出結果を後処理して、UI で返された結果を活用する必要があります。
6. 検出結果を入力画像に描画する
前の手順では、検出結果を logcat
にシンプルかつ迅速に出力しました。このステップでは、以下の目的で、スターター アプリですでに実装されているユーティリティ メソッドを利用します。
- 画像に境界ボックスを描画する
- カテゴリと信頼度を境界ボックス内に描画する
debugPrint(results)
呼び出しを次のコード スニペットに置き換えます。
val resultToDisplay = results.map {
// Get the top-1 category and craft the display text
val category = it.categories.first()
val text = "${category.label}, ${category.score.times(100).toInt()}%"
// Create a data object to display the detection result
DetectionResult(it.boundingBox, text)
}
// Draw the detection result on the bitmap and show it.
val imgWithResult = drawDetectionResult(bitmap, resultToDisplay)
runOnUiThread {
inputImageView.setImageBitmap(imgWithResult)
}
- Android Studio のツールバーで [Run]()をクリックします。
- アプリが読み込まれたら、いずれかのプリセット画像をタップして検出結果を確認します。
ご自分の写真で試してみませんか?[写真を撮影] ボタンをタップして、周囲の物体の写真を撮ります。
7. カスタム オブジェクト検出モデルをトレーニングする
前のステップでは、トレーニング済みの TFLite オブジェクト検出モデルを Android アプリに統合し、サンプル画像からボウルやダイニング テーブルなどの一般的な物体を検出できることを学びました。ただし、目的は画像内の食材の検出であるため、一般的な物体検出はユースケースに適していません。検出したい要素を含むトレーニング データセットを使用して、カスタム オブジェクト検出モデルをトレーニングします。
カスタム データセットには、独自のカスタム モデルをトレーニングするために使用できる画像とラベルが含まれています。Open Images Dataset V4 の画像を使用して作成されました。
Colaboratory
次に、Google Colab に移動して、カスタムモデルをトレーニングしましょう。
カスタムモデルのトレーニングには 30 分ほどかかります。
急いでいる場合は、提供されたデータセットで事前トレーニング済みのモデルをダウンロードして、次のステップに進むことができます。
8. カスタム TFLite モデルを Android アプリに統合する
以上でサラダ検出モデルをトレーニングして統合し、一般的なオブジェクト検出機能(具体的にはサラダ検出機能)にアプリを変換しました。
- サラダ TFLite モデルを
assets
フォルダにコピーします。新しいモデルにsalad.tflite
という名前を付けます。
MainActivity.kt
ファイルを開き、ObjectDetector
初期化コードを見つけます。- EfficientDet-Lite モデル(
model.tflite
)をサラダモデル(salad.tflite
)に置き換える
val detector = ObjectDetector.createFromFileAndOptions(
this, // the application context
"salad.tflite", // must be same as the filename in assets folder
options
)
- Android Studio のツールバーで [Run]()をクリックし、新しいモデルでアプリを再実行します。これにより、アプリはチーズ、サラダ、焼き菓子を認識できるようになりました。
9. 完了
TFLite を使用してカスタムモデルをトレーニングし、アプリにオブジェクト検出機能を追加しました。セットアップは完了です。
学習した内容
- TensorFlow Hub で事前トレーニング済み TFLite オブジェクト検出モデルを見つける方法
- TFLite Task Library を使用して反論検出モデルを Android アプリに統合する方法
- TFLite Model Maker を使用してカスタム オブジェクト検出モデルをトレーニングする方法
次の手順
- Firebase を使用して TFLite モデルのデプロイを強化する
- モデルをトレーニングして独自のモデルをトレーニングする
- 独自の Android アプリでオブジェクト検出を適用する