diff --git a/build.gradle b/build.gradle index 1ce28c8..178aaae 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { // 4.1.0-alpha10 or above and Android Studio 4.1 Canary 10 or above is required for // TensorFlow Lite / Machine Learning (ML) binding - classpath 'com.android.tools.build:gradle:4.1.0-rc03' + classpath 'com.android.tools.build:gradle:7.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } diff --git a/finish/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt b/finish/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt index a2279f8..6572c8b 100644 --- a/finish/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt +++ b/finish/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt @@ -50,7 +50,7 @@ import java.util.concurrent.Executors import org.tensorflow.lite.gpu.CompatibilityList // Constants -private const val MAX_RESULT_DISPLAY = 3 // Maximum number of results displayed +private const val MAX_RESULT_DISPLAY = 1 // Maximum number of results displayed private const val TAG = "TFL Classify" // Name for logging private const val REQUEST_CODE_PERMISSIONS = 999 // Return code after asking for permission private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA) // permission needed diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f96a208..b15eab5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -19,4 +19,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip diff --git a/start/build.gradle b/start/build.gradle index c128a6e..4b9e9fc 100644 --- a/start/build.gradle +++ b/start/build.gradle @@ -55,6 +55,7 @@ android { // Enable data binding buildFeatures{ dataBinding = true + mlModelBinding true } } @@ -66,6 +67,9 @@ dependencies { implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' + implementation 'org.tensorflow:tensorflow-lite-support:0.1.0-rc1' + implementation "androidx.recyclerview:recyclerview:1.1.0" + implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0-rc1' // Import for CameraX def camerax_version = "1.0.0-beta10" @@ -78,7 +82,7 @@ dependencies { implementation "androidx.activity:activity-ktx:1.1.0" // TODO 5: Optional GPU Delegates - + implementation 'org.tensorflow:tensorflow-lite-gpu:2.3.0' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.2' diff --git a/start/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt b/start/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt index 40fb036..38d7286 100644 --- a/start/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt +++ b/start/src/main/java/org/tensorflow/lite/examples/classification/MainActivity.kt @@ -39,15 +39,19 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.lifecycle.Observer import androidx.recyclerview.widget.RecyclerView +import org.tensorflow.lite.examples.classification.ml.FlowerModel import org.tensorflow.lite.examples.classification.ui.RecognitionAdapter import org.tensorflow.lite.examples.classification.util.YuvToRgbConverter import org.tensorflow.lite.examples.classification.viewmodel.Recognition import org.tensorflow.lite.examples.classification.viewmodel.RecognitionListViewModel +import org.tensorflow.lite.gpu.CompatibilityList +import org.tensorflow.lite.schema.Model +import org.tensorflow.lite.support.image.TensorImage import java.util.concurrent.Executors import kotlin.random.Random // Constants -private const val MAX_RESULT_DISPLAY = 3 // Maximum number of results displayed +private const val MAX_RESULT_DISPLAY = 1 // Maximum number of results displayed private const val TAG = "TFL Classify" // Name for logging private const val REQUEST_CODE_PERMISSIONS = 999 // Return code after asking for permission private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA) // permission needed @@ -209,8 +213,22 @@ class MainActivity : AppCompatActivity() { // TODO 1: Add class variable TensorFlow Lite Model // Initializing the flowerModel by lazy so that it runs in the same thread when the process // method is called. + private val flowerModel: FlowerModel by lazy { + // TODO 6. Optional GPU acceleration + val compatList = CompatibilityList() + + val options = if (compatList.isDelegateSupportedOnThisDevice) { + Log.d(TAG, "This device is GPU compatible ") + org.tensorflow.lite.support.model.Model.Options.Builder().setDevice(org.tensorflow.lite.support.model.Model.Device.GPU).build() + } else { + Log.d(TAG, "This device is GPU incompatible ") + org.tensorflow.lite.support.model.Model.Options.Builder().setNumThreads(4).build() + } + FlowerModel.newInstance(ctx,options) + } + + - // TODO 6. Optional GPU acceleration override fun analyze(imageProxy: ImageProxy) { @@ -218,15 +236,20 @@ class MainActivity : AppCompatActivity() { val items = mutableListOf() // TODO 2: Convert Image to Bitmap then to TensorImage + val tfImage = TensorImage.fromBitmap(toBitmap(imageProxy)) // TODO 3: Process the image using the trained model, sort and pick out the top results - + val outputs = flowerModel.process(tfImage).probabilityAsCategoryList.apply { + sortByDescending { it.score } + }.take(MAX_RESULT_DISPLAY) // TODO 4: Converting the top probability items into a list of recognitions - - // START - Placeholder code at the start of the codelab. Comment this block of code out. - for (i in 0 until MAX_RESULT_DISPLAY){ - items.add(Recognition("Fake label $i", Random.nextFloat())) + for (output in outputs){ + items.add(Recognition(output.label, output.score)) } + // START - Placeholder code at the start of the codelab. Comment this block of code out. +// for (i in 0 until MAX_RESULT_DISPLAY){ +// items.add(Recognition("Fake label $i", Random.nextFloat())) +// } // END - Placeholder code at the start of the codelab. Comment this block of code out. // Return the result diff --git a/start/src/main/ml/FlowerModel.tflite b/start/src/main/ml/FlowerModel.tflite new file mode 100644 index 0000000..0ccd5fe Binary files /dev/null and b/start/src/main/ml/FlowerModel.tflite differ